diff --git a/HISTORY b/HISTORY index 13d6d40..3fc8b38 100644 --- a/HISTORY +++ b/HISTORY @@ -7,7 +7,7 @@ VDR Plugin 'femon' Revision History 2004-02-23: Version 0.0.1b -- Fixed cThread to work under vdr-1.2.6. +- Fixed cThread initialization to work under vdr-1.2.6. 2004-02-26: Version 0.0.2 @@ -22,3 +22,10 @@ VDR Plugin 'femon' Revision History - Translation only update: Fixed 'Deutsch' (Thanks to Olaf Henkel @ VDRPortal). Added 'Italiano' (Thanks to Sean Carlos). + +2004-03-03: Version 0.0.3 + +- Redesigned the user interface. +- Transponder information is now available in advanced display mode: + Press 'OK' key to switch between the simple and the advanced display mode. +- Moved bitrate calculation to it's own thread for improved accurancy. diff --git a/README b/README index 04eec4c..805cc96 100644 --- a/README +++ b/README @@ -11,34 +11,33 @@ See the file COPYING for license information. Requirements: Ph.D. in Astro Physics and preferably a six-pack waiting in a fridge. +Never trust a Klingon. Description: -DVB Frontend Status Monitor is a plugin that displays a few signal quality parameters -of the tuned channel on your screen. You can zap through all your channels and the -plugin should be monitoring always the right frontend *fingers crossed*. A short -message is shown at the bottom line to help the DVB card identification after each -channel switch and OK press. +DVB Frontend Status Monitor is a plugin that displays some signal information +parameters of the current tuned channel on OSD. You can zap through all your +channels and the plugin should be monitoring always the right frontend. The +transponder information is also available in advanced display mode. User can +switch between simple and advanced display modes by pressing 'OK' key. -The plugin is based on a neat console frontend status monitor application called -'femon' by Johannes Stezenbach (see DVB-apps/szap/femon.c for -further information). The other parts of plugin code are borrowed from the -excellent OSD Picture-In-Picture plugin by Sascha Volkenandt -and Andreas Regel . Props to Sascha for being brave -enough to test this piece of junk and ofcourse for german translations. The bitrate -calculation algorithm is originally copied from dvbstream application by Dave Chapman -. +The plugin is based on a neat console frontend status monitor application called +'femon' by Johannes Stezenbach (see DVB-apps/szap/femon.c +for further information). The other parts of plugin code are borrowed from the +excellent 'OSD Picture-In-Picture' plugin by Sascha Volkenandt +and Andreas Regel . The bitrate calculation algorithm +originates from the 'dvbstream' application by Dave Chapman . Shortcomings / Todo list: - The current version is a kind of Proof In Concept to replace the old 'tech - patch', so the internals will be eventually rewritten... if I'll find some - spare time. -- The plugin supports only those DVB cards with _one_ frontend (do any cards with - multiple frontends even exist?), because I haven't yet figured howto do it without - patching the VDR core. + patch', and it's now eating many unnecessary cpu clock cycles - this will be + fixed later... +- The plugin supports only those DVB cards with _one_ frontend (do any cards + with multiple frontends even exist?), because I haven't yet figured howto do + it without patching the VDR core. - Sometimes (read always) ttxtsubs plugin messes up the OSD - user should disable - ttxtsubs, but closing and reopening the femon plugin might help temporarily as well. - Btw., this same thing happens with OSDTeletext plugin too :) -- The plugin GUI is designed for small fonts, so stable vdr-1.2.6 users should consider - the ElchiAIO4a+ patch to maximize the *wow* effect :) + ttxtsubs, but closing and reopening the femon plugin might help temporarily as + well. Btw., this same thing happens with OSDTeletext plugin too :) +- The plugin GUI is designed for _small fonts_, so stable vdr-1.2.6 users should + consider a small font patch (e.g. ElchiAIO4a) to maximize the visual effect :) diff --git a/femon.c b/femon.c index e60d811..f629831 100644 --- a/femon.c +++ b/femon.c @@ -1,5 +1,5 @@ /* - * A Frontend Monitor plugin for the Video Disk Recorder + * Frontend Status Monitor plugin for the Video Disk Recorder * * See the README file for copyright information and how to reach the author. * @@ -63,11 +63,14 @@ cOsdObject *cPluginFemon::MainMenuAction(void) bool cPluginFemon::SetupParse(const char *Name, const char *Value) { // Parse your own setup parameters and store their values. - if (!strcasecmp(Name, "HideMenu")) femonConfig.hidemenu = atoi(Value); - else if (!strcasecmp(Name, "Position")) femonConfig.position = atoi(Value); - else if (!strcasecmp(Name, "Interval")) femonConfig.interval = atoi(Value); - else if (!strcasecmp(Name, "RedLimit")) femonConfig.redlimit = atoi(Value); - else if (!strcasecmp(Name, "GreenLimit")) femonConfig.greenlimit = atoi(Value); + if (!strcasecmp(Name, "HideMenu")) femonConfig.hidemenu = atoi(Value); + else if (!strcasecmp(Name, "DisplayMode")) femonConfig.displaymode = atoi(Value); + else if (!strcasecmp(Name, "Position")) femonConfig.position = atoi(Value); + else if (!strcasecmp(Name, "RedLimit")) femonConfig.redlimit = atoi(Value); + else if (!strcasecmp(Name, "GreenLimit")) femonConfig.greenlimit = atoi(Value); + else if (!strcasecmp(Name, "UpdateInterval")) femonConfig.updateinterval = atoi(Value); + else if (!strcasecmp(Name, "ShowBitRate")) femonConfig.showbitrate = atoi(Value); + else if (!strcasecmp(Name, "CalcInterval")) femonConfig.calcinterval = atoi(Value); else return false; @@ -76,20 +79,51 @@ bool cPluginFemon::SetupParse(const char *Name, const char *Value) cMenuFemonSetup::cMenuFemonSetup(void) { - Add(new cMenuEditBoolItem(tr("Hide Mainmenu Entry"), &femonConfig.hidemenu, tr("no"), tr("yes"))); - Add(new cMenuEditBoolItem(tr("Position"), &femonConfig.position, tr("bottom"), tr("top"))); - Add(new cMenuEditIntItem( tr("Update Interval [0.1s]"), &femonConfig.interval, 5, 50)); - Add(new cMenuEditIntItem( tr("Red Limit [%]"), &femonConfig.redlimit, 1, 50)); - Add(new cMenuEditIntItem( tr("Green Limit [%]"), &femonConfig.greenlimit, 51, 100)); + Setup(); +} + +void cMenuFemonSetup::Setup(void) +{ + int current = Current(); + + Clear(); + Add(new cMenuEditBoolItem( tr("Hide Mainmenu Entry"), &femonConfig.hidemenu, tr("no"), tr("yes"))); + Add(new cMenuEditBoolItem( tr("Default Display Mode"), &femonConfig.displaymode, tr("simple"), tr("advanced"))); + Add(new cMenuEditBoolItem( tr("Position"), &femonConfig.position, tr("bottom"), tr("top"))); + Add(new cMenuEditIntItem( tr("Red Limit [%]"), &femonConfig.redlimit, 1, 50)); + Add(new cMenuEditIntItem( tr("Green Limit [%]"), &femonConfig.greenlimit, 51, 100)); + Add(new cMenuEditIntItem( tr("OSD Update Interval [0.1s]"), &femonConfig.updateinterval, 1, 100)); + Add(new cMenuEditBoolItem( tr("Bitrate Calculation"), &femonConfig.showbitrate, tr("no"), tr("yes"))); + if (femonConfig.showbitrate) + Add(new cMenuEditIntItem(tr("Calculation Interval [0.1s]"), &femonConfig.calcinterval, 1, 100)); + + SetCurrent(Get(current)); + Display(); } void cMenuFemonSetup::Store(void) { - SetupStore("HideMenu", femonConfig.hidemenu); - SetupStore("Position", femonConfig.position); - SetupStore("Interval", femonConfig.interval); - SetupStore("RedLimit", femonConfig.redlimit); - SetupStore("GreenLimit", femonConfig.greenlimit); + SetupStore("HideMenu", femonConfig.hidemenu); + SetupStore("Position", femonConfig.position); + SetupStore("DisplayMode", femonConfig.displaymode); + SetupStore("RedLimit", femonConfig.redlimit); + SetupStore("GreenLimit", femonConfig.greenlimit); + SetupStore("UpdateInterval", femonConfig.updateinterval); + SetupStore("ShowBitRate", femonConfig.showbitrate); + SetupStore("CalcInterval", femonConfig.calcinterval); +} + +eOSState cMenuFemonSetup::ProcessKey(eKeys Key) +{ + int oldShowbitrate = femonConfig.showbitrate; + + eOSState state = cMenuSetupPage::ProcessKey(Key); + + if (Key != kNone && (femonConfig.showbitrate != oldShowbitrate)) { + Setup(); + } + + return state; } cMenuSetupPage *cPluginFemon::SetupMenu(void) diff --git a/femon.h b/femon.h index 3ca73e0..a2ef116 100644 --- a/femon.h +++ b/femon.h @@ -1,11 +1,19 @@ +/* + * Frontend Status Monitor plugin for the Video Disk Recorder + * + * See the README file for copyright information and how to reach the author. + * + * $Id$ + */ + #ifndef __FEMON_H #define __FEMON_H #include -static const char *VERSION = "0.0.2c"; -static const char *DESCRIPTION = "DVB Signal Quality Monitor (OSD)"; -static const char *MAINMENUENTRY = "Signal Quality"; +static const char *VERSION = "0.0.3"; +static const char *DESCRIPTION = "DVB Signal Information Monitor (OSD)"; +static const char *MAINMENUENTRY = "Signal Information"; class cPluginFemon : public cPlugin { private: @@ -27,11 +35,14 @@ public: }; class cMenuFemonSetup : public cMenuSetupPage { + private: + virtual void Setup(void); + protected: + virtual eOSState ProcessKey(eKeys Key); + virtual void Store(void); public: cMenuFemonSetup(void); - protected: - virtual void Store(void); -}; + }; #endif //__FEMON_H diff --git a/femoncfg.c b/femoncfg.c index 95daee1..1f61b92 100644 --- a/femoncfg.c +++ b/femoncfg.c @@ -1,5 +1,5 @@ /* - * A Frontend Monitor plugin for the Video Disk Recorder + * Frontend Status Monitor plugin for the Video Disk Recorder * * See the README file for copyright information and how to reach the author. * @@ -12,9 +12,12 @@ cFemonConfig femonConfig; cFemonConfig::cFemonConfig(void) { - hidemenu = 0; - position = 1; - interval = 10; - redlimit = 33; - greenlimit = 66; + hidemenu = 0; + displaymode = 0; + position = 1; + redlimit = 33; + greenlimit = 66; + updateinterval = 5; + showbitrate = 1; + calcinterval = 20; } diff --git a/femoncfg.h b/femoncfg.h index e9339ef..6fddcb8 100644 --- a/femoncfg.h +++ b/femoncfg.h @@ -1,3 +1,11 @@ +/* + * Frontend Status Monitor plugin for the Video Disk Recorder + * + * See the README file for copyright information and how to reach the author. + * + * $Id$ + */ + #ifndef __FEMONCFG_H #define __FEMONCFG_H @@ -6,10 +14,13 @@ struct cFemonConfig public: cFemonConfig(void); int hidemenu; + int displaymode; int position; - int interval; int redlimit; int greenlimit; + int updateinterval; + int showbitrate; + int calcinterval; }; extern cFemonConfig femonConfig; diff --git a/femoni18n.c b/femoni18n.c index 498f95b..159bc5b 100644 --- a/femoni18n.c +++ b/femoni18n.c @@ -1,5 +1,5 @@ /* - * A Frontend Monitor plugin for the Video Disk Recorder + * Frontend Status Monitor plugin for the Video Disk Recorder * * See the README file for copyright information and how to reach the author. * @@ -9,10 +9,10 @@ #include "femoni18n.h" const tI18nPhrase Phrases[] = { - { "DVB Signal Quality Monitor (OSD)", // English - "DVB Signalqualitäts-Anzeige (OSD)", // Deutsch + { "DVB Signal Information Monitor (OSD)", // English + "DVB Signal Informationsanzeige (OSD)", // Deutsch "", // Slovenski - "Visualizzazione della qualita' del segnale DVB (OSD)", // Italiano + "", // Italiano "", // Nederlands "", // Português "", // Français @@ -29,10 +29,10 @@ const tI18nPhrase Phrases[] = { "" // ÀãááÚØÙ #endif }, - { "Signal Quality", // English - "Signalqualität", // Deutsch + { "Signal Information", // English + "Signalinformationen", // Deutsch "", // Slovenski - "Qualita' del segnale", // Italiano + "", // Italiano "", // Nederlands "", // Português "", // Français @@ -67,6 +67,66 @@ const tI18nPhrase Phrases[] = { "", // Català #if VDRVERSNUM >= 10300 "" // ÀãááÚØÙ +#endif + }, + { "Default Display Mode", // English + "Standard Anzeigemodus", // Deutsch + "", // Slovenski + "", // Italiano + "", // Nederlands + "", // Português + "", // Français + "", // Norsk + "Oletus näyttömoodi", // suomi + "", // Polski + "", // Español + "", // ÅëëçíéêÜ + "", // Svenska + "", // Romaneste + "", // Magyar + "", // Català +#if VDRVERSNUM >= 10300 + "" // ÀãááÚØÙ +#endif + }, + { "simple", // English + "einfach", // Deutsch + "", // Slovenski + "", // Italiano + "", // Nederlands + "", // Português + "", // Français + "", // Norsk + "suppea", // suomi + "", // Polski + "", // Español + "", // ÅëëçíéêÜ + "", // Svenska + "", // Romaneste + "", // Magyar + "", // Català +#if VDRVERSNUM >= 10300 + "" // ÀãááÚØÙ +#endif + }, + { "advanced", // English + "fortgeschritten", // Deutsch + "", // Slovenski + "", // Italiano + "", // Nederlands + "", // Português + "", // Français + "", // Norsk + "laaja", // suomi + "", // Polski + "", // Español + "", // ÅëëçíéêÜ + "", // Svenska + "", // Romaneste + "", // Magyar + "", // Català +#if VDRVERSNUM >= 10300 + "" // ÀãááÚØÙ #endif }, { "Hide Mainmenu Entry", // English @@ -89,15 +149,55 @@ const tI18nPhrase Phrases[] = { "" // ÀãááÚØÙ #endif }, - { "Update Interval [0.1s]", // English - "Aktualisierung alle [0.1s]", // Deutsch + { "OSD Update Interval [0.1s]", // English + "OSD Updateintervall [0.1s]", // Deutsch "", // Slovenski "Intervallo di aggiornamento [0.1s]", // Italiano "", // Nederlands "", // Português "", // Français "", // Norsk - "Päivitystaajuus [0.1s]", // suomi + "Näytön päivitysväli [0.1s]", // suomi + "", // Polski + "", // Español + "", // ÅëëçíéêÜ + "", // Svenska + "", // Romaneste + "", // Magyar + "", // Català +#if VDRVERSNUM >= 10300 + "" // ÀãááÚØÙ +#endif + }, + { "Bitrate Calculation", // English + "Bitratenberechnung", // Deutsch + "", // Slovenski + "", // Italiano + "", // Nederlands + "", // Português + "", // Français + "", // Norsk + "Bittinopeuden laskenta", // suomi + "", // Polski + "", // Español + "", // ÅëëçíéêÜ + "", // Svenska + "", // Romaneste + "", // Magyar + "", // Català +#if VDRVERSNUM >= 10300 + "" // ÀãááÚØÙ +#endif + }, + { "Calculation Interval [0.1s]", // English + "Berechnungsintervall [0.1s]", // Deutsch + "", // Slovenski + "", // Italiano + "", // Nederlands + "", // Português + "", // Français + "", // Norsk + "Laskennan päivitysväli [0.1s]", // suomi "", // Polski "", // Español "", // ÅëëçíéêÜ @@ -147,6 +247,86 @@ const tI18nPhrase Phrases[] = { "", // Català #if VDRVERSNUM >= 10300 "" // ÀãááÚØÙ +#endif + }, + { "Transponder Information", // English + "Transponderinformation", // Deutsch + "", // Slovenski + "", // Italiano + "", // Nederlands + "", // Português + "", // Français + "", // Norsk + "Transponderin tiedot", // suomi + "", // Polski + "", // Español + "", // ÅëëçíéêÜ + "", // Svenska + "", // Romaneste + "", // Magyar + "", // Català +#if VDRVERSNUM >= 10300 + "" // ÀãááÚØÙ +#endif + }, + { "Satellite Card", // English + "Satellitenkarte", // Deutsch + "", // Slovenski + "", // Italiano + "", // Nederlands + "", // Português + "", // Français + "", // Norsk + "Satelliittikortti", // suomi + "", // Polski + "", // Español + "", // ÅëëçíéêÜ + "", // Svenska + "", // Romaneste + "", // Magyar + "", // Català +#if VDRVERSNUM >= 10300 + "" // ÀãááÚØÙ +#endif + }, + { "Cable Card", // English + "Kabelkarte", // Deutsch + "", // Slovenski + "", // Italiano + "", // Nederlands + "", // Português + "", // Français + "", // Norsk + "Kaapelikortti", // suomi + "", // Polski + "", // Español + "", // ÅëëçíéêÜ + "", // Svenska + "", // Romaneste + "", // Magyar + "", // Català +#if VDRVERSNUM >= 10300 + "" // ÀãááÚØÙ +#endif + }, + { "Terrestial Card", // English + "Terrestrische Karte", // Deutsch + "", // Slovenski + "", // Italiano + "", // Nederlands + "", // Português + "", // Français + "", // Norsk + "Terrestiaalikortti", // suomi + "", // Polski + "", // Español + "", // ÅëëçíéêÜ + "", // Svenska + "", // Romaneste + "", // Magyar + "", // Català +#if VDRVERSNUM >= 10300 + "" // ÀãááÚØÙ #endif }, { NULL } diff --git a/femoni18n.h b/femoni18n.h index 653f98d..3c5cc6d 100644 --- a/femoni18n.h +++ b/femoni18n.h @@ -1,3 +1,11 @@ +/* + * Frontend Status Monitor plugin for the Video Disk Recorder + * + * See the README file for copyright information and how to reach the author. + * + * $Id$ + */ + #ifndef __FEMONI18N_H #define __FEMONI18N_H diff --git a/femonosd.c b/femonosd.c index 601a4d8..d0fa7bd 100644 --- a/femonosd.c +++ b/femonosd.c @@ -1,48 +1,75 @@ /* - * A Frontend Monitor plugin for the Video Disk Recorder + * Frontend Status Monitor plugin for the Video Disk Recorder * * See the README file for copyright information and how to reach the author. * * $Id$ */ +#include #include "femoncfg.h" +#include "femoni18n.h" #include "femonreceiver.h" #include "femonosd.h" -#define FE_DEVICE "/dev/dvb/adapter%d/frontend%d" +#if (VDRVERSNUM < 10300) && !defined(ELCHIAIOVERSION) +#warning You should consider using the small fonts! +#endif + +#define FE_DEVICE "/dev/dvb/adapter%d/frontend%d" #define CHANNELINPUT_TIMEOUT 1000 -#define CHANNELINFO_TIMEOUT 5000 -#define OSDHEIGHT 5 + +#define OSDWIDTH 46 +#define OSDINFOHEIGHT 11 +#define OSDGAPHEIGHT 1 +#define OSDSTATUSHEIGHT 6 + +#define OSDSTATUSCOL1 1 +#define OSDSTATUSCOL2 10 +#define OSDSTATUSCOL3 17 +#define OSDSTATUSCOL4 32 + +#define OSDSTATUSLOCK 1 +#define OSDSTATUSSIGN 9 +#define OSDSTATUSCARR 19 +#define OSDSTATUSVITE 30 +#define OSDSTATUSSYNC 40 + +#define OSDINFOLCOL1 1 +#define OSDINFOLCOL2 14 +#define OSDINFOLCOL3 23 +#define OSDINFOLCOL4 36 cFemonOsd::cFemonOsd(void) #if VDRVERSNUM >= 10300 :cOsdObject(true), cThread("femon plugin") #else -:cOsdObject(true), cThread() +:cOsdObject(true) #endif { //printf("cFemonOsd::cFemonOsd()\n"); m_Osd = NULL; - m_Window = -1; + m_InfoWindow = -1; + m_StatusWindow = -1; m_Receiver = NULL; m_Frontend = -1; m_Active = false; m_Number = 0; m_InputTime = 0; - m_InfoTime = 0; - m_Width = Setup.OSDwidth * cOsd::CellWidth(); - m_Height = OSDHEIGHT * cOsd::LineHeight(); - m_Xpos = (720 - m_Width) / 2; - m_Ypos = (576 - Setup.OSDheight * cOsd::LineHeight()) / 2 + ( femonConfig.position ? 0 : (Setup.OSDheight - OSDHEIGHT) * cOsd::LineHeight()); + m_Signal = 0; + m_SNR = 0; + m_BER = 0; + m_UNC = 0; + m_DisplayMode = femonConfig.displaymode; + m_Mutex = new cMutex(); } - + cFemonOsd::~cFemonOsd(void) { //printf("cFemonOsd::~cFemonOsd()\n"); if (m_Active) { m_Active = false; - Cancel(3); + Cancel(5); } if (m_Receiver) delete m_Receiver; @@ -50,97 +77,326 @@ cFemonOsd::~cFemonOsd(void) delete m_Osd; } +void cFemonOsd::DrawStatusWindow(void) +{ + cMutexLock lock(m_Mutex); + //printf("cFemonOsd::DrawStatusWindow()\n"); + char buf[128]; + int snr = m_SNR / 655; + int signal = m_Signal / 655; + int lines = 0; + + if (m_Osd) { +#if (VDRVERSNUM >= 10300) || defined(ELCHIAIOVERSION) + eDvbFont OldFont = m_Osd->SetFont(fontSml); +#endif + m_Osd->Clear(m_StatusWindow); + snprintf(buf, sizeof(buf), "%d%s %s", m_Number ? m_Number : Channels.GetByNumber(cDevice::CurrentChannel())->Number(), m_Number ? "-" : "", Channels.GetByNumber(cDevice::CurrentChannel())->Name()); + m_Osd->Fill(0, femonConfig.position ? 0 : (OSDINFOHEIGHT + OSDGAPHEIGHT) * cOsd::LineHeight(), OSDWIDTH * cOsd::CellWidth(), femonConfig.position ? cOsd::LineHeight() - 1 : (OSDINFOHEIGHT + OSDGAPHEIGHT + 1) * cOsd::LineHeight() - 1, clrWhite, m_StatusWindow); + m_Osd->Text(OSDSTATUSCOL1 * cOsd::CellWidth(), femonConfig.position ? 0 : (OSDINFOHEIGHT + OSDGAPHEIGHT + 0) * cOsd::LineHeight(), buf, clrBlack, clrWhite, m_StatusWindow); + lines++; + if (signal > 0) { + signal = (OSDWIDTH * cOsd::CellWidth()) * signal / 100; + m_Osd->Fill(0, femonConfig.position ? lines * cOsd::LineHeight() + 3 : (OSDINFOHEIGHT + OSDGAPHEIGHT + lines) * cOsd::LineHeight() + 3, min(((OSDWIDTH * cOsd::CellWidth()) * femonConfig.redlimit / 100), signal), femonConfig.position ? (lines + 1) * cOsd::LineHeight() - 3 : (OSDINFOHEIGHT + OSDGAPHEIGHT + lines + 1) * cOsd::LineHeight() - 3, clrRed, m_StatusWindow); + if (signal > ((OSDWIDTH * cOsd::CellWidth()) * femonConfig.redlimit / 100)) { + m_Osd->Fill(((OSDWIDTH * cOsd::CellWidth()) * femonConfig.redlimit / 100), femonConfig.position ? lines * cOsd::LineHeight() + 3 : (OSDINFOHEIGHT + OSDGAPHEIGHT + lines) * cOsd::LineHeight() + 3, min(((OSDWIDTH * cOsd::CellWidth()) * femonConfig.greenlimit / 100), signal), femonConfig.position ? (lines + 1) * cOsd::LineHeight() - 3 : (OSDINFOHEIGHT + OSDGAPHEIGHT + lines + 1) * cOsd::LineHeight() - 3, clrYellow, m_StatusWindow); + } + if (signal > ((OSDWIDTH * cOsd::CellWidth()) * femonConfig.greenlimit / 100)) { + m_Osd->Fill(((OSDWIDTH * cOsd::CellWidth()) * femonConfig.greenlimit / 100), femonConfig.position ? lines * cOsd::LineHeight() + 3 : (OSDINFOHEIGHT + OSDGAPHEIGHT + lines) * cOsd::LineHeight() + 3, signal, femonConfig.position ? (lines + 1) * cOsd::LineHeight() - 3 : (OSDINFOHEIGHT + OSDGAPHEIGHT + lines + 1) * cOsd::LineHeight() - 3, clrGreen, m_StatusWindow); + } + } + lines++; + if (snr > 0) { + snr = (OSDWIDTH * cOsd::CellWidth()) * snr / 100; + m_Osd->Fill(0, femonConfig.position ? lines * cOsd::LineHeight() + 3 : (OSDINFOHEIGHT + OSDGAPHEIGHT + lines) * cOsd::LineHeight() + 3, min(((OSDWIDTH * cOsd::CellWidth()) * femonConfig.redlimit / 100), snr), femonConfig.position ? (lines + 1) * cOsd::LineHeight() - 3 : (OSDINFOHEIGHT + OSDGAPHEIGHT + lines + 1) * cOsd::LineHeight() - 3, clrRed, m_StatusWindow); + if (snr > ((OSDWIDTH * cOsd::CellWidth()) * femonConfig.redlimit / 100)) { + m_Osd->Fill(((OSDWIDTH * cOsd::CellWidth()) * femonConfig.redlimit / 100), femonConfig.position ? lines * cOsd::LineHeight() + 3 : (OSDINFOHEIGHT + OSDGAPHEIGHT + lines) * cOsd::LineHeight() + 3, min(((OSDWIDTH * cOsd::CellWidth()) * femonConfig.greenlimit / 100), snr), femonConfig.position ? (lines + 1) * cOsd::LineHeight() - 3 : (OSDINFOHEIGHT + OSDGAPHEIGHT + lines + 1) * cOsd::LineHeight() - 3, clrYellow, m_StatusWindow); + } + if (snr > ((OSDWIDTH * cOsd::CellWidth()) * femonConfig.greenlimit / 100)) { + m_Osd->Fill(((OSDWIDTH * cOsd::CellWidth()) * femonConfig.greenlimit / 100), femonConfig.position ? lines * cOsd::LineHeight() + 3 : (OSDINFOHEIGHT + OSDGAPHEIGHT + lines) * cOsd::LineHeight() + 3, snr, femonConfig.position ? (lines + 1) * cOsd::LineHeight() - 3 : (OSDINFOHEIGHT + OSDGAPHEIGHT + lines + 1) * cOsd::LineHeight() - 3, clrGreen, m_StatusWindow); + } + } + lines++; + snprintf(buf, sizeof(buf), "STR: %04x", m_Signal); + m_Osd->Text(OSDSTATUSCOL1 * cOsd::CellWidth(), femonConfig.position ? lines * cOsd::LineHeight() : (OSDINFOHEIGHT + OSDGAPHEIGHT + lines) * cOsd::LineHeight(), buf, clrWhite, clrBackground, m_StatusWindow); + snprintf(buf, sizeof(buf), "(%2d%%)", m_Signal / 655); + m_Osd->Text(OSDSTATUSCOL2 * cOsd::CellWidth(), femonConfig.position ? lines * cOsd::LineHeight() : (OSDINFOHEIGHT + OSDGAPHEIGHT + lines) * cOsd::LineHeight(), buf, clrWhite /*signal < femonConfig.redlimit ? clrRed : signal < femonConfig.greenlimit ? clrYellow : clrGreen*/, clrBackground, m_StatusWindow); + snprintf(buf, sizeof(buf), "BER: %08x", m_BER); + m_Osd->Text(OSDSTATUSCOL3 * cOsd::CellWidth(), femonConfig.position ? lines * cOsd::LineHeight() : (OSDINFOHEIGHT + OSDGAPHEIGHT + lines) * cOsd::LineHeight(), buf, clrWhite, clrBackground, m_StatusWindow); + if (m_Receiver) snprintf(buf, sizeof(buf), "Video: %.2f Mbit/s",m_Receiver->VideoBitrate()); + else snprintf(buf, sizeof(buf), "Video: --- Mbit/s"); + m_Osd->Text(OSDSTATUSCOL4 * cOsd::CellWidth(), femonConfig.position ? lines * cOsd::LineHeight() : (OSDINFOHEIGHT + OSDGAPHEIGHT + lines) * cOsd::LineHeight(), buf, clrWhite, clrBackground, m_StatusWindow); + lines++; + snprintf(buf, sizeof(buf), "SNR: %04x", m_SNR); + m_Osd->Text(OSDSTATUSCOL1 * cOsd::CellWidth(), femonConfig.position ? lines * cOsd::LineHeight() : (OSDINFOHEIGHT + OSDGAPHEIGHT + lines) * cOsd::LineHeight(), buf, clrWhite, clrBackground, m_StatusWindow); + snprintf(buf, sizeof(buf), "(%2d%%)", m_SNR / 655); + m_Osd->Text(OSDSTATUSCOL2 * cOsd::CellWidth(), femonConfig.position ? lines * cOsd::LineHeight() : (OSDINFOHEIGHT + OSDGAPHEIGHT + lines) * cOsd::LineHeight(), buf, clrWhite /*snr < femonConfig.redlimit ? clrRed : snr < femonConfig.greenlimit ? clrYellow : clrGreen*/, clrBackground, m_StatusWindow); + snprintf(buf, sizeof(buf), "UNC: %08x", m_UNC); + m_Osd->Text(OSDSTATUSCOL3 * cOsd::CellWidth(), femonConfig.position ? lines * cOsd::LineHeight() : (OSDINFOHEIGHT + OSDGAPHEIGHT + lines) * cOsd::LineHeight(), buf, clrWhite, clrBackground, m_StatusWindow); + if (m_Receiver) snprintf(buf, sizeof(buf), "Audio: %.0f kbit/s",m_Receiver->AudioBitrate()); + else snprintf(buf, sizeof(buf), "Audio: --- kbit/s"); + m_Osd->Text(OSDSTATUSCOL4 * cOsd::CellWidth(), femonConfig.position ? lines * cOsd::LineHeight() : (OSDINFOHEIGHT + OSDGAPHEIGHT + lines) * cOsd::LineHeight(), buf, clrWhite, clrBackground, m_StatusWindow); + lines++; + m_Osd->Text(OSDSTATUSLOCK * cOsd::CellWidth(), femonConfig.position ? lines * cOsd::LineHeight() : (OSDINFOHEIGHT + OSDGAPHEIGHT + lines) * cOsd::LineHeight(), "LOCK", (m_FrontendStatus & FE_HAS_LOCK) ? clrYellow : clrBlack, clrBackground, m_StatusWindow); + m_Osd->Text(OSDSTATUSSIGN * cOsd::CellWidth(), femonConfig.position ? lines * cOsd::LineHeight() : (OSDINFOHEIGHT + OSDGAPHEIGHT + lines) * cOsd::LineHeight(), "SIGNAL", (m_FrontendStatus & FE_HAS_SIGNAL) ? clrYellow : clrBlack, clrBackground, m_StatusWindow); + m_Osd->Text(OSDSTATUSCARR * cOsd::CellWidth(), femonConfig.position ? lines * cOsd::LineHeight() : (OSDINFOHEIGHT + OSDGAPHEIGHT + lines) * cOsd::LineHeight(), "CARRIER",(m_FrontendStatus & FE_HAS_CARRIER)? clrYellow : clrBlack, clrBackground, m_StatusWindow); + m_Osd->Text(OSDSTATUSVITE * cOsd::CellWidth(), femonConfig.position ? lines * cOsd::LineHeight() : (OSDINFOHEIGHT + OSDGAPHEIGHT + lines) * cOsd::LineHeight(), "VITERBI",(m_FrontendStatus & FE_HAS_VITERBI)? clrYellow : clrBlack, clrBackground, m_StatusWindow); + m_Osd->Text(OSDSTATUSSYNC * cOsd::CellWidth(), femonConfig.position ? lines * cOsd::LineHeight() : (OSDINFOHEIGHT + OSDGAPHEIGHT + lines) * cOsd::LineHeight(), "SYNC", (m_FrontendStatus & FE_HAS_SYNC) ? clrYellow : clrBlack, clrBackground, m_StatusWindow); +#if (VDRVERSNUM >= 10300) || defined(ELCHIAIOVERSION) + m_Osd->SetFont(OldFont); +#endif + m_Osd->Flush(); + } +} + +void cFemonOsd::DrawInfoWindow(void) +{ + cMutexLock lock(m_Mutex); + //printf("cFemonOsd::DrawInfoWindow()\n"); + char buf[128]; + char buf2[20]; + int lines = 0; + int value = 0; + + if (m_Osd) { + if (m_DisplayMode) { +#if (VDRVERSNUM >= 10300) || defined(ELCHIAIOVERSION) + eDvbFont OldFont = m_Osd->SetFont(fontSml); +#endif + m_Osd->Clear(m_InfoWindow); + m_Osd->Fill(0, femonConfig.position ? (OSDSTATUSHEIGHT + OSDGAPHEIGHT + lines) * cOsd::LineHeight() : lines * cOsd::LineHeight(), OSDWIDTH * cOsd::CellWidth(), femonConfig.position ? (OSDSTATUSHEIGHT + OSDGAPHEIGHT + lines + 1) * cOsd::LineHeight() - 1 : (lines + 1) * cOsd::LineHeight() - 1, clrWhite, m_InfoWindow); + m_Osd->Text( OSDINFOLCOL1 * cOsd::CellWidth(), femonConfig.position ? (OSDSTATUSHEIGHT + OSDGAPHEIGHT + lines) * cOsd::LineHeight() : lines, tr("Transponder Information"), clrBackground, clrWhite, m_InfoWindow); + lines++; + m_Osd->Text(OSDINFOLCOL1 * cOsd::CellWidth(), femonConfig.position ? (OSDSTATUSHEIGHT + OSDGAPHEIGHT + lines) * cOsd::LineHeight() : lines * cOsd::LineHeight(), tr("Vpid"), clrWhite, clrBackground, m_InfoWindow); + snprintf(buf, sizeof(buf), "%d", Channels.GetByNumber(cDevice::CurrentChannel())->Vpid()); + m_Osd->Text(OSDINFOLCOL2 * cOsd::CellWidth(), femonConfig.position ? (OSDSTATUSHEIGHT + OSDGAPHEIGHT + lines) * cOsd::LineHeight() : lines * cOsd::LineHeight(), buf, clrYellow, clrBackground, m_InfoWindow); + m_Osd->Text(OSDINFOLCOL3 * cOsd::CellWidth(), femonConfig.position ? (OSDSTATUSHEIGHT + OSDGAPHEIGHT + lines) * cOsd::LineHeight() : lines * cOsd::LineHeight(), tr("Ppid"), clrWhite, clrBackground, m_InfoWindow); + snprintf(buf, sizeof(buf), "%d", Channels.GetByNumber(cDevice::CurrentChannel())->Ppid()); + m_Osd->Text(OSDINFOLCOL4 * cOsd::CellWidth(), femonConfig.position ? (OSDSTATUSHEIGHT + OSDGAPHEIGHT + lines) * cOsd::LineHeight() : lines * cOsd::LineHeight(), buf, clrYellow, clrBackground, m_InfoWindow); + lines++; + m_Osd->Text(OSDINFOLCOL1 * cOsd::CellWidth(), femonConfig.position ? (OSDSTATUSHEIGHT + OSDGAPHEIGHT + lines) * cOsd::LineHeight() : lines * cOsd::LineHeight(), tr("Apid1"), clrWhite, clrBackground, m_InfoWindow); + snprintf(buf, sizeof(buf), "%d", Channels.GetByNumber(cDevice::CurrentChannel())->Apid1()); + m_Osd->Text(OSDINFOLCOL2 * cOsd::CellWidth(), femonConfig.position ? (OSDSTATUSHEIGHT + OSDGAPHEIGHT + lines) * cOsd::LineHeight() : lines * cOsd::LineHeight(), buf, clrYellow, clrBackground, m_InfoWindow); + m_Osd->Text(OSDINFOLCOL3 * cOsd::CellWidth(), femonConfig.position ? (OSDSTATUSHEIGHT + OSDGAPHEIGHT + lines) * cOsd::LineHeight() : lines * cOsd::LineHeight(), tr("Tpid"), clrWhite, clrBackground, m_InfoWindow); + snprintf(buf, sizeof(buf), "%d", Channels.GetByNumber(cDevice::CurrentChannel())->Tpid()); + m_Osd->Text(OSDINFOLCOL4 * cOsd::CellWidth(), femonConfig.position ? (OSDSTATUSHEIGHT + OSDGAPHEIGHT + lines) * cOsd::LineHeight() : lines * cOsd::LineHeight(), buf, clrYellow, clrBackground, m_InfoWindow); + lines++; + m_Osd->Text(OSDINFOLCOL1 * cOsd::CellWidth(), femonConfig.position ? (OSDSTATUSHEIGHT + OSDGAPHEIGHT + lines) * cOsd::LineHeight() : lines * cOsd::LineHeight(), tr("CA"), clrWhite, clrBackground, m_InfoWindow); + snprintf(buf, sizeof(buf), "%d", Channels.GetByNumber(cDevice::CurrentChannel())->Ca()); + m_Osd->Text(OSDINFOLCOL2 * cOsd::CellWidth(), femonConfig.position ? (OSDSTATUSHEIGHT + OSDGAPHEIGHT + lines) * cOsd::LineHeight() : lines * cOsd::LineHeight(), buf, clrYellow, clrBackground, m_InfoWindow); + m_Osd->Text(OSDINFOLCOL3 * cOsd::CellWidth(), femonConfig.position ? (OSDSTATUSHEIGHT + OSDGAPHEIGHT + lines) * cOsd::LineHeight() : lines * cOsd::LineHeight(), tr("Sid"), clrWhite, clrBackground, m_InfoWindow); + snprintf(buf, sizeof(buf), "%d", Channels.GetByNumber(cDevice::CurrentChannel())->Sid()); + m_Osd->Text(OSDINFOLCOL4 * cOsd::CellWidth(), femonConfig.position ? (OSDSTATUSHEIGHT + OSDGAPHEIGHT + lines) * cOsd::LineHeight() : lines * cOsd::LineHeight(), buf, clrYellow, clrBackground, m_InfoWindow); + lines++; +#if (VDRVERSNUM >= 10300) + m_Osd->Text(OSDINFOLCOL1 * cOsd::CellWidth(), femonConfig.position ? (OSDSTATUSHEIGHT + OSDGAPHEIGHT + lines) * cOsd::LineHeight() : lines * cOsd::LineHeight(), "Nid", clrWhite, clrBackground, m_InfoWindow); + snprintf(buf, sizeof(buf), "%d", Channels.GetByNumber(cDevice::CurrentChannel())->Nid()); + m_Osd->Text(OSDINFOLCOL2 * cOsd::CellWidth(), femonConfig.position ? (OSDSTATUSHEIGHT + OSDGAPHEIGHT + lines) * cOsd::LineHeight() : lines * cOsd::LineHeight(), buf, clrYellow, clrBackground, m_InfoWindow); + m_Osd->Text(OSDINFOLCOL3 * cOsd::CellWidth(), femonConfig.position ? (OSDSTATUSHEIGHT + OSDGAPHEIGHT + lines) * cOsd::LineHeight() : lines * cOsd::LineHeight(), "Tid" /*tr("Tid")*/, clrWhite, clrBackground, m_InfoWindow); + snprintf(buf, sizeof(buf), "%d", Channels.GetByNumber(cDevice::CurrentChannel())->Tid()); + m_Osd->Text(OSDINFOLCOL4 * cOsd::CellWidth(), femonConfig.position ? (OSDSTATUSHEIGHT + OSDGAPHEIGHT + lines) * cOsd::LineHeight() : lines * cOsd::LineHeight(), buf, clrYellow, clrBackground, m_InfoWindow); + lines++; + m_Osd->Text(OSDINFOLCOL1 * cOsd::CellWidth(), femonConfig.position ? (OSDSTATUSHEIGHT + OSDGAPHEIGHT + lines) * cOsd::LineHeight() : lines * cOsd::LineHeight(), "Rid" /*tr("Rid")*/, clrWhite, clrBackground, m_InfoWindow); + snprintf(buf, sizeof(buf), "%d", Channels.GetByNumber(cDevice::CurrentChannel())->Rid()); + m_Osd->Text(OSDINFOLCOL2 * cOsd::CellWidth(), femonConfig.position ? (OSDSTATUSHEIGHT + OSDGAPHEIGHT + lines) * cOsd::LineHeight() : lines * cOsd::LineHeight(), buf, clrYellow, clrBackground, m_InfoWindow); + lines++; +#endif + switch (m_FrontendInfo.type) { + case FE_QPSK: + snprintf(buf, sizeof(buf), "%s #%d - %s", tr("Satellite Card"), cDevice::ActualDevice()->CardIndex(), m_FrontendInfo.name); + m_Osd->Text(OSDINFOLCOL1 * cOsd::CellWidth(), femonConfig.position ? (OSDSTATUSHEIGHT + OSDGAPHEIGHT + lines) * cOsd::LineHeight() : lines * cOsd::LineHeight(), buf, clrYellow, clrBackground, m_InfoWindow); + lines++; + m_Osd->Text(OSDINFOLCOL1 * cOsd::CellWidth(), femonConfig.position ? (OSDSTATUSHEIGHT + OSDGAPHEIGHT + lines) * cOsd::LineHeight() : lines * cOsd::LineHeight(), tr("Frequency"), clrWhite, clrBackground, m_InfoWindow); + snprintf(buf, sizeof(buf), "%d kHz", Channels.GetByNumber(cDevice::CurrentChannel())->Frequency()); + m_Osd->Text(OSDINFOLCOL2 * cOsd::CellWidth(), femonConfig.position ? (OSDSTATUSHEIGHT + OSDGAPHEIGHT + lines) * cOsd::LineHeight() : lines * cOsd::LineHeight(), buf, clrYellow, clrBackground, m_InfoWindow); + m_Osd->Text(OSDINFOLCOL3 * cOsd::CellWidth(), femonConfig.position ? (OSDSTATUSHEIGHT + OSDGAPHEIGHT + lines) * cOsd::LineHeight() : lines * cOsd::LineHeight(), tr("Source"), clrWhite, clrBackground, m_InfoWindow); + snprintf(buf, sizeof(buf), "%s", cSource::ToString(Channels.GetByNumber(cDevice::CurrentChannel())->Source())); + m_Osd->Text(OSDINFOLCOL4 * cOsd::CellWidth(), femonConfig.position ? (OSDSTATUSHEIGHT + OSDGAPHEIGHT + lines) * cOsd::LineHeight() : lines * cOsd::LineHeight(), buf, clrYellow, clrBackground, m_InfoWindow); + lines++; + m_Osd->Text(OSDINFOLCOL1 * cOsd::CellWidth(), femonConfig.position ? (OSDSTATUSHEIGHT + OSDGAPHEIGHT + lines) * cOsd::LineHeight() : lines * cOsd::LineHeight(), tr("Srate"), clrWhite, clrBackground, m_InfoWindow); + snprintf(buf, sizeof(buf), "%d", Channels.GetByNumber(cDevice::CurrentChannel())->Srate()); + m_Osd->Text(OSDINFOLCOL2 * cOsd::CellWidth(), femonConfig.position ? (OSDSTATUSHEIGHT + OSDGAPHEIGHT + lines) * cOsd::LineHeight() : lines * cOsd::LineHeight(), buf, clrYellow, clrBackground, m_InfoWindow); + m_Osd->Text(OSDINFOLCOL3 * cOsd::CellWidth(), femonConfig.position ? (OSDSTATUSHEIGHT + OSDGAPHEIGHT + lines) * cOsd::LineHeight() : lines * cOsd::LineHeight(), tr("Polarization"), clrWhite, clrBackground, m_InfoWindow); + snprintf(buf, sizeof(buf), "%c", toupper(Channels.GetByNumber(cDevice::CurrentChannel())->Polarization())); + m_Osd->Text(OSDINFOLCOL4 * cOsd::CellWidth(), femonConfig.position ? (OSDSTATUSHEIGHT + OSDGAPHEIGHT + lines) * cOsd::LineHeight() : lines * cOsd::LineHeight(), buf, clrYellow, clrBackground, m_InfoWindow); + lines++; + m_Osd->Text(OSDINFOLCOL1 * cOsd::CellWidth(), femonConfig.position ? (OSDSTATUSHEIGHT + OSDGAPHEIGHT + lines) * cOsd::LineHeight() : lines * cOsd::LineHeight(), tr("Inversion"), clrWhite, clrBackground, m_InfoWindow); + value = Channels.GetByNumber(cDevice::CurrentChannel())->Inversion(); + if (value == 0) snprintf(buf, sizeof(buf), "Off"); + else if (value == 1) snprintf(buf, sizeof(buf), "On"); + else snprintf(buf, sizeof(buf), "Auto"); + m_Osd->Text(OSDINFOLCOL2 * cOsd::CellWidth(), femonConfig.position ? (OSDSTATUSHEIGHT + OSDGAPHEIGHT + lines) * cOsd::LineHeight() : lines * cOsd::LineHeight(), buf, clrYellow, clrBackground, m_InfoWindow); + m_Osd->Text(OSDINFOLCOL3 * cOsd::CellWidth(), femonConfig.position ? (OSDSTATUSHEIGHT + OSDGAPHEIGHT + lines) * cOsd::LineHeight() : lines * cOsd::LineHeight(), tr("CoderateH"), clrWhite, clrBackground, m_InfoWindow); + value = Channels.GetByNumber(cDevice::CurrentChannel())->CoderateH(); + if (value == 0) snprintf(buf, sizeof(buf), "None"); + else if (value == 1) snprintf(buf, sizeof(buf), "1/2"); + else if (value == 2) snprintf(buf, sizeof(buf), "2/3"); + else if (value == 3) snprintf(buf, sizeof(buf), "3/4"); + else if (value == 4) snprintf(buf, sizeof(buf), "4/5"); + else if (value == 5) snprintf(buf, sizeof(buf), "5/6"); + else if (value == 6) snprintf(buf, sizeof(buf), "6/7"); + else if (value == 7) snprintf(buf, sizeof(buf), "7/8"); + else if (value == 8) snprintf(buf, sizeof(buf), "8/9"); + else snprintf(buf, sizeof(buf), "Auto"); + m_Osd->Text(OSDINFOLCOL4 * cOsd::CellWidth(), femonConfig.position ? (OSDSTATUSHEIGHT + OSDGAPHEIGHT + lines) * cOsd::LineHeight() : lines * cOsd::LineHeight(), buf, clrYellow, clrBackground, m_InfoWindow); + break; + + case FE_QAM: + snprintf(buf, sizeof(buf), "%s #%d - %s", tr("Cable Card"), cDevice::ActualDevice()->CardIndex(), m_FrontendInfo.name); + m_Osd->Text(OSDINFOLCOL1 * cOsd::CellWidth(), femonConfig.position ? (OSDSTATUSHEIGHT + OSDGAPHEIGHT + lines) * cOsd::LineHeight() : lines * cOsd::LineHeight(), buf, clrYellow, clrBackground, m_InfoWindow); + lines++; + m_Osd->Text(OSDINFOLCOL1 * cOsd::CellWidth(), femonConfig.position ? (OSDSTATUSHEIGHT + OSDGAPHEIGHT + lines) * cOsd::LineHeight() : lines * cOsd::LineHeight(), tr("Frequency"), clrWhite, clrBackground, m_InfoWindow); + snprintf(buf, sizeof(buf), "%d kHz", Channels.GetByNumber(cDevice::CurrentChannel())->Frequency()); + m_Osd->Text(OSDINFOLCOL2 * cOsd::CellWidth(), femonConfig.position ? (OSDSTATUSHEIGHT + OSDGAPHEIGHT + lines) * cOsd::LineHeight() : lines * cOsd::LineHeight(), buf, clrYellow, clrBackground, m_InfoWindow); + m_Osd->Text(OSDINFOLCOL3 * cOsd::CellWidth(), femonConfig.position ? (OSDSTATUSHEIGHT + OSDGAPHEIGHT + lines) * cOsd::LineHeight() : lines * cOsd::LineHeight(), tr("Source"), clrWhite, clrBackground, m_InfoWindow); + snprintf(buf, sizeof(buf), "%s", cSource::ToString(Channels.GetByNumber(cDevice::CurrentChannel())->Source())); + m_Osd->Text(OSDINFOLCOL4 * cOsd::CellWidth(), femonConfig.position ? (OSDSTATUSHEIGHT + OSDGAPHEIGHT + lines) * cOsd::LineHeight() : lines * cOsd::LineHeight(), buf, clrYellow, clrBackground, m_InfoWindow); + lines++; + m_Osd->Text(OSDINFOLCOL1 * cOsd::CellWidth(), femonConfig.position ? (OSDSTATUSHEIGHT + OSDGAPHEIGHT + lines) * cOsd::LineHeight() : lines * cOsd::LineHeight(), tr("Srate"), clrWhite, clrBackground, m_InfoWindow); + snprintf(buf, sizeof(buf), "%d", Channels.GetByNumber(cDevice::CurrentChannel())->Srate()); + m_Osd->Text(OSDINFOLCOL2 * cOsd::CellWidth(), femonConfig.position ? (OSDSTATUSHEIGHT + OSDGAPHEIGHT + lines) * cOsd::LineHeight() : lines * cOsd::LineHeight(), buf, clrYellow, clrBackground, m_InfoWindow); + m_Osd->Text(OSDINFOLCOL3 * cOsd::CellWidth(), femonConfig.position ? (OSDSTATUSHEIGHT + OSDGAPHEIGHT + lines) * cOsd::LineHeight() : lines * cOsd::LineHeight(), tr("Modulation"), clrWhite, clrBackground, m_InfoWindow); + value = Channels.GetByNumber(cDevice::CurrentChannel())->Modulation(); + if (value == 0) snprintf(buf, sizeof(buf), "QPSK"); + else if (value == 1) snprintf(buf, sizeof(buf), "QAM 16"); + else if (value == 2) snprintf(buf, sizeof(buf), "QAM 32"); + else if (value == 3) snprintf(buf, sizeof(buf), "QAM 64"); + else if (value == 4) snprintf(buf, sizeof(buf), "QAM 128"); + else if (value == 5) snprintf(buf, sizeof(buf), "QAM 256"); + else snprintf(buf, sizeof(buf), "QAM Auto"); + m_Osd->Text(OSDINFOLCOL4 * cOsd::CellWidth(), femonConfig.position ? (OSDSTATUSHEIGHT + OSDGAPHEIGHT + lines) * cOsd::LineHeight() : lines * cOsd::LineHeight(), buf, clrYellow, clrBackground, m_InfoWindow); + lines++; + m_Osd->Text(OSDINFOLCOL1 * cOsd::CellWidth(), femonConfig.position ? (OSDSTATUSHEIGHT + OSDGAPHEIGHT + lines) * cOsd::LineHeight() : lines * cOsd::LineHeight(), tr("Inversion"), clrWhite, clrBackground, m_InfoWindow); + value = Channels.GetByNumber(cDevice::CurrentChannel())->Inversion(); + if (value == 0) snprintf(buf, sizeof(buf), "Off"); + else if (value == 1) snprintf(buf, sizeof(buf), "On"); + else snprintf(buf, sizeof(buf), "Auto"); + m_Osd->Text(OSDINFOLCOL2 * cOsd::CellWidth(), femonConfig.position ? (OSDSTATUSHEIGHT + OSDGAPHEIGHT + lines) * cOsd::LineHeight() : lines * cOsd::LineHeight(), buf, clrYellow, clrBackground, m_InfoWindow); + m_Osd->Text(OSDINFOLCOL3 * cOsd::CellWidth(), femonConfig.position ? (OSDSTATUSHEIGHT + OSDGAPHEIGHT + lines) * cOsd::LineHeight() : lines * cOsd::LineHeight(), tr("CoderateH"), clrWhite, clrBackground, m_InfoWindow); + value = Channels.GetByNumber(cDevice::CurrentChannel())->CoderateH(); + if (value == 0) snprintf(buf, sizeof(buf), "None"); + else if (value == 1) snprintf(buf, sizeof(buf), "1/2"); + else if (value == 2) snprintf(buf, sizeof(buf), "2/3"); + else if (value == 3) snprintf(buf, sizeof(buf), "3/4"); + else if (value == 4) snprintf(buf, sizeof(buf), "4/5"); + else if (value == 5) snprintf(buf, sizeof(buf), "5/6"); + else if (value == 6) snprintf(buf, sizeof(buf), "6/7"); + else if (value == 7) snprintf(buf, sizeof(buf), "7/8"); + else if (value == 8) snprintf(buf, sizeof(buf), "8/9"); + else snprintf(buf, sizeof(buf), "Auto"); + m_Osd->Text(OSDINFOLCOL4 * cOsd::CellWidth(), femonConfig.position ? (OSDSTATUSHEIGHT + OSDGAPHEIGHT + lines) * cOsd::LineHeight() : lines * cOsd::LineHeight(), buf, clrYellow, clrBackground, m_InfoWindow); + break; + + default: + snprintf(buf, sizeof(buf), "%s #%d - %s", tr("Terrestial Card"), cDevice::ActualDevice()->CardIndex(), m_FrontendInfo.name); + m_Osd->Text(OSDINFOLCOL1 * cOsd::CellWidth(), femonConfig.position ? (OSDSTATUSHEIGHT + OSDGAPHEIGHT + lines) * cOsd::LineHeight() : lines * cOsd::LineHeight(), buf, clrYellow, clrBackground, m_InfoWindow); + lines++; + m_Osd->Text(OSDINFOLCOL1 * cOsd::CellWidth(), femonConfig.position ? (OSDSTATUSHEIGHT + OSDGAPHEIGHT + lines) * cOsd::LineHeight() : lines * cOsd::LineHeight(), tr("Frequency"), clrWhite, clrBackground, m_InfoWindow); + snprintf(buf, sizeof(buf), "%d kHz", Channels.GetByNumber(cDevice::CurrentChannel())->Frequency() / 1000); + m_Osd->Text(OSDINFOLCOL2 * cOsd::CellWidth(), femonConfig.position ? (OSDSTATUSHEIGHT + OSDGAPHEIGHT + lines) * cOsd::LineHeight() : lines * cOsd::LineHeight(), buf, clrYellow, clrBackground, m_InfoWindow); + m_Osd->Text(OSDINFOLCOL3 * cOsd::CellWidth(), femonConfig.position ? (OSDSTATUSHEIGHT + OSDGAPHEIGHT + lines) * cOsd::LineHeight() : lines * cOsd::LineHeight(), tr("Transmission"), clrWhite, clrBackground, m_InfoWindow); + value = Channels.GetByNumber(cDevice::CurrentChannel())->Transmission(); + if (value == 0) snprintf(buf, sizeof(buf), "2K"); + else if (value == 1) snprintf(buf, sizeof(buf), "8K"); + else snprintf(buf, sizeof(buf), "Auto"); + m_Osd->Text(OSDINFOLCOL4 * cOsd::CellWidth(), femonConfig.position ? (OSDSTATUSHEIGHT + OSDGAPHEIGHT + lines) * cOsd::LineHeight() : lines * cOsd::LineHeight(), buf, clrYellow, clrBackground, m_InfoWindow); + lines++; + m_Osd->Text( OSDINFOLCOL1 * cOsd::CellWidth(), femonConfig.position ? (OSDSTATUSHEIGHT + OSDGAPHEIGHT + lines) * cOsd::LineHeight() : lines * cOsd::LineHeight(), tr("Bandwidth"), clrWhite, clrBackground, m_InfoWindow); + value = Channels.GetByNumber(cDevice::CurrentChannel())->Bandwidth(); + if (value == 0) snprintf(buf, sizeof(buf), "6 MHz"); + else if (value == 1) snprintf(buf, sizeof(buf), "7 MHz"); + else if (value == 2) snprintf(buf, sizeof(buf), "8 MHz"); + else snprintf(buf, sizeof(buf), "Auto"); + m_Osd->Text(OSDINFOLCOL2 * cOsd::CellWidth(), femonConfig.position ? (OSDSTATUSHEIGHT + OSDGAPHEIGHT + lines) * cOsd::LineHeight() : lines * cOsd::LineHeight(), buf, clrYellow, clrBackground, m_InfoWindow); + m_Osd->Text(OSDINFOLCOL3 * cOsd::CellWidth(), femonConfig.position ? (OSDSTATUSHEIGHT + OSDGAPHEIGHT + lines) * cOsd::LineHeight() : lines * cOsd::LineHeight(), tr("Modulation"), clrWhite, clrBackground, m_InfoWindow); + value = Channels.GetByNumber(cDevice::CurrentChannel())->Modulation(); + if (value == 0) snprintf(buf, sizeof(buf), "QPSK"); + else if (value == 1) snprintf(buf, sizeof(buf), "QAM 16"); + else if (value == 2) snprintf(buf, sizeof(buf), "QAM 32"); + else if (value == 3) snprintf(buf, sizeof(buf), "QAM 64"); + else if (value == 4) snprintf(buf, sizeof(buf), "QAM 128"); + else if (value == 5) snprintf(buf, sizeof(buf), "QAM 256"); + else snprintf(buf, sizeof(buf), "QAM Auto"); + m_Osd->Text(OSDINFOLCOL4 * cOsd::CellWidth(), femonConfig.position ? (OSDSTATUSHEIGHT + OSDGAPHEIGHT + lines) * cOsd::LineHeight() : lines * cOsd::LineHeight(), buf, clrYellow, clrBackground, m_InfoWindow); + lines++; + m_Osd->Text(OSDINFOLCOL1 * cOsd::CellWidth(), femonConfig.position ? (OSDSTATUSHEIGHT + OSDGAPHEIGHT + lines) * cOsd::LineHeight() : lines * cOsd::LineHeight(), tr("Inversion"), clrWhite, clrBackground, m_InfoWindow); + value = Channels.GetByNumber(cDevice::CurrentChannel())->Inversion(); + if (value == 0) snprintf(buf, sizeof(buf), "Off"); + else if (value == 1) snprintf(buf, sizeof(buf), "On"); + else snprintf(buf, sizeof(buf), "Auto"); + m_Osd->Text(OSDINFOLCOL2 * cOsd::CellWidth(), femonConfig.position ? (OSDSTATUSHEIGHT + OSDGAPHEIGHT + lines) * cOsd::LineHeight() : lines * cOsd::LineHeight(), buf, clrYellow, clrBackground, m_InfoWindow); + m_Osd->Text(OSDINFOLCOL3 * cOsd::CellWidth(), femonConfig.position ? (OSDSTATUSHEIGHT + OSDGAPHEIGHT + lines) * cOsd::LineHeight() : lines * cOsd::LineHeight(), tr("CoderateH"), clrWhite, clrBackground, m_InfoWindow); + value = Channels.GetByNumber(cDevice::CurrentChannel())->CoderateH(); + if (value == 0) snprintf(buf, sizeof(buf), "None"); + else if (value == 1) snprintf(buf, sizeof(buf), "1/2"); + else if (value == 2) snprintf(buf, sizeof(buf), "2/3"); + else if (value == 3) snprintf(buf, sizeof(buf), "3/4"); + else if (value == 4) snprintf(buf, sizeof(buf), "4/5"); + else if (value == 5) snprintf(buf, sizeof(buf), "5/6"); + else if (value == 6) snprintf(buf, sizeof(buf), "6/7"); + else if (value == 7) snprintf(buf, sizeof(buf), "7/8"); + else if (value == 8) snprintf(buf, sizeof(buf), "8/9"); + else snprintf(buf, sizeof(buf), "Auto"); + value = Channels.GetByNumber(cDevice::CurrentChannel())->CoderateL(); + if (value == 0) snprintf(buf2, sizeof(buf2), " - None"); + else if (value == 1) snprintf(buf2, sizeof(buf2), " - 1/2"); + else if (value == 2) snprintf(buf2, sizeof(buf2), " - 2/3"); + else if (value == 3) snprintf(buf2, sizeof(buf2), " - 3/4"); + else if (value == 4) snprintf(buf2, sizeof(buf2), " - 4/5"); + else if (value == 5) snprintf(buf2, sizeof(buf2), " - 5/6"); + else if (value == 6) snprintf(buf2, sizeof(buf2), " - 6/7"); + else if (value == 7) snprintf(buf2, sizeof(buf2), " - 7/8"); + else if (value == 8) snprintf(buf2, sizeof(buf2), " - 8/9"); + else snprintf(buf2, sizeof(buf2), " - Auto"); + strncat(buf, buf2, sizeof(buf)); + m_Osd->Text(OSDINFOLCOL4 * cOsd::CellWidth(), femonConfig.position ? (OSDSTATUSHEIGHT + OSDGAPHEIGHT + lines) * cOsd::LineHeight() : lines * cOsd::LineHeight(), buf, clrYellow, clrBackground, m_InfoWindow); + lines++; + m_Osd->Text(OSDINFOLCOL1 * cOsd::CellWidth(), femonConfig.position ? (OSDSTATUSHEIGHT + OSDGAPHEIGHT + lines) * cOsd::LineHeight() : lines * cOsd::LineHeight(), tr("Hierarchy"), clrWhite, clrBackground, m_InfoWindow); + value = Channels.GetByNumber(cDevice::CurrentChannel())->Hierarchy(); + if (value == 0) snprintf(buf, sizeof(buf), "None"); + else if (value == 1) snprintf(buf, sizeof(buf), "1"); + else if (value == 2) snprintf(buf, sizeof(buf), "2"); + else snprintf(buf, sizeof(buf), "Auto"); + m_Osd->Text(OSDINFOLCOL2 * cOsd::CellWidth(), femonConfig.position ? (OSDSTATUSHEIGHT + OSDGAPHEIGHT + lines) * cOsd::LineHeight() : lines * cOsd::LineHeight(), buf, clrYellow, clrBackground, m_InfoWindow); + m_Osd->Text(OSDINFOLCOL3 * cOsd::CellWidth(), femonConfig.position ? (OSDSTATUSHEIGHT + OSDGAPHEIGHT + lines) * cOsd::LineHeight() : lines * cOsd::LineHeight(), tr("Guard"), clrWhite, clrBackground, m_InfoWindow); + value = Channels.GetByNumber(cDevice::CurrentChannel())->Guard(); + if (value == 0) snprintf(buf, sizeof(buf), "1/4"); + else if (value == 1) snprintf(buf, sizeof(buf), "1/8"); + else if (value == 2) snprintf(buf, sizeof(buf), "1/16"); + else if (value == 3) snprintf(buf, sizeof(buf), "1/32"); + else snprintf(buf, sizeof(buf), "Auto"); + m_Osd->Text(OSDINFOLCOL4 * cOsd::CellWidth(), femonConfig.position ? (OSDSTATUSHEIGHT + OSDGAPHEIGHT + lines) * cOsd::LineHeight() : lines * cOsd::LineHeight(), buf, clrYellow, clrBackground, m_InfoWindow); + break; + } +#if (VDRVERSNUM >= 10300) || defined(ELCHIAIOVERSION) + m_Osd->SetFont(OldFont); +#endif + } + else { + m_Osd->Fill(0, femonConfig.position ? (OSDSTATUSHEIGHT + OSDGAPHEIGHT) * cOsd::LineHeight() : 0, OSDWIDTH * cOsd::CellWidth(), femonConfig.position ? (OSDSTATUSHEIGHT + OSDINFOHEIGHT + OSDGAPHEIGHT) * cOsd::LineHeight() : OSDINFOHEIGHT * cOsd::LineHeight(), clrTransparent, m_InfoWindow); + } + m_Osd->Flush(); + } +} + void cFemonOsd::Action(void) { //printf("cFemonOsd::Action()\n"); - int snr_o, signal_o; - uint16_t snr, signal; - uint32_t ber, unc; - fe_status_t fe_status; - char buf[128]; - double VRate = 0.0; - double ARate = 0.0; - #if (VDRVERSNUM < 10300) isyslog("femon plugin: thread started (pid = %d)", getpid()); #endif m_Active = true; while (m_Active) { if (m_Frontend != -1) { - CHECK(ioctl(m_Frontend, FE_READ_STATUS, &fe_status)); - CHECK(ioctl(m_Frontend, FE_READ_SIGNAL_STRENGTH, &signal)); - CHECK(ioctl(m_Frontend, FE_READ_SNR, &snr)); - CHECK(ioctl(m_Frontend, FE_READ_BER, &ber)); - CHECK(ioctl(m_Frontend, FE_READ_UNCORRECTED_BLOCKS, &unc)); - if (m_Osd) { - m_Osd->Clear(m_Window); -#if (VDRVERSNUM >= 10300) || defined(ELCHIAIOVERSION) - eDvbFont OldFont = m_Osd->SetFont(fontSml); -#endif - sprintf(buf, "%d%s%s", m_Number ? m_Number : cDevice::CurrentChannel(), m_Number ? "- " : " ", Channels.GetByNumber(cDevice::CurrentChannel())->Name()); - m_Osd->Fill(0, 0, m_Width, cOsd::LineHeight() - 1, clrWhite, m_Window); - m_Osd->Text(cOsd::CellWidth(), 0, buf, clrBlack, clrWhite, m_Window); - if (m_Receiver) { - // do some averaging to smooth the value - VRate = (VRate + (8.0 * TS_SIZE * m_Receiver->VideoPacketCount()) / (femonConfig.interval * 102.4 * 1024.0)) / 2.0; - ARate = (ARate + (8.0 * TS_SIZE * m_Receiver->AudioPacketCount()) / (femonConfig.interval * 102.4)) / 2.0; - sprintf(buf, "V: %.2f Mbit/s", VRate); - m_Osd->Text((m_Width - 22 * cOsd::CellWidth()), 0, buf, clrBlack, clrWhite, m_Window); - sprintf(buf, "A: %.0f kbit/s", ARate); - m_Osd->Text((m_Width - 10 * cOsd::CellWidth()), 0, buf, clrBlack, clrWhite, m_Window); - } - sprintf(buf, "STR: %04x", signal); - m_Osd->Text(cOsd::CellWidth(), 3 * cOsd::LineHeight(), buf, clrWhite, clrBackground, m_Window); - sprintf(buf, "SNR: %04x", snr); - m_Osd->Text(11 * cOsd::CellWidth(), 3 * cOsd::LineHeight(), buf, clrWhite, clrBackground, m_Window); - sprintf(buf, "BER: %08x", ber); - m_Osd->Text(21 * cOsd::CellWidth(), 3 * cOsd::LineHeight(), buf, clrWhite, clrBackground, m_Window); - sprintf(buf, "UNC: %08x", unc); - m_Osd->Text(35 * cOsd::CellWidth(), 3 * cOsd::LineHeight(), buf, clrWhite, clrBackground, m_Window); - signal_o = signal / 655; - sprintf(buf, "STR: %2d%%", signal_o); - if (signal_o > 0) { - signal_o = (m_Width - 8 * cOsd::CellWidth()) * signal_o / 100; - m_Osd->Fill(0, cOsd::LineHeight() + 3, min(((m_Width - 8 * cOsd::CellWidth()) * femonConfig.redlimit / 100), signal_o), 2 * cOsd::LineHeight() - 3, clrRed, m_Window); - if (signal_o > ((m_Width - 8 * cOsd::CellWidth()) * femonConfig.redlimit / 100)) { - m_Osd->Fill(((m_Width - 8 * cOsd::CellWidth()) * femonConfig.redlimit / 100), cOsd::LineHeight() + 3, min(((m_Width - 8 * cOsd::CellWidth()) * femonConfig.greenlimit / 100), signal_o), 2 * cOsd::LineHeight() - 3, clrYellow, m_Window); - } - if (signal_o > ((m_Width - 8 * cOsd::CellWidth()) * femonConfig.greenlimit / 100)) { - m_Osd->Fill(((m_Width - 8 * cOsd::CellWidth()) * femonConfig.greenlimit / 100), cOsd::LineHeight() + 3, signal_o, 2 * cOsd::LineHeight() - 3, clrGreen, m_Window); - } - m_Osd->Text(m_Width - 8 * cOsd::CellWidth(), cOsd::LineHeight(), buf, clrWhite, clrBackground, m_Window); - } - snr_o = snr / 655; - sprintf(buf, "SNR: %2d%%", snr_o); - if (snr_o > 0) { - snr_o = (m_Width - 8 * cOsd::CellWidth()) * snr_o / 100; - m_Osd->Fill(0, 2 * cOsd::LineHeight() + 3, min(((m_Width - 8 * cOsd::CellWidth()) * femonConfig.redlimit / 100), snr_o), 3 * cOsd::LineHeight() - 3, clrRed, m_Window); - if (snr_o > ((m_Width - 8 * cOsd::CellWidth()) * femonConfig.redlimit / 100)) { - m_Osd->Fill(((m_Width - 8 * cOsd::CellWidth()) * femonConfig.redlimit / 100), 2 * cOsd::LineHeight() + 3, min(((m_Width - 8 * cOsd::CellWidth()) * femonConfig.greenlimit / 100), snr_o), 3 * cOsd::LineHeight() - 3, clrYellow, m_Window); - } - if (snr_o > ((m_Width - 8 * cOsd::CellWidth()) * femonConfig.greenlimit / 100)) { - m_Osd->Fill(((m_Width - 8 * cOsd::CellWidth()) * femonConfig.greenlimit / 100), 2 * cOsd::LineHeight() + 3, snr_o, 3 * cOsd::LineHeight() - 3, clrGreen, m_Window); - } - m_Osd->Text(m_Width - 8 * cOsd::CellWidth(), 2 * cOsd::LineHeight(), buf, clrWhite, clrBackground, m_Window); - } - if (time_ms() - m_InfoTime < CHANNELINFO_TIMEOUT) { - sprintf(buf, "%s Card #%d - %s", m_FrontendInfo.type == FE_QPSK ? "Satellite" : m_FrontendInfo.type == FE_QAM ? "Cable" : "Terrestial", cDevice::ActualDevice()->CardIndex(), m_FrontendInfo.name); - m_Osd->Text(cOsd::CellWidth(), 4 * cOsd::LineHeight(), buf, clrWhite, clrBackground, m_Window); - } - else { - m_Osd->Text( 1 * cOsd::CellWidth(), 4 * cOsd::LineHeight(), "LOCK", (fe_status & FE_HAS_LOCK) ? clrYellow : clrBlack, clrBackground, m_Window); - m_Osd->Text( 9 * cOsd::CellWidth(), 4 * cOsd::LineHeight(), "SIGNAL", (fe_status & FE_HAS_SIGNAL) ? clrYellow : clrBlack, clrBackground, m_Window); - m_Osd->Text( 19 * cOsd::CellWidth(), 4 * cOsd::LineHeight(), "CARRIER",(fe_status & FE_HAS_CARRIER) ? clrYellow : clrBlack, clrBackground, m_Window); - m_Osd->Text( 30 * cOsd::CellWidth(), 4 * cOsd::LineHeight(), "VITERBI",(fe_status & FE_HAS_VITERBI) ? clrYellow : clrBlack, clrBackground, m_Window); - m_Osd->Text( 40 * cOsd::CellWidth(), 4 * cOsd::LineHeight(), "SYNC", (fe_status & FE_HAS_SYNC) ? clrYellow : clrBlack, clrBackground, m_Window); - } -#if (VDRVERSNUM >= 10300) || defined(ELCHIAIOVERSION) - m_Osd->SetFont(OldFont); -#endif - m_Osd->Flush(); - } + CHECK(ioctl(m_Frontend, FE_READ_STATUS, &m_FrontendStatus)); + CHECK(ioctl(m_Frontend, FE_READ_SIGNAL_STRENGTH, &m_Signal)); + CHECK(ioctl(m_Frontend, FE_READ_SNR, &m_SNR)); + CHECK(ioctl(m_Frontend, FE_READ_BER, &m_BER)); + CHECK(ioctl(m_Frontend, FE_READ_UNCORRECTED_BLOCKS, &m_UNC)); + DrawInfoWindow(); + DrawStatusWindow(); } - usleep(100000L * femonConfig.interval); + usleep(100000L * femonConfig.updateinterval); } #if (VDRVERSNUM < 10300) isyslog("femon plugin: thread stopped (pid = %d)", getpid()); @@ -165,24 +421,19 @@ void cFemonOsd::Show(void) close(m_Frontend); return; } - m_InfoTime = time_ms(); - m_Osd = cOsd::OpenRaw(m_Xpos, m_Ypos); + m_Osd = cOsd::OpenRaw((720 - OSDWIDTH * cOsd::CellWidth()) / 2, (576 - (OSDSTATUSHEIGHT + OSDINFOHEIGHT + OSDGAPHEIGHT) * cOsd::LineHeight()) / 2); if (m_Osd) { - //printf("X: %d - Y: %d - W: %d - H: %d\n", m_Xpos, m_Ypos, m_Width, m_Height); - m_Window = m_Osd->Create(0, 0, m_Width, m_Height, 4); - m_Osd->AddColor(clrBackground, m_Window); - m_Osd->AddColor(clrRed, m_Window); - m_Osd->AddColor(clrGreen, m_Window); - m_Osd->AddColor(clrYellow, m_Window); - m_Osd->AddColor(clrWhite, m_Window); - m_Osd->AddColor(clrBlack, m_Window); - m_Osd->AddColor(clrTransparent, m_Window); - m_Osd->Clear(m_Window); + m_StatusWindow = m_Osd->Create(0, femonConfig.position ? 0 : (OSDINFOHEIGHT + OSDGAPHEIGHT) * cOsd::LineHeight(), OSDWIDTH * cOsd::CellWidth(), OSDSTATUSHEIGHT * cOsd::LineHeight(), 4); + m_InfoWindow = m_Osd->Create(0, femonConfig.position ? (OSDSTATUSHEIGHT + OSDGAPHEIGHT) * cOsd::LineHeight() : 0, OSDWIDTH * cOsd::CellWidth(), OSDINFOHEIGHT * cOsd::LineHeight(), 2); + m_Osd->Clear(); + m_Osd->Fill(0, femonConfig.position ? (OSDSTATUSHEIGHT + OSDGAPHEIGHT) * cOsd::LineHeight() : 0, OSDWIDTH * cOsd::CellWidth(), femonConfig.position ? (OSDSTATUSHEIGHT + OSDINFOHEIGHT + OSDGAPHEIGHT) * cOsd::LineHeight() : OSDINFOHEIGHT * cOsd::LineHeight(), clrTransparent, m_InfoWindow); m_Osd->Flush(); if (m_Receiver) delete m_Receiver; - m_Receiver = new cFemonReceiver(Channels.GetByNumber(cDevice::CurrentChannel())->Ca(), Channels.GetByNumber(cDevice::CurrentChannel())->Vpid(), Channels.GetByNumber(cDevice::CurrentChannel())->Apid1()); - cDevice::ActualDevice()->AttachReceiver(m_Receiver); + if (femonConfig.showbitrate) { + m_Receiver = new cFemonReceiver(Channels.GetByNumber(cDevice::CurrentChannel())->Ca(), Channels.GetByNumber(cDevice::CurrentChannel())->Vpid(), Channels.GetByNumber(cDevice::CurrentChannel())->Apid1()); + cDevice::ActualDevice()->AttachReceiver(m_Receiver); + } Start(); } } @@ -208,9 +459,10 @@ void cFemonOsd::ChannelSwitch(const cDevice * device, int channelNumber) } if (m_Receiver) delete m_Receiver; - m_Receiver = new cFemonReceiver(Channels.GetByNumber(cDevice::CurrentChannel())->Ca(), Channels.GetByNumber(cDevice::CurrentChannel())->Vpid(), Channels.GetByNumber(cDevice::CurrentChannel())->Apid1()); - cDevice::ActualDevice()->AttachReceiver(m_Receiver); - m_InfoTime = time_ms(); + if (femonConfig.showbitrate) { + m_Receiver = new cFemonReceiver(Channels.GetByNumber(cDevice::CurrentChannel())->Ca(), Channels.GetByNumber(cDevice::CurrentChannel())->Vpid(), Channels.GetByNumber(cDevice::CurrentChannel())->Apid1()); + cDevice::ActualDevice()->AttachReceiver(m_Receiver); + } } eOSState cFemonOsd::ProcessKey(eKeys Key) @@ -221,7 +473,7 @@ eOSState cFemonOsd::ProcessKey(eKeys Key) switch (Key & ~k_Repeat) { case k0: if (m_Number == 0) { - // keep the "Toggle channels" function working + // keep the "Toggle channels" function working - however it isn't working now :) cRemote::Put(Key); return osContinue; } @@ -229,6 +481,7 @@ eOSState cFemonOsd::ProcessKey(eKeys Key) if (m_Number >= 0) { m_Number = m_Number * 10 + Key - k0; if (m_Number > 0) { + DrawStatusWindow(); cChannel *ch = Channels.GetByNumber(m_Number); m_InputTime = time_ms(); // Lets see if there can be any useful further input: @@ -264,13 +517,14 @@ eOSState cFemonOsd::ProcessKey(eKeys Key) m_Number = 0; } else { - m_Number = 0; m_InputTime = time_ms(); + m_Number = 0; } } break; case kOk: - m_InfoTime = time_ms(); + m_DisplayMode ^= 1; // toggle between advanced and simple display mode + DrawInfoWindow(); break; default: break; diff --git a/femonosd.h b/femonosd.h index 6d5765d..487587a 100644 --- a/femonosd.h +++ b/femonosd.h @@ -1,3 +1,11 @@ +/* + * Frontend Status Monitor plugin for the Video Disk Recorder + * + * See the README file for copyright information and how to reach the author. + * + * $Id$ + */ + #ifndef __FEMONOSD_H #define __FEMONOSD_H @@ -9,23 +17,27 @@ #include #include #include -#include // only for TS_SIZE class cFemonOsd : public cOsdObject, public cThread, public cStatus { private: bool m_Active; cOsdBase *m_Osd; - tWindowHandle m_Window; + tWindowHandle m_InfoWindow; + tWindowHandle m_StatusWindow; cFemonReceiver *m_Receiver; int m_Frontend; struct dvb_frontend_info m_FrontendInfo; int m_Number; int m_InputTime; - int m_InfoTime; - int m_Width; - int m_Height; - int m_Xpos; - int m_Ypos; + uint16_t m_SNR; + uint16_t m_Signal; + uint32_t m_BER; + uint32_t m_UNC; + fe_status_t m_FrontendStatus; + int m_DisplayMode; + cMutex* m_Mutex; + void DrawStatusWindow(void); + void DrawInfoWindow(void); protected: virtual void Action(void); diff --git a/femonreceiver.c b/femonreceiver.c index 556281d..61e0304 100644 --- a/femonreceiver.c +++ b/femonreceiver.c @@ -1,31 +1,45 @@ /* - * A Frontend Monitor plugin for the Video Disk Recorder + * Frontend Status Monitor plugin for the Video Disk Recorder * * See the README file for copyright information and how to reach the author. * * $Id$ */ +#include +#include "femoncfg.h" #include "femonreceiver.h" cFemonReceiver::cFemonReceiver(int Ca, int Vpid, int Apid) +#if VDRVERSNUM >= 10300 +:cReceiver(Ca, -1, 2, Vpid, Apid), cThread("femon receiver") +#else :cReceiver(Ca, -1, 2, Vpid, Apid) +#endif { //printf("cFemonReceiver::cFemonReceiver()\n"); - m_VPid = Vpid; - m_APid = Apid; - m_VideoCount = 0; - m_AudioCount = 0; + m_Active = false; + m_VideoPid = Vpid; + m_AudioPid = Apid; + m_VideoPacketCount = 0; + m_AudioPacketCount = 0; + m_VideoBitrate = 0.0; + m_AudioBitrate = 0.0; } cFemonReceiver::~cFemonReceiver(void) { //printf("cFemonReceiver::~cFemonReceiver()\n"); + if (m_Active) { + m_Active = false; + Cancel(5); + } } void cFemonReceiver::Activate(bool On) { //printf("cFemonReceiver::Activate()\n"); + Start(); } void cFemonReceiver::Receive(uchar *Data, int Length) @@ -33,27 +47,31 @@ void cFemonReceiver::Receive(uchar *Data, int Length) //printf("cFemonReceiver::Receive()\n"); if (Length == TS_SIZE) { int pid = ((Data[1] & 0x1f) << 8) | (Data[2]); - if (pid == m_VPid) { - m_VideoCount++; + if (pid == m_VideoPid) { + m_VideoPacketCount++; } - else if (pid == m_APid) { - m_AudioCount++; + else if (pid == m_AudioPid) { + m_AudioPacketCount++; } } } -int cFemonReceiver::VideoPacketCount(void) +void cFemonReceiver::Action(void) { - //printf("cFemonReceiver::VideoPacketCount()\n"); - int count = m_VideoCount; - m_VideoCount = 0; - return count; -} - -int cFemonReceiver::AudioPacketCount(void) -{ - //printf("cFemonReceiver::AudioPacketCount()\n"); - int count = m_AudioCount; - m_AudioCount = 0; - return count; + //printf("cFemonReceiver::Action()\n"); +#if (VDRVERSNUM < 10300) + isyslog("femon receiver: thread started (pid = %d)", getpid()); +#endif + m_Active = true; + while (m_Active) { + // should we do some averaging to smooth the bitrates ? + m_VideoBitrate = (8.0 * TS_SIZE * m_VideoPacketCount) / (femonConfig.calcinterval * 102.4 * 1024.0); + m_VideoPacketCount = 0; + m_AudioBitrate = (8.0 * TS_SIZE * m_AudioPacketCount) / (femonConfig.calcinterval * 102.4); + m_AudioPacketCount = 0; + usleep(100000L * femonConfig.calcinterval); + } +#if (VDRVERSNUM < 10300) + isyslog("femon receiver: thread stopped (pid = %d)", getpid()); +#endif } diff --git a/femonreceiver.h b/femonreceiver.h index 7b80630..ece272d 100644 --- a/femonreceiver.h +++ b/femonreceiver.h @@ -1,26 +1,39 @@ +/* + * Frontend Status Monitor plugin for the Video Disk Recorder + * + * See the README file for copyright information and how to reach the author. + * + * $Id$ + */ + #ifndef __FEMONRECEIVER_H #define __FEMONRECEIVER_H #include // only for TS_SIZE +#include #include -class cFemonReceiver : public cReceiver { +class cFemonReceiver : public cReceiver, public cThread { private: - int m_VPid; - int m_APid; - int m_VideoCount; - int m_AudioCount; + bool m_Active; + int m_VideoPid; + int m_AudioPid; + int m_VideoPacketCount; + int m_AudioPacketCount; + double m_VideoBitrate; + double m_AudioBitrate; protected: virtual void Activate(bool On); virtual void Receive(uchar *Data, int Length); + virtual void Action(void); public: cFemonReceiver(int Ca, int Vpid, int Apid); virtual ~cFemonReceiver(); - int VideoPacketCount(void); - int AudioPacketCount(void); + double VideoBitrate(void) { return m_VideoBitrate; }; + double AudioBitrate(void) { return m_AudioBitrate; }; }; #endif //__FEMONRECEIVER_H