1
0
mirror of https://github.com/rofafor/vdr-plugin-femon.git synced 2023-10-10 11:36:53 +00:00

Compare commits

..

9 Commits

Author SHA1 Message Date
Rolf Ahrenberg
22802773b8 Backported changes and fixes from version 0.1.6. 2004-09-11 04:20:00 +03:00
Rolf Ahrenberg
ca717b0425 Backported the "AC3 Stream Information" feature from version 0.1.3. 2004-06-11 04:20:00 +03:00
Rolf Ahrenberg
9ce3009e39 Backported changes and fixes from version 0.1.2. 2004-06-06 04:20:00 +03:00
Rolf Ahrenberg
b08205607c Backported "stream information" feature (from version 0.1.1). 2004-05-31 04:20:00 +03:00
Rolf Ahrenberg
ba7896b59a Fixed minor bitrate calculation errors.
Added russian translation (Thanks to Vyacheslav Dikonov).
2004-04-04 04:20:00 +03:00
Rolf Ahrenberg
43c68bcf23 Fixed channel toggling with '0' key.
Bitrate calculation thread is now canceled immediately to speed up channel switching.
2004-03-16 04:20:00 +02:00
Rolf Ahrenberg
954f09182f Fixed frequency, guard and bandwidth units in transponder information.
Added Apid2, Dpid1, Dpid2 information.
Added option to write signal information into system log.
2004-03-07 04:20:00 +02:00
Rolf Ahrenberg
23487c5972 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.
2004-03-03 04:20:00 +02:00
Rolf Ahrenberg
52b9653b42 Translation only update:
Fixed 'Deutsch' (Thanks to Olaf Henkel @ VDRPortal).
Added 'Italiano' (Thanks to Sean Carlos).
2004-02-28 04:20:00 +02:00
13 changed files with 3205 additions and 259 deletions

94
HISTORY
View File

@@ -1,5 +1,6 @@
===================================
VDR Plugin 'femon' Revision History VDR Plugin 'femon' Revision History
----------------------------------- ===================================
2004-02-15: Version 0.0.1 2004-02-15: Version 0.0.1
@@ -7,7 +8,7 @@ VDR Plugin 'femon' Revision History
2004-02-23: Version 0.0.1b 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 2004-02-26: Version 0.0.2
@@ -16,3 +17,92 @@ VDR Plugin 'femon' Revision History
2004-02-27: Version 0.0.2b 2004-02-27: Version 0.0.2b
- Some minor cosmetic changes. - Some minor cosmetic changes.
2004-02-28: Version 0.0.2c
- 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.
2004-03-07: Version 0.0.3a
- Fixed frequency, guard and bandwidth units in transponder information.
- Added Apid2, Dpid1, Dpid2 information.
- Added option to write signal information into system log.
2004-03-16: Version 0.0.3b
- Fixed channel toggling with '0' key.
- Bitrate calculation thread is now canceled immediately to speed up channel switching.
2004-04-04: Version 0.0.3c
- Fixed minor bitrate calculation errors.
- Added russian translation (Thanks to Vyacheslav Dikonov).
2004-05-31: Version 0.0.4
- Backported "stream information" feature (from version 0.1.1).
2004-06-06: Version 0.0.5
- Backported changes and fixes from version 0.1.2.
2004-06-11: Version 0.0.6
- Backported the "AC3 Stream Information" feature from version 0.1.3.
2004-09-11: Version 0.0.7
- Backported changes and fixes from version 0.1.6.
===================================
VDR Plugin 'femon' Revision History
===================================
2004-05-18: Version 0.1.0
- Updated for vdr-1.3.7 and removed compability with older versions.
2004-05-30: Version 0.1.1
- Added "Stream Information" display mode.
Toggle between different modes with 'OK' key:
.-> basic -> transponder -> stream -.
`-----------------------------------<2D>
- Added missing german translations (Thanks to Peter Marquardt).
2004-06-06: Version 0.1.2
- Fixed the channel switch bug (reported by Stefan Lucke).
- Nid/Tid/Rid are now included in translations.
- Added video format and aspect ratio symbols into status window.
2004-06-11: Version 0.1.3
- Added "AC-3 Stream Information" display mode (Thanks to Lothar Englisch).
2004-06-24: Version 0.1.4
- Added some new symbols and beautified the old ones.
- Added audio track selection feature.
- Added preliminary device switching feature (disabled at the moment).
2004-08-18: Version 0.1.5
- Fixed OSDSTATUSWIN_XC define.
- Added preliminary NTSC support (make NTSC_SYSTEM=1 plugins).
- Fixed "Setup/OSD/Use Small Fonts" bug (Thanks to Winni for reporting this one).
- Added patches directory: CA system names by Lauri Tischler.
2004-09-11: Version 0.1.6
- Yet Another Minor Release.
- Integrated the CA system names patch: "Setup / Show CA System".

View File

@@ -11,7 +11,7 @@ PLUGIN = femon
### The version number of this plugin (taken from the main source file): ### The version number of this plugin (taken from the main source file):
VERSION = $(shell grep 'static const char \*VERSION *=' $(PLUGIN).c | awk '{ print $$6 }' | sed -e 's/[";]//g') VERSION = $(shell grep 'static const char \*VERSION *=' $(PLUGIN).h | awk '{ print $$6 }' | sed -e 's/[";]//g')
### The C++ compiler and options: ### The C++ compiler and options:
@@ -44,6 +44,10 @@ INCLUDES += -I$(VDRDIR)/include -I$(DVBDIR)/include
DEFINES += -D_GNU_SOURCE -DPLUGIN_NAME_I18N='"$(PLUGIN)"' DEFINES += -D_GNU_SOURCE -DPLUGIN_NAME_I18N='"$(PLUGIN)"'
ifdef NTSC_SYSTEM
DEFINES += -DNTSC_SYSTEM
endif
### The object files (add further files here): ### The object files (add further files here):
OBJS = femon.o femonosd.o femonreceiver.o femoncfg.o femoni18n.o OBJS = femon.o femonosd.o femonreceiver.o femoncfg.o femoni18n.o

101
README
View File

@@ -10,35 +10,86 @@ See the file COPYING for license information.
Requirements: Requirements:
Ph.D. in Astro Physics and preferably a six-pack waiting in a fridge. VDR & DVB. BMW & Ph.D.. BEER. YARRR!
Description: Description:
DVB Frontend Status Monitor is a plugin that displays a few signal quality parameters DVB Frontend Status Monitor is a plugin that displays some signal information
of the tuned channel on your screen. You can zap through all your channels and the parameters of the current tuned channel on OSD. You can zap through all your
plugin should be monitoring always the right frontend *fingers crossed*. A short channels and the plugin should be monitoring always the right frontend. The
message is shown at the bottom line to help the DVB card identification after each transponder and stream information are also available in advanced display modes.
channel switch and OK press.
The plugin is based on a neat console frontend status monitor application called The plugin is based on a neat console frontend status monitor application
'femon' by Johannes Stezenbach <js@convergence.de> (see DVB-apps/szap/femon.c for called 'femon' by Johannes Stezenbach (see DVB-apps/szap/femon.c for further
further information). The other parts of plugin code are borrowed from the information). The other parts of plugin code are borrowed from the excellent
excellent OSD Picture-In-Picture plugin by Sascha Volkenandt <sascha@akv-soft.de> 'OSD Picture-In-Picture' plugin by Sascha Volkenandt and Andreas Regel. The
and Andreas Regel <andreas.regel@powarman.de>. Props to Sascha for being brave bitrate calculation algorithm originates from the 'dvbstream' application by
enough to test this piece of junk and ofcourse for german translations. The bitrate Dave Chapman and the stream information routines from the 'libdvb' library by
calculation algorithm is originally copied from dvbstream application by Dave Chapman Metzler Brothers.
<dave@dchapman.com>.
Shortcomings / Todo list: Terminology:
- 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 |## Channel Name ######################### [DD][AR][VF][A][D]|
spare time. |[=====Signal Strength in % ==============|=================]|
- The plugin supports only those DVB cards with _one_ frontend (do any cards with |[=====Signal-to-Noise Ratio in % ========|=================]|
multiple frontends even exist?), because I haven't yet figured howto do it without | STR: #0000 (0%) BER: #00000000 Video: 0 Mbit/s |
patching the VDR core. | SNR: #0000 (0%) UNC: #00000000 Audio: 0 kbit/s |
| [LOCK] [SIGNAL] [CARRIER] [VITERBI] [SYNC] |
--------------------------------------------------------------
STR - Signal strength
SNR - Signal-to-noise ratio
BER - Bit error rate
UNC - Uncorrected blocks
Video - Calculated video bitrate in Mbit/s
Audio - Calculated audio / AC-3 bitrate in kbit/s
LOCK - Everything's working...
SIGNAL - Found something above the noise level
CARRIER - Found a DVB signal
VITERBI - FEC (forward error correction) is stable
SYNC - Found sync bytes
DD - AC-3 stream (optional)
AR - Aspect Ratio: 1:1/4:3/16:9/2.21:1 (optional)
VF - Video format: PAL/NTSC (optional)
A - Audio track: 1..2 (optional)
D - Device number: 0..3 (optional)
Controls:
ChanUp/ChanDn - Switch channel up/down
Up/Down - Switch channel up/down
0-9 - Select channel
Ok - Switch between display modes: basic, transponder, stream, AC-3
Right/Left - Switch to next/previous device that provides the current channel
Green - Select language (APID)
Back - Exit plugin
Installation:
cd /put/your/path/here/VDR/PLUGINS/src
tar -xzf /put/your/path/here/vdr-femon-X.Y.Z.tgz
ln -s femon-X.Y.Z femon
cd /put/your/path/here/VDR
make
make plugins
./vdr -P femon
Notes:
- 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 - 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. ttxtsubs, but closing and reopening the femon plugin might help temporarily as
Btw., this same thing happens with OSDTeletext plugin too :) 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 - Disable the stream analyze to speed up heavy zapping sessions.
the ElchiAIO4a+ patch to maximize the *wow* effect :) - The signal strength and signal-to-noise ratio values are comparable only
between the same brand/model frontends. Due to the lack of proper frontend
specifications those values cannot be calculated into any real units.
- Shrinked OSD is available for NTSC users: make NTSC_SYSTEM=1
- The device switching feature is still non-functional.
"Femon - A real womon who lives according to her natural feminine inclinations."

81
femon.c
View File

@@ -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. * See the README file for copyright information and how to reach the author.
* *
@@ -12,6 +12,10 @@
#include "femonosd.h" #include "femonosd.h"
#include "femon.h" #include "femon.h"
#if VDRVERSNUM && VDRVERSNUM >= 10307
#error "You don't exist! Go away!"
#endif
cPluginFemon::cPluginFemon(void) cPluginFemon::cPluginFemon(void)
{ {
// Initialize any member variables here. // Initialize any member variables here.
@@ -63,33 +67,78 @@ cOsdObject *cPluginFemon::MainMenuAction(void)
bool cPluginFemon::SetupParse(const char *Name, const char *Value) bool cPluginFemon::SetupParse(const char *Name, const char *Value)
{ {
// Parse your own setup parameters and store their values. // Parse your own setup parameters and store their values.
if (!strcasecmp(Name, "HideMenu")) femonConfig.hidemenu = atoi(Value); if (!strcasecmp(Name, "HideMenu")) femonConfig.hidemenu = atoi(Value);
else if (!strcasecmp(Name, "Position")) femonConfig.position = atoi(Value); else if (!strcasecmp(Name, "SyslogOutput")) femonConfig.syslogoutput = atoi(Value);
else if (!strcasecmp(Name, "Interval")) femonConfig.interval = atoi(Value); else if (!strcasecmp(Name, "DisplayMode")) femonConfig.displaymode = atoi(Value);
else if (!strcasecmp(Name, "RedLimit")) femonConfig.redlimit = atoi(Value); else if (!strcasecmp(Name, "Position")) femonConfig.position = atoi(Value);
else if (!strcasecmp(Name, "GreenLimit")) femonConfig.greenlimit = atoi(Value); else if (!strcasecmp(Name, "ShowCASystem")) femonConfig.showcasystem = 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, "AnalStream")) femonConfig.analyzestream = atoi(Value);
else if (!strcasecmp(Name, "CalcInterval")) femonConfig.calcinterval = atoi(Value);
else else
return false; return false;
if (femonConfig.displaymode < 0 || femonConfig.displaymode >= modeMaxNumber) femonConfig.displaymode = 0;
return true; return true;
} }
cMenuFemonSetup::cMenuFemonSetup(void) cMenuFemonSetup::cMenuFemonSetup(void)
{ {
Add(new cMenuEditBoolItem(tr("Hide Mainmenu Entry"), &femonConfig.hidemenu, tr("no"), tr("yes"))); dispmodes[modeBasic] = tr("basic");
Add(new cMenuEditBoolItem(tr("Position"), &femonConfig.position, tr("bottom"), tr("top"))); dispmodes[modeTransponder] = tr("transponder");
Add(new cMenuEditIntItem( tr("Update Interval [0.1s]"), &femonConfig.interval, 5, 50)); dispmodes[modeStream] = tr("stream");
Add(new cMenuEditIntItem( tr("Red Limit [%]"), &femonConfig.redlimit, 1, 50)); dispmodes[modeAC3] = tr("AC-3");
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("Use Syslog Output"), &femonConfig.syslogoutput, tr("no"), tr("yes")));
Add(new cMenuEditStraItem( tr("Default Display Mode"), &femonConfig.displaymode, modeMaxNumber, dispmodes));
Add(new cMenuEditBoolItem( tr("Position"), &femonConfig.position, tr("bottom"), tr("top")));
Add(new cMenuEditBoolItem( tr("Show CA System"), &femonConfig.showcasystem, tr("no"), tr("yes")));
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("Analyze Stream"), &femonConfig.analyzestream, tr("no"), tr("yes")));
if (femonConfig.analyzestream)
Add(new cMenuEditIntItem(tr("Calculation Interval [0.1s]"), &femonConfig.calcinterval, 1, 100));
SetCurrent(Get(current));
Display();
} }
void cMenuFemonSetup::Store(void) void cMenuFemonSetup::Store(void)
{ {
SetupStore("HideMenu", femonConfig.hidemenu); SetupStore("HideMenu", femonConfig.hidemenu);
SetupStore("Position", femonConfig.position); SetupStore("SyslogOutput", femonConfig.syslogoutput);
SetupStore("Interval", femonConfig.interval); SetupStore("DisplayMode", femonConfig.displaymode);
SetupStore("RedLimit", femonConfig.redlimit); SetupStore("Position", femonConfig.position);
SetupStore("GreenLimit", femonConfig.greenlimit); SetupStore("ShowCASystem", femonConfig.showcasystem);
SetupStore("RedLimit", femonConfig.redlimit);
SetupStore("GreenLimit", femonConfig.greenlimit);
SetupStore("UpdateInterval", femonConfig.updateinterval);
SetupStore("AnalStream", femonConfig.analyzestream);
SetupStore("CalcInterval", femonConfig.calcinterval);
}
eOSState cMenuFemonSetup::ProcessKey(eKeys Key)
{
int oldAnalyzestream = femonConfig.analyzestream;
eOSState state = cMenuSetupPage::ProcessKey(Key);
if (Key != kNone && (femonConfig.analyzestream != oldAnalyzestream)) {
Setup();
}
return state;
} }
cMenuSetupPage *cPluginFemon::SetupMenu(void) cMenuSetupPage *cPluginFemon::SetupMenu(void)

24
femon.h
View File

@@ -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 #ifndef __FEMON_H
#define __FEMON_H #define __FEMON_H
#include <vdr/plugin.h> #include <vdr/plugin.h>
static const char *VERSION = "0.0.2b"; static const char *VERSION = "0.0.7";
static const char *DESCRIPTION = "DVB Signal Quality Monitor (OSD)"; static const char *DESCRIPTION = "DVB Signal Information Monitor (OSD)";
static const char *MAINMENUENTRY = "Signal Quality"; static const char *MAINMENUENTRY = "Signal Information";
class cPluginFemon : public cPlugin { class cPluginFemon : public cPlugin {
private: private:
@@ -27,11 +35,15 @@ public:
}; };
class cMenuFemonSetup : public cMenuSetupPage { class cMenuFemonSetup : public cMenuSetupPage {
private:
const char *dispmodes[modeMaxNumber];
virtual void Setup(void);
protected:
virtual eOSState ProcessKey(eKeys Key);
virtual void Store(void);
public: public:
cMenuFemonSetup(void); cMenuFemonSetup(void);
protected: };
virtual void Store(void);
};
#endif //__FEMON_H #endif //__FEMON_H

View File

@@ -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. * See the README file for copyright information and how to reach the author.
* *
@@ -12,9 +12,14 @@ cFemonConfig femonConfig;
cFemonConfig::cFemonConfig(void) cFemonConfig::cFemonConfig(void)
{ {
hidemenu = 0; hidemenu = 0;
position = 1; displaymode = 0;
interval = 10; position = 1;
redlimit = 33; redlimit = 33;
greenlimit = 66; greenlimit = 66;
updateinterval = 5;
analyzestream = 1;
calcinterval = 20;
syslogoutput = 0;
showcasystem = 0;
} }

View File

@@ -1,15 +1,36 @@
/*
* 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 #ifndef __FEMONCFG_H
#define __FEMONCFG_H #define __FEMONCFG_H
enum dispModes {
modeBasic,
modeTransponder,
modeStream,
modeAC3,
modeMaxNumber
};
struct cFemonConfig struct cFemonConfig
{ {
public: public:
cFemonConfig(void); cFemonConfig(void);
int hidemenu; int hidemenu;
int position; int displaymode;
int interval; int position;
int redlimit; int redlimit;
int greenlimit; int greenlimit;
int updateinterval;
int analyzestream;
int calcinterval;
int syslogoutput;
int showcasystem;
}; };
extern cFemonConfig femonConfig; extern cFemonConfig femonConfig;

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,15 @@
/*
* 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 #ifndef __FEMONI18N_H
#define __FEMONI18N_H #define __FEMONI18N_H
#include <vdr/config.h> // for VDRVERSNUM
#include <vdr/i18n.h> #include <vdr/i18n.h>
extern const tI18nPhrase Phrases[]; extern const tI18nPhrase Phrases[];

View File

@@ -1,42 +1,72 @@
/* /*
* 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. * See the README file for copyright information and how to reach the author.
* *
* $Id$ * $Id$
*/ */
#include <ctype.h>
#include "femoncfg.h" #include "femoncfg.h"
#include "femoni18n.h"
#include "femonreceiver.h" #include "femonreceiver.h"
#include "femonosd.h" #include "femonosd.h"
#define FE_DEVICE "/dev/dvb/adapter%d/frontend%d" #if (VDRVERSNUM < 10300) && !defined(ELCHIAIOVERSION)
#define CHANNELINPUT_TIMEOUT 1000 #warning You should consider using the small fonts!
#define CHANNELINFO_TIMEOUT 5000 #endif
#define OSDHEIGHT 5
#define FRONTEND_DEVICE "/dev/dvb/adapter%d/frontend%d"
#define CHANNELINPUT_TIMEOUT 1000
#ifdef NTSC_SYSTEM
#define SCREENHEIGHT 480 // in pixels
#define OSDHEIGHT 420 // in pixels
#else
#define SCREENHEIGHT 576 // in pixels
#define OSDHEIGHT 480 // in pixels
#endif
#define SCREENWIDTH 720 // in pixels
#define OSDWIDTH 600 // in pixels
#define OSDINFOHEIGHT ((cOsd::LineHeight() - 2) * 11) // in pixels (11 rows)
#define OSDSTATUSHEIGHT ((cOsd::LineHeight() - 2) * 6) // in pixels (6 rows)
#define OSDINFOWIN_Y(offset) (femonConfig.position ? (OSDHEIGHT - OSDINFOHEIGHT + offset) : offset)
#define OSDINFOWIN_X(col) ((col == 4) ? 455 : (col == 3) ? 305 : (col == 2) ? 155 : 15)
#define OSDSTATUSWIN_Y(offset) (femonConfig.position ? offset : (OSDHEIGHT - OSDSTATUSHEIGHT + offset))
#define OSDSTATUSWIN_X(col) ((col == 7) ? 475 : (col == 6) ? 410 : (col == 5) ? 275 : (col == 4) ? 220 : (col == 3) ? 125 : (col == 2) ? 70 : 15)
#define OSDSTATUSWIN_XC(col,txt) (((col - 1) * OSDWIDTH / 5) + ((OSDWIDTH / 5 - cOsd::WidthInCells(txt) * cOsd::CellWidth()) / 2))
#define BARWIDTH(x) (OSDWIDTH * x / 100)
#define DELTA 2
cFemonOsd::cFemonOsd(void) cFemonOsd::cFemonOsd(void)
#if VDRVERSNUM >= 10300 #if VDRVERSNUM >= 10300
:cOsdObject(true), cThread("femon plugin") :cOsdObject(true), cThread("femon osd")
#else #else
:cOsdObject(true), cThread() :cOsdObject(true)
#endif #endif
{ {
//printf("cFemonOsd::cFemonOsd()\n"); //printf("cFemonOsd::cFemonOsd()\n");
m_Osd = NULL; m_Osd = NULL;
m_Window = -1;
m_Receiver = NULL; m_Receiver = NULL;
m_Frontend = -1; m_Frontend = -1;
m_Active = false; m_Active = false;
m_Number = 0; m_Number = 0;
m_OldNumber = 0;
m_InputTime = 0; m_InputTime = 0;
m_InfoTime = 0; m_Signal = 0;
m_Width = Setup.OSDwidth * cOsd::CellWidth(); m_SNR = 0;
m_Height = OSDHEIGHT * cOsd::LineHeight(); m_BER = 0;
m_Xpos = (720 - m_Width) / 2; m_UNC = 0;
m_Ypos = (576 - Setup.OSDheight * cOsd::LineHeight()) / 2 + ( femonConfig.position ? 0 : (Setup.OSDheight - OSDHEIGHT) * cOsd::LineHeight()); m_DisplayMode = femonConfig.displaymode;
#if (VDRVERSNUM >= 10300) || defined(ELCHIAIOVERSION)
m_Font = fontSml;
#else
m_Font = fontOsd;
#endif
m_Mutex = new cMutex();
} }
cFemonOsd::~cFemonOsd(void) cFemonOsd::~cFemonOsd(void)
{ {
//printf("cFemonOsd::~cFemonOsd()\n"); //printf("cFemonOsd::~cFemonOsd()\n");
@@ -50,97 +80,586 @@ cFemonOsd::~cFemonOsd(void)
delete m_Osd; 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 offset = 0;
cChannel *channel = Channels.GetByNumber(cDevice::CurrentChannel());
if (m_Osd) {
#if (VDRVERSNUM >= 10300) || defined(ELCHIAIOVERSION)
eDvbFont OldFont = m_Osd->SetFont(m_Font);
#endif
m_Osd->Fill(0, OSDSTATUSWIN_Y(0), OSDWIDTH, OSDSTATUSWIN_Y(OSDSTATUSHEIGHT), clrBackground, m_StatusWindow);
snprintf(buf, sizeof(buf), "%d%s %s", m_Number ? m_Number : channel->Number(), m_Number ? "-" : "", channel->Name());
m_Osd->Fill(0, OSDSTATUSWIN_Y(offset), OSDWIDTH, OSDSTATUSWIN_Y(offset+cOsd::LineHeight()-1), clrWhite, m_StatusWindow);
m_Osd->Text(OSDSTATUSWIN_X(1), OSDSTATUSWIN_Y(offset), buf, clrBlack, clrWhite, m_StatusWindow);
offset += cOsd::LineHeight();
if (signal > 0) {
signal = BARWIDTH(signal);
m_Osd->Fill(0, OSDSTATUSWIN_Y(offset+3), min(BARWIDTH(femonConfig.redlimit), signal), OSDSTATUSWIN_Y(offset+cOsd::LineHeight()-3), clrRed, m_StatusWindow);
if (signal > BARWIDTH(femonConfig.redlimit)) {
m_Osd->Fill(BARWIDTH(femonConfig.redlimit), OSDSTATUSWIN_Y(offset+3), min((OSDWIDTH * femonConfig.greenlimit / 100), signal), OSDSTATUSWIN_Y(offset+cOsd::LineHeight()-3), clrYellow, m_StatusWindow);
}
if (signal > BARWIDTH(femonConfig.greenlimit)) {
m_Osd->Fill(BARWIDTH(femonConfig.greenlimit), OSDSTATUSWIN_Y(offset+3), signal, OSDSTATUSWIN_Y(offset+cOsd::LineHeight()-3), clrGreen, m_StatusWindow);
}
}
offset += cOsd::LineHeight() - DELTA;
if (snr > 0) {
snr = BARWIDTH(snr);
m_Osd->Fill(0, OSDSTATUSWIN_Y(offset+3), min(BARWIDTH(femonConfig.redlimit), snr), OSDSTATUSWIN_Y(offset+cOsd::LineHeight()-3), clrRed, m_StatusWindow);
if (snr > BARWIDTH(femonConfig.redlimit)) {
m_Osd->Fill(BARWIDTH(femonConfig.redlimit), OSDSTATUSWIN_Y(offset+3), min(BARWIDTH(femonConfig.greenlimit), snr), OSDSTATUSWIN_Y(offset+cOsd::LineHeight()-3), clrYellow, m_StatusWindow);
}
if (snr > BARWIDTH(femonConfig.greenlimit)) {
m_Osd->Fill(BARWIDTH(femonConfig.greenlimit), OSDSTATUSWIN_Y(offset+3), snr, OSDSTATUSWIN_Y(offset+cOsd::LineHeight()-3), clrGreen, m_StatusWindow);
}
}
offset += cOsd::LineHeight() - DELTA;
m_Osd->Text(OSDSTATUSWIN_X(1), OSDSTATUSWIN_Y(offset), "STR:", clrWhite, clrBackground, m_StatusWindow);
snprintf(buf, sizeof(buf), "%04x", m_Signal);
m_Osd->Text(OSDSTATUSWIN_X(2), OSDSTATUSWIN_Y(offset), buf, clrWhite, clrBackground, m_StatusWindow);
snprintf(buf, sizeof(buf), "(%2d%%)", m_Signal / 655);
m_Osd->Text(OSDSTATUSWIN_X(3), OSDSTATUSWIN_Y(offset), buf, clrWhite, clrBackground, m_StatusWindow);
m_Osd->Text(OSDSTATUSWIN_X(4), OSDSTATUSWIN_Y(offset), "BER:", clrWhite, clrBackground, m_StatusWindow);
snprintf(buf, sizeof(buf), "%08x", m_BER);
m_Osd->Text(OSDSTATUSWIN_X(5), OSDSTATUSWIN_Y(offset), buf, clrWhite, clrBackground, m_StatusWindow);
snprintf(buf, sizeof(buf), "%s:", tr("Video"));
m_Osd->Text(OSDSTATUSWIN_X(6), OSDSTATUSWIN_Y(offset), buf, clrWhite, clrBackground, m_StatusWindow);
if (m_Receiver) snprintf(buf, sizeof(buf), "%.2f %s", m_Receiver->VideoBitrate(), tr("Mbit/s"));
else snprintf(buf, sizeof(buf), "--- %s", tr("Mbit/s"));
m_Osd->Text(OSDSTATUSWIN_X(7), OSDSTATUSWIN_Y(offset), buf, clrWhite, clrBackground, m_StatusWindow);
offset += cOsd::LineHeight() - DELTA;
m_Osd->Text(OSDSTATUSWIN_X(1), OSDSTATUSWIN_Y(offset), "SNR:", clrWhite, clrBackground, m_StatusWindow);
snprintf(buf, sizeof(buf), "%04x", m_SNR);
m_Osd->Text(OSDSTATUSWIN_X(2), OSDSTATUSWIN_Y(offset), buf, clrWhite, clrBackground, m_StatusWindow);
snprintf(buf, sizeof(buf), "(%2d%%)", m_SNR / 655);
m_Osd->Text(OSDSTATUSWIN_X(3), OSDSTATUSWIN_Y(offset), buf, clrWhite, clrBackground, m_StatusWindow);
m_Osd->Text(OSDSTATUSWIN_X(4), OSDSTATUSWIN_Y(offset), "UNC:", clrWhite, clrBackground, m_StatusWindow);
snprintf(buf, sizeof(buf), "%08x", m_UNC);
m_Osd->Text(OSDSTATUSWIN_X(5), OSDSTATUSWIN_Y(offset), buf, clrWhite, clrBackground, m_StatusWindow);
snprintf(buf, sizeof(buf), "%s:", (m_Receiver && m_Receiver->AC3Valid()) ? tr("AC-3") : tr("Audio"));
m_Osd->Text(OSDSTATUSWIN_X(6), OSDSTATUSWIN_Y(offset), buf, clrWhite, clrBackground, m_StatusWindow);
if (m_Receiver) snprintf(buf, sizeof(buf), "%.0f %s", m_Receiver->AC3Valid() ? m_Receiver->AC3Bitrate() : m_Receiver->AudioBitrate(), tr("kbit/s"));
else snprintf(buf, sizeof(buf), "--- %s", tr("kbit/s"));
m_Osd->Text(OSDSTATUSWIN_X(7), OSDSTATUSWIN_Y(offset), buf, clrWhite, clrBackground, m_StatusWindow);
offset += cOsd::LineHeight() - DELTA;
m_Osd->Text(OSDSTATUSWIN_XC(1,tr("LOCK")), OSDSTATUSWIN_Y(offset), tr("LOCK"), (m_FrontendStatus & FE_HAS_LOCK) ? clrYellow : clrBlack, clrBackground, m_StatusWindow);
m_Osd->Text(OSDSTATUSWIN_XC(2,tr("SIGNAL")), OSDSTATUSWIN_Y(offset), tr("SIGNAL"), (m_FrontendStatus & FE_HAS_SIGNAL) ? clrYellow : clrBlack, clrBackground, m_StatusWindow);
m_Osd->Text(OSDSTATUSWIN_XC(3,tr("CARRIER")), OSDSTATUSWIN_Y(offset), tr("CARRIER"),(m_FrontendStatus & FE_HAS_CARRIER)? clrYellow : clrBlack, clrBackground, m_StatusWindow);
m_Osd->Text(OSDSTATUSWIN_XC(4,tr("VITERBI")), OSDSTATUSWIN_Y(offset), tr("VITERBI"),(m_FrontendStatus & FE_HAS_VITERBI)? clrYellow : clrBlack, clrBackground, m_StatusWindow);
m_Osd->Text(OSDSTATUSWIN_XC(5,tr("SYNC")), OSDSTATUSWIN_Y(offset), tr("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 offset = 0;
int value = 0;
double dvalue = 0.0;
cChannel *channel = Channels.GetByNumber(cDevice::CurrentChannel());
if (m_Osd) {
#if (VDRVERSNUM >= 10300) || defined(ELCHIAIOVERSION)
eDvbFont OldFont = m_Osd->SetFont(m_Font);
#endif
if (m_DisplayMode == modeTransponder) {
m_Osd->Fill(0, OSDINFOWIN_Y(0), OSDWIDTH, OSDINFOWIN_Y(OSDINFOHEIGHT), clrBackground, m_InfoWindow);
m_Osd->Fill(0, OSDINFOWIN_Y(offset), OSDWIDTH, OSDINFOWIN_Y(offset+cOsd::LineHeight()-1), clrWhite, m_InfoWindow);
m_Osd->Text( OSDINFOWIN_X(1), OSDINFOWIN_Y(offset), tr("Transponder Information"), clrBackground, clrWhite, m_InfoWindow);
offset += cOsd::LineHeight();
m_Osd->Text(OSDINFOWIN_X(1), OSDINFOWIN_Y(offset), tr("Vpid"), clrWhite, clrBackground, m_InfoWindow);
snprintf(buf, sizeof(buf), "%d", channel->Vpid());
m_Osd->Text(OSDINFOWIN_X(2), OSDINFOWIN_Y(offset), buf, clrYellow, clrBackground, m_InfoWindow);
m_Osd->Text(OSDINFOWIN_X(3), OSDINFOWIN_Y(offset), tr("Ppid"), clrWhite, clrBackground, m_InfoWindow);
snprintf(buf, sizeof(buf), "%d", channel->Ppid());
m_Osd->Text(OSDINFOWIN_X(4), OSDINFOWIN_Y(offset), buf, clrYellow, clrBackground, m_InfoWindow);
offset += cOsd::LineHeight() - DELTA;
m_Osd->Text(OSDINFOWIN_X(1), OSDINFOWIN_Y(offset), tr("Apid1"), clrWhite, clrBackground, m_InfoWindow);
value = channel->Apid2();
if (value) snprintf(buf, sizeof(buf), "%d, %d", channel->Apid1(), value);
else snprintf(buf, sizeof(buf), "%d", channel->Apid1());
m_Osd->Text(OSDINFOWIN_X(2), OSDINFOWIN_Y(offset), buf, clrYellow, clrBackground, m_InfoWindow);
m_Osd->Text(OSDINFOWIN_X(3), OSDINFOWIN_Y(offset), tr("Dpid1"), clrWhite, clrBackground, m_InfoWindow);
value = channel->Dpid2();
if (value) snprintf(buf, sizeof(buf), "%d, %d", channel->Dpid1(), value);
else snprintf(buf, sizeof(buf), "%d", channel->Dpid1());
m_Osd->Text(OSDINFOWIN_X(4), OSDINFOWIN_Y(offset), buf, clrYellow, clrBackground, m_InfoWindow);
offset += cOsd::LineHeight() - DELTA;
m_Osd->Text(OSDINFOWIN_X(1), OSDINFOWIN_Y(offset), tr("CA"), clrWhite, clrBackground, m_InfoWindow);
value = channel->Ca();
if (femonConfig.showcasystem) {
/* http://www.dvb.org/index.php?id=174 */
switch (value) {
case 0x0000:
/* Reserved */
snprintf(buf, sizeof(buf), "%s", tr("Free to Air"));
break;
case 0x0001 ... 0x00FF:
/* Standardized systems */
snprintf(buf, sizeof(buf), "%s", tr("Fixed"));
break;
case 0x0100 ... 0x01FF:
/* Canal Plus */
snprintf(buf, sizeof(buf), "%s", tr("SECA/Mediaguard"));
break;
case 0x0500 ... 0x05FF:
/* France Telecom */
snprintf(buf, sizeof(buf), "%s", tr("Viaccess"));
break;
case 0x0600 ... 0x06FF:
/* Irdeto */
snprintf(buf, sizeof(buf), "%s", tr("Irdeto"));
break;
case 0x0900 ... 0x09FF:
/* News Datacom */
snprintf(buf, sizeof(buf), "%s", tr("NDS/Videoguard"));
break;
case 0x0B00 ... 0x0BFF:
/* Norwegian Telekom */
snprintf(buf, sizeof(buf), "%s", tr("Conax"));
break;
case 0x0D00 ... 0x0DFF:
/* Philips */
snprintf(buf, sizeof(buf), "%s", tr("CryptoWorks"));
break;
case 0x0E00 ... 0x0EFF:
/* Scientific Atlanta */
snprintf(buf, sizeof(buf), "%s", tr("PowerVu"));
break;
case 0x1200 ... 0x12FF:
/* BellVu Express */
snprintf(buf, sizeof(buf), "%s", tr("NagraVision"));
break;
case 0x1700 ... 0x17FF:
/* BetaTechnik */
snprintf(buf, sizeof(buf), "%s", tr("BetaCrypt"));
break;
case 0x1800 ... 0x18FF:
/* Kudelski SA */
snprintf(buf, sizeof(buf), "%s", tr("NagraVision"));
break;
case 0x4A60 ... 0x4A6F:
/* @Sky */
snprintf(buf, sizeof(buf), "%s", tr("SkyCrypt"));
break;
default:
snprintf(buf, sizeof(buf), "%X", value);
break;
}
}
else {
snprintf(buf, sizeof(buf), "%X", value);
}
m_Osd->Text(OSDINFOWIN_X(2), OSDINFOWIN_Y(offset), buf, clrYellow, clrBackground, m_InfoWindow);
m_Osd->Text(OSDINFOWIN_X(3), OSDINFOWIN_Y(offset), tr("Tpid"), clrWhite, clrBackground, m_InfoWindow);
snprintf(buf, sizeof(buf), "%d", channel->Tpid());
m_Osd->Text(OSDINFOWIN_X(4), OSDINFOWIN_Y(offset), buf, clrYellow, clrBackground, m_InfoWindow);
offset += cOsd::LineHeight() - DELTA;
m_Osd->Text(OSDINFOWIN_X(1), OSDINFOWIN_Y(offset), tr("Sid"), clrWhite, clrBackground, m_InfoWindow);
snprintf(buf, sizeof(buf), "%d", channel->Sid());
m_Osd->Text(OSDINFOWIN_X(2), OSDINFOWIN_Y(offset), buf, clrYellow, clrBackground, m_InfoWindow);
#if (VDRVERSNUM >= 10300)
m_Osd->Text(OSDINFOWIN_X(3), OSDINFOWIN_Y(offset), tr("Nid"), clrWhite, clrBackground, m_InfoWindow);
snprintf(buf, sizeof(buf), "%d", channel->Nid());
m_Osd->Text(OSDINFOWIN_X(4), OSDINFOWIN_Y(offset), buf, clrYellow, clrBackground, m_InfoWindow);
offset += cOsd::LineHeight() - DELTA;
m_Osd->Text(OSDINFOWIN_X(1), OSDINFOWIN_Y(offset), tr("Tid"), clrWhite, clrBackground, m_InfoWindow);
snprintf(buf, sizeof(buf), "%d", channel->Tid());
m_Osd->Text(OSDINFOWIN_X(2), OSDINFOWIN_Y(offset), buf, clrYellow, clrBackground, m_InfoWindow);
m_Osd->Text(OSDINFOWIN_X(3), OSDINFOWIN_Y(offset), tr("Rid"), clrWhite, clrBackground, m_InfoWindow);
snprintf(buf, sizeof(buf), "%d", channel->Rid());
m_Osd->Text(OSDINFOWIN_X(4), OSDINFOWIN_Y(offset), buf, clrYellow, clrBackground, m_InfoWindow);
#endif
offset += cOsd::LineHeight() - DELTA;
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(OSDINFOWIN_X(1), OSDINFOWIN_Y(offset), buf, clrYellow, clrBackground, m_InfoWindow);
offset += cOsd::LineHeight() - DELTA;
m_Osd->Text(OSDINFOWIN_X(1), OSDINFOWIN_Y(offset), tr("Frequency"), clrWhite, clrBackground, m_InfoWindow);
value = channel->Frequency();
while (value > 20000) value /= 1000;
snprintf(buf, sizeof(buf), "%d %s", value, tr("MHz"));
m_Osd->Text(OSDINFOWIN_X(2), OSDINFOWIN_Y(offset), buf, clrYellow, clrBackground, m_InfoWindow);
m_Osd->Text(OSDINFOWIN_X(3), OSDINFOWIN_Y(offset), tr("Source"), clrWhite, clrBackground, m_InfoWindow);
snprintf(buf, sizeof(buf), "%s", cSource::ToString(channel->Source()));
m_Osd->Text(OSDINFOWIN_X(4), OSDINFOWIN_Y(offset), buf, clrYellow, clrBackground, m_InfoWindow);
offset += cOsd::LineHeight() - DELTA;
m_Osd->Text(OSDINFOWIN_X(1), OSDINFOWIN_Y(offset), tr("Srate"), clrWhite, clrBackground, m_InfoWindow);
snprintf(buf, sizeof(buf), "%d", channel->Srate());
m_Osd->Text(OSDINFOWIN_X(2), OSDINFOWIN_Y(offset), buf, clrYellow, clrBackground, m_InfoWindow);
m_Osd->Text(OSDINFOWIN_X(3), OSDINFOWIN_Y(offset), tr("Polarization"), clrWhite, clrBackground, m_InfoWindow);
snprintf(buf, sizeof(buf), "%c", toupper(channel->Polarization()));
m_Osd->Text(OSDINFOWIN_X(4), OSDINFOWIN_Y(offset), buf, clrYellow, clrBackground, m_InfoWindow);
offset += cOsd::LineHeight() - DELTA;
m_Osd->Text(OSDINFOWIN_X(1), OSDINFOWIN_Y(offset), tr("Inversion"), clrWhite, clrBackground, m_InfoWindow);
value = channel->Inversion();
if (value == INVERSION_OFF) snprintf(buf, sizeof(buf), tr("Off"));
else if (value == INVERSION_ON) snprintf(buf, sizeof(buf), tr("On"));
else /*INVERSION_AUTO*/ snprintf(buf, sizeof(buf), tr("Auto"));
m_Osd->Text(OSDINFOWIN_X(2), OSDINFOWIN_Y(offset), buf, clrYellow, clrBackground, m_InfoWindow);
m_Osd->Text(OSDINFOWIN_X(3), OSDINFOWIN_Y(offset), tr("CoderateH"), clrWhite, clrBackground, m_InfoWindow);
value = channel->CoderateH();
if (value == FEC_NONE) snprintf(buf, sizeof(buf), tr("None"));
else if (value == FEC_1_2) snprintf(buf, sizeof(buf), "1/2");
else if (value == FEC_2_3) snprintf(buf, sizeof(buf), "2/3");
else if (value == FEC_3_4) snprintf(buf, sizeof(buf), "3/4");
else if (value == FEC_4_5) snprintf(buf, sizeof(buf), "4/5");
else if (value == FEC_5_6) snprintf(buf, sizeof(buf), "5/6");
else if (value == FEC_6_7) snprintf(buf, sizeof(buf), "6/7");
else if (value == FEC_7_8) snprintf(buf, sizeof(buf), "7/8");
else if (value == FEC_8_9) snprintf(buf, sizeof(buf), "8/9");
else /*FEC_AUTO*/ snprintf(buf, sizeof(buf), tr("Auto"));
m_Osd->Text(OSDINFOWIN_X(4), OSDINFOWIN_Y(offset), 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(OSDINFOWIN_X(1), OSDINFOWIN_Y(offset), buf, clrYellow, clrBackground, m_InfoWindow);
offset += cOsd::LineHeight() - DELTA;
m_Osd->Text(OSDINFOWIN_X(1), OSDINFOWIN_Y(offset), tr("Frequency"), clrWhite, clrBackground, m_InfoWindow);
value = channel->Frequency();
while (value > 20000) value /= 1000;
snprintf(buf, sizeof(buf), "%d %s", value, tr("MHz"));
m_Osd->Text(OSDINFOWIN_X(2), OSDINFOWIN_Y(offset), buf, clrYellow, clrBackground, m_InfoWindow);
m_Osd->Text(OSDINFOWIN_X(3), OSDINFOWIN_Y(offset), tr("Source"), clrWhite, clrBackground, m_InfoWindow);
snprintf(buf, sizeof(buf), "%s", cSource::ToString(channel->Source()));
m_Osd->Text(OSDINFOWIN_X(4), OSDINFOWIN_Y(offset), buf, clrYellow, clrBackground, m_InfoWindow);
offset += cOsd::LineHeight() - DELTA;
m_Osd->Text(OSDINFOWIN_X(1), OSDINFOWIN_Y(offset), tr("Srate"), clrWhite, clrBackground, m_InfoWindow);
snprintf(buf, sizeof(buf), "%d", channel->Srate());
m_Osd->Text(OSDINFOWIN_X(2), OSDINFOWIN_Y(offset), buf, clrYellow, clrBackground, m_InfoWindow);
m_Osd->Text(OSDINFOWIN_X(3), OSDINFOWIN_Y(offset), tr("Modulation"), clrWhite, clrBackground, m_InfoWindow);
value = channel->Modulation();
if (value == QPSK) snprintf(buf, sizeof(buf), "QPSK");
else if (value == QAM_16) snprintf(buf, sizeof(buf), "QAM 16");
else if (value == QAM_32) snprintf(buf, sizeof(buf), "QAM 32");
else if (value == QAM_64) snprintf(buf, sizeof(buf), "QAM 64");
else if (value == QAM_128) snprintf(buf, sizeof(buf), "QAM 128");
else if (value == QAM_256) snprintf(buf, sizeof(buf), "QAM 256");
else /*QAM_AUTO*/ snprintf(buf, sizeof(buf), "QAM %s", tr("Auto"));
m_Osd->Text(OSDINFOWIN_X(4), OSDINFOWIN_Y(offset), buf, clrYellow, clrBackground, m_InfoWindow);
offset += cOsd::LineHeight() - DELTA;
m_Osd->Text(OSDINFOWIN_X(1), OSDINFOWIN_Y(offset), tr("Inversion"), clrWhite, clrBackground, m_InfoWindow);
value = channel->Inversion();
if (value == INVERSION_OFF) snprintf(buf, sizeof(buf), tr("Off"));
else if (value == INVERSION_ON) snprintf(buf, sizeof(buf), tr("On"));
else /*INVERSION_AUTO*/ snprintf(buf, sizeof(buf), tr("Auto"));
m_Osd->Text(OSDINFOWIN_X(2), OSDINFOWIN_Y(offset), buf, clrYellow, clrBackground, m_InfoWindow);
m_Osd->Text(OSDINFOWIN_X(3), OSDINFOWIN_Y(offset), tr("CoderateH"), clrWhite, clrBackground, m_InfoWindow);
value = channel->CoderateH();
if (value == FEC_NONE) snprintf(buf, sizeof(buf), tr("None"));
else if (value == FEC_1_2) snprintf(buf, sizeof(buf), "1/2");
else if (value == FEC_2_3) snprintf(buf, sizeof(buf), "2/3");
else if (value == FEC_3_4) snprintf(buf, sizeof(buf), "3/4");
else if (value == FEC_4_5) snprintf(buf, sizeof(buf), "4/5");
else if (value == FEC_5_6) snprintf(buf, sizeof(buf), "5/6");
else if (value == FEC_6_7) snprintf(buf, sizeof(buf), "6/7");
else if (value == FEC_7_8) snprintf(buf, sizeof(buf), "7/8");
else if (value == FEC_8_9) snprintf(buf, sizeof(buf), "8/9");
else /*FEC_AUTO*/ snprintf(buf, sizeof(buf), tr("Auto"));
m_Osd->Text(OSDINFOWIN_X(4), OSDINFOWIN_Y(offset), 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(OSDINFOWIN_X(1), OSDINFOWIN_Y(offset), buf, clrYellow, clrBackground, m_InfoWindow);
offset += cOsd::LineHeight() - DELTA;
m_Osd->Text(OSDINFOWIN_X(1), OSDINFOWIN_Y(offset), tr("Frequency"), clrWhite, clrBackground, m_InfoWindow);
value = channel->Frequency();
while (value > 20000) value /= 1000;
snprintf(buf, sizeof(buf), "%d %s", value, tr("MHz"));
m_Osd->Text(OSDINFOWIN_X(2), OSDINFOWIN_Y(offset), buf, clrYellow, clrBackground, m_InfoWindow);
m_Osd->Text(OSDINFOWIN_X(3), OSDINFOWIN_Y(offset), tr("Transmission"), clrWhite, clrBackground, m_InfoWindow);
value = channel->Transmission();
if (value == TRANSMISSION_MODE_2K) snprintf(buf, sizeof(buf), "2K");
else if (value == TRANSMISSION_MODE_8K) snprintf(buf, sizeof(buf), "8K");
else /*TRANSMISSION_MODE_AUTO*/ snprintf(buf, sizeof(buf), tr("Auto"));
m_Osd->Text(OSDINFOWIN_X(4), OSDINFOWIN_Y(offset), buf, clrYellow, clrBackground, m_InfoWindow);
offset += cOsd::LineHeight() - DELTA;
m_Osd->Text( OSDINFOWIN_X(1), OSDINFOWIN_Y(offset), tr("Bandwidth"), clrWhite, clrBackground, m_InfoWindow);
value = channel->Bandwidth();
if (value == BANDWIDTH_8_MHZ) snprintf(buf, sizeof(buf), "8 %s", tr("MHz"));
else if (value == BANDWIDTH_7_MHZ) snprintf(buf, sizeof(buf), "7 %s", tr("MHz"));
else if (value == BANDWIDTH_6_MHZ) snprintf(buf, sizeof(buf), "6 %s", tr("MHz"));
else /*BANDWIDTH_AUTO*/ snprintf(buf, sizeof(buf), tr("Auto"));
m_Osd->Text(OSDINFOWIN_X(2), OSDINFOWIN_Y(offset), buf, clrYellow, clrBackground, m_InfoWindow);
m_Osd->Text(OSDINFOWIN_X(3), OSDINFOWIN_Y(offset), tr("Modulation"), clrWhite, clrBackground, m_InfoWindow);
value = channel->Modulation();
if (value == QPSK) snprintf(buf, sizeof(buf), "QPSK");
else if (value == QAM_16) snprintf(buf, sizeof(buf), "QAM 16");
else if (value == QAM_32) snprintf(buf, sizeof(buf), "QAM 32");
else if (value == QAM_64) snprintf(buf, sizeof(buf), "QAM 64");
else if (value == QAM_128) snprintf(buf, sizeof(buf), "QAM 128");
else if (value == QAM_256) snprintf(buf, sizeof(buf), "QAM 256");
else /*QAM_AUTO*/ snprintf(buf, sizeof(buf), "QAM %s", tr("Auto"));
m_Osd->Text(OSDINFOWIN_X(4), OSDINFOWIN_Y(offset), buf, clrYellow, clrBackground, m_InfoWindow);
offset += cOsd::LineHeight() - DELTA;
m_Osd->Text(OSDINFOWIN_X(1), OSDINFOWIN_Y(offset), tr("Inversion"), clrWhite, clrBackground, m_InfoWindow);
value = channel->Inversion();
if (value == INVERSION_OFF) snprintf(buf, sizeof(buf), tr("Off"));
else if (value == INVERSION_ON) snprintf(buf, sizeof(buf), tr("On"));
else /*INVERSION_AUTO*/ snprintf(buf, sizeof(buf), tr("Auto"));
m_Osd->Text(OSDINFOWIN_X(2), OSDINFOWIN_Y(offset), buf, clrYellow, clrBackground, m_InfoWindow);
m_Osd->Text(OSDINFOWIN_X(3), OSDINFOWIN_Y(offset), tr("CoderateH"), clrWhite, clrBackground, m_InfoWindow);
value = channel->CoderateH();
if (value == FEC_NONE) snprintf(buf, sizeof(buf), tr("None"));
else if (value == FEC_1_2) snprintf(buf, sizeof(buf), "1/2");
else if (value == FEC_2_3) snprintf(buf, sizeof(buf), "2/3");
else if (value == FEC_3_4) snprintf(buf, sizeof(buf), "3/4");
else if (value == FEC_4_5) snprintf(buf, sizeof(buf), "4/5");
else if (value == FEC_5_6) snprintf(buf, sizeof(buf), "5/6");
else if (value == FEC_6_7) snprintf(buf, sizeof(buf), "6/7");
else if (value == FEC_7_8) snprintf(buf, sizeof(buf), "7/8");
else if (value == FEC_8_9) snprintf(buf, sizeof(buf), "8/9");
else /*FEC_AUTO*/ snprintf(buf, sizeof(buf), tr("Auto"));
value = channel->CoderateL();
if (value == FEC_NONE) snprintf(buf2, sizeof(buf2), " - %s", tr("None"));
else if (value == FEC_1_2) snprintf(buf2, sizeof(buf2), " - 1/2");
else if (value == FEC_2_3) snprintf(buf2, sizeof(buf2), " - 2/3");
else if (value == FEC_3_4) snprintf(buf2, sizeof(buf2), " - 3/4");
else if (value == FEC_4_5) snprintf(buf2, sizeof(buf2), " - 4/5");
else if (value == FEC_5_6) snprintf(buf2, sizeof(buf2), " - 5/6");
else if (value == FEC_6_7) snprintf(buf2, sizeof(buf2), " - 6/7");
else if (value == FEC_7_8) snprintf(buf2, sizeof(buf2), " - 7/8");
else if (value == FEC_8_9) snprintf(buf2, sizeof(buf2), " - 8/9");
else /*FEC_AUTO*/ snprintf(buf2, sizeof(buf2), " - %s", tr("Auto"));
strncat(buf, buf2, sizeof(buf));
m_Osd->Text(OSDINFOWIN_X(4), OSDINFOWIN_Y(offset), buf, clrYellow, clrBackground, m_InfoWindow);
offset += cOsd::LineHeight() - DELTA;
m_Osd->Text(OSDINFOWIN_X(1), OSDINFOWIN_Y(offset), tr("Hierarchy"), clrWhite, clrBackground, m_InfoWindow);
value = channel->Hierarchy();
if (value == HIERARCHY_NONE) snprintf(buf, sizeof(buf), tr("None"));
else if (value == HIERARCHY_1) snprintf(buf, sizeof(buf), "1");
else if (value == HIERARCHY_2) snprintf(buf, sizeof(buf), "2");
else if (value == HIERARCHY_4) snprintf(buf, sizeof(buf), "4");
else /*HIERARCHY_AUTO*/ snprintf(buf, sizeof(buf), tr("Auto"));
m_Osd->Text(OSDINFOWIN_X(2), OSDINFOWIN_Y(offset), buf, clrYellow, clrBackground, m_InfoWindow);
m_Osd->Text(OSDINFOWIN_X(3), OSDINFOWIN_Y(offset), tr("Guard"), clrWhite, clrBackground, m_InfoWindow);
value = channel->Guard();
if (value == GUARD_INTERVAL_1_32) snprintf(buf, sizeof(buf), "1/32");
else if (value == GUARD_INTERVAL_1_16) snprintf(buf, sizeof(buf), "1/16");
else if (value == GUARD_INTERVAL_1_8) snprintf(buf, sizeof(buf), "1/8");
else if (value == GUARD_INTERVAL_1_4) snprintf(buf, sizeof(buf), "1/4");
else /*GUARD_INTERVAL_AUTO*/ snprintf(buf, sizeof(buf), tr("Auto"));
m_Osd->Text(OSDINFOWIN_X(4), OSDINFOWIN_Y(offset), buf, clrYellow, clrBackground, m_InfoWindow);
break;
}
}
else if (m_DisplayMode == modeStream) {
m_Osd->Fill(0, OSDINFOWIN_Y(0), OSDWIDTH, OSDINFOWIN_Y(OSDINFOHEIGHT), clrBackground, m_InfoWindow);
m_Osd->Fill(0, OSDINFOWIN_Y(offset), OSDWIDTH, OSDINFOWIN_Y(offset+cOsd::LineHeight()-1), clrWhite, m_InfoWindow);
m_Osd->Text( OSDINFOWIN_X(1), OSDINFOWIN_Y(offset), tr("Stream Information"), clrBackground, clrWhite, m_InfoWindow);
offset += cOsd::LineHeight();
m_Osd->Text(OSDINFOWIN_X(1), OSDINFOWIN_Y(offset), tr("Video Stream"), clrYellow, clrBackground, m_InfoWindow);
snprintf(buf, sizeof(buf), "#%d", channel->Vpid());
m_Osd->Text(OSDINFOWIN_X(3), OSDINFOWIN_Y(offset), buf, clrYellow, clrBackground, m_InfoWindow);
offset += cOsd::LineHeight() - DELTA;
m_Osd->Text(OSDINFOWIN_X(1), OSDINFOWIN_Y(offset), tr("Bitrate"), clrWhite, clrBackground, m_InfoWindow);
if (m_Receiver) snprintf(buf, sizeof(buf), "%.2f %s (%.2f %s)", m_Receiver->VideoStreamBitrate(), tr("Mbit/s"), m_Receiver->VideoBitrate(), tr("Mbit/s"));
else snprintf(buf, sizeof(buf), "---");
m_Osd->Text(OSDINFOWIN_X(3), OSDINFOWIN_Y(offset), buf, clrYellow, clrBackground, m_InfoWindow);
offset += cOsd::LineHeight() - DELTA;
m_Osd->Text(OSDINFOWIN_X(1), OSDINFOWIN_Y(offset), tr("Aspect Ratio"), clrWhite, clrBackground, m_InfoWindow);
if (m_Receiver) {
value = m_Receiver->VideoAspectRatio();
if (value == AR_1_1) snprintf(buf, sizeof(buf), "1:1");
else if (value == AR_4_3) snprintf(buf, sizeof(buf), "4:3");
else if (value == AR_16_9) snprintf(buf, sizeof(buf), "16:9");
else if (value == AR_2_21_1) snprintf(buf, sizeof(buf), "2.21:1");
else snprintf(buf, sizeof(buf), "%s", tr("reserved"));
}
else snprintf(buf, sizeof(buf), "---");
m_Osd->Text(OSDINFOWIN_X(3), OSDINFOWIN_Y(offset), buf, clrYellow, clrBackground, m_InfoWindow);
offset += cOsd::LineHeight() - DELTA;
m_Osd->Text(OSDINFOWIN_X(1), OSDINFOWIN_Y(offset), tr("Frame Rate"), clrWhite, clrBackground, m_InfoWindow);
if (m_Receiver) snprintf(buf, sizeof(buf), "%.2f %s", m_Receiver->VideoFrameRate(), tr("Hz"));
else snprintf(buf, sizeof(buf), "---");
m_Osd->Text(OSDINFOWIN_X(3), OSDINFOWIN_Y(offset), buf, clrYellow, clrBackground, m_InfoWindow);
offset += cOsd::LineHeight() - DELTA;
m_Osd->Text(OSDINFOWIN_X(1), OSDINFOWIN_Y(offset), tr("Video Format"), clrWhite, clrBackground, m_InfoWindow);
if (m_Receiver) {
value = m_Receiver->VideoFormat();
if (value == VF_PAL) snprintf(buf, sizeof(buf), "%s", tr("PAL"));
else if (value == VF_NTSC) snprintf(buf, sizeof(buf), "%s", tr("NTSC"));
else snprintf(buf, sizeof(buf), "%s", tr("unknown"));
}
else snprintf(buf, sizeof(buf), "---");
m_Osd->Text(OSDINFOWIN_X(3), OSDINFOWIN_Y(offset), buf, clrYellow, clrBackground, m_InfoWindow);
offset += cOsd::LineHeight() - DELTA;
m_Osd->Text(OSDINFOWIN_X(1), OSDINFOWIN_Y(offset), tr("Resolution"), clrWhite, clrBackground, m_InfoWindow);
if (m_Receiver) snprintf(buf, sizeof(buf), "%d x %d", m_Receiver->VideoHorizontalSize(), m_Receiver->VideoVerticalSize());
else snprintf(buf, sizeof(buf), "---");
m_Osd->Text(OSDINFOWIN_X(3), OSDINFOWIN_Y(offset), buf, clrYellow, clrBackground, m_InfoWindow);
offset += cOsd::LineHeight() - DELTA;
m_Osd->Text(OSDINFOWIN_X(1), OSDINFOWIN_Y(offset), tr("Audio Stream"), clrYellow, clrBackground, m_InfoWindow);
value = -1;
cDevice::PrimaryDevice()->GetAudioTracks(&value);
snprintf(buf, sizeof(buf), "#%d", (value > 0 ? channel->Apid2() : channel->Apid1()));
m_Osd->Text(OSDINFOWIN_X(3), OSDINFOWIN_Y(offset), buf, clrYellow, clrBackground, m_InfoWindow);
offset += cOsd::LineHeight() - DELTA;
m_Osd->Text(OSDINFOWIN_X(1), OSDINFOWIN_Y(offset), tr("Bitrate"), clrWhite, clrBackground, m_InfoWindow);
if (m_Receiver) {
dvalue = m_Receiver->AudioStreamBitrate();
if (dvalue == (double)FR_RESERVED) snprintf(buf, sizeof(buf), "%s (%.0f %s)", tr("reserved"), m_Receiver->AudioBitrate(), tr("kbit/s"));
else if (dvalue == (double)FR_FREE) snprintf(buf, sizeof(buf), "%s (%.0f %s)", tr("free"), m_Receiver->AudioBitrate(), tr("kbit/s"));
else snprintf(buf, sizeof(buf), "%.0f %s (%.0f %s)", dvalue, tr("kbit/s"), m_Receiver->AudioBitrate(), tr("kbit/s"));
}
else snprintf(buf, sizeof(buf), "---");
m_Osd->Text(OSDINFOWIN_X(3), OSDINFOWIN_Y(offset), buf, clrYellow, clrBackground, m_InfoWindow);
offset += cOsd::LineHeight() - DELTA;
m_Osd->Text(OSDINFOWIN_X(1), OSDINFOWIN_Y(offset), tr("MPEG Layer"), clrWhite, clrBackground, m_InfoWindow);
if (m_Receiver) snprintf(buf, sizeof(buf), "%d", m_Receiver->AudioMPEGLayer());
else snprintf(buf, sizeof(buf), "---");
m_Osd->Text(OSDINFOWIN_X(3), OSDINFOWIN_Y(offset), buf, clrYellow, clrBackground, m_InfoWindow);
offset += cOsd::LineHeight() - DELTA;
m_Osd->Text(OSDINFOWIN_X(1), OSDINFOWIN_Y(offset), tr("Sampling Frequency"), clrWhite, clrBackground, m_InfoWindow);
if (m_Receiver) {
value = m_Receiver->AudioSamplingFreq();
if (value == FR_RESERVED) snprintf(buf, sizeof(buf), "%s", tr("reserved"));
else snprintf(buf, sizeof(buf), "%.1f %s", (value / 1000.0), tr("kHz"));
}
else snprintf(buf, sizeof(buf), "---");
m_Osd->Text(OSDINFOWIN_X(3), OSDINFOWIN_Y(offset), buf, clrYellow, clrBackground, m_InfoWindow);
offset += cOsd::LineHeight() - DELTA;
}
else if (m_DisplayMode == modeAC3) {
m_Osd->Fill(0, OSDINFOWIN_Y(0), OSDWIDTH, OSDINFOWIN_Y(OSDINFOHEIGHT), clrBackground, m_InfoWindow);
m_Osd->Fill(0, OSDINFOWIN_Y(offset), OSDWIDTH, OSDINFOWIN_Y(offset+cOsd::LineHeight()-1), clrWhite, m_InfoWindow);
snprintf(buf, sizeof(buf), "%s - %s #%d", tr("Stream Information"), tr("AC-3 Stream"), channel->Dpid1());
m_Osd->Text( OSDINFOWIN_X(1), OSDINFOWIN_Y(offset), buf, clrBackground, clrWhite, m_InfoWindow);
offset += cOsd::LineHeight();
if (m_Receiver && m_Receiver->AC3Valid()) {
m_Osd->Text(OSDINFOWIN_X(1), OSDINFOWIN_Y(offset), tr("Bitrate"), clrWhite, clrBackground, m_InfoWindow);
snprintf(buf, sizeof(buf), "%.0f %s (%0.f %s)", m_Receiver->AC3StreamBitrate(), tr("kbit/s"), m_Receiver->AC3Bitrate(), tr("kbit/s"));
m_Osd->Text(OSDINFOWIN_X(3), OSDINFOWIN_Y(offset), buf, clrYellow, clrBackground, m_InfoWindow);
offset += cOsd::LineHeight() - DELTA;
m_Osd->Text(OSDINFOWIN_X(1), OSDINFOWIN_Y(offset), tr("Sampling Frequency"), clrWhite, clrBackground, m_InfoWindow);
snprintf(buf, sizeof(buf), "%.1f %s", m_Receiver->AC3SamplingFreq() / 1000., tr("kHz"));
m_Osd->Text(OSDINFOWIN_X(3), OSDINFOWIN_Y(offset), buf, clrYellow, clrBackground, m_InfoWindow);
offset += cOsd::LineHeight() - DELTA;
m_Osd->Text(OSDINFOWIN_X(1), OSDINFOWIN_Y(offset), tr("Frame Size"), clrWhite, clrBackground, m_InfoWindow);
snprintf(buf, sizeof(buf), "%d", m_Receiver->AC3FrameSize());
m_Osd->Text(OSDINFOWIN_X(3), OSDINFOWIN_Y(offset), buf, clrYellow, clrBackground, m_InfoWindow);
offset += cOsd::LineHeight() - DELTA;
m_Osd->Text(OSDINFOWIN_X(1), OSDINFOWIN_Y(offset), tr("Bit Stream Mode"), clrWhite, clrBackground, m_InfoWindow);
switch (m_Receiver->AC3BitStreamMode()) {
case 0: snprintf(buf, sizeof(buf), tr("Complete Main (CM)")); break;
case 1: snprintf(buf, sizeof(buf), tr("Music and Effects (ME)")); break;
case 2: snprintf(buf, sizeof(buf), tr("Visually Impaired (VI)")); break;
case 3: snprintf(buf, sizeof(buf), tr("Hearing Impaired (HI)")); break;
case 4: snprintf(buf, sizeof(buf), tr("Dialogue (D)")); break;
case 5: snprintf(buf, sizeof(buf), tr("Commentary (C)")); break;
case 6: snprintf(buf, sizeof(buf), tr("Emergency (E)")); break;
case 7: (m_Receiver->AC3AudioCodingMode() == 1) ? snprintf(buf, sizeof(buf), tr("Voice Over (VO)")) : snprintf(buf, sizeof(buf), tr("Karaoke")); break;
default: snprintf(buf, sizeof(buf), "---");
}
m_Osd->Text(OSDINFOWIN_X(3), OSDINFOWIN_Y(offset), buf, clrYellow, clrBackground, m_InfoWindow);
offset += cOsd::LineHeight() - DELTA;
m_Osd->Text(OSDINFOWIN_X(1), OSDINFOWIN_Y(offset), tr("Audio Coding Mode"), clrWhite, clrBackground, m_InfoWindow);
if (m_Receiver->AC3BitStreamMode() != 7) {
switch (m_Receiver->AC3AudioCodingMode()) {
case 0: snprintf(buf, sizeof(buf), "1+1 - %s, %s", tr("Ch1"), tr("Ch2")); break;
case 1: snprintf(buf, sizeof(buf), "1/0 - %s", tr("C")); break;
case 2: snprintf(buf, sizeof(buf), "2/0 - %s, %s", tr("L"), tr("R")); break;
case 3: snprintf(buf, sizeof(buf), "3/0 - %s, %s, %s", tr("L"), tr("C"), tr("R")); break;
case 4: snprintf(buf, sizeof(buf), "2/1 - %s, %s, %s", tr("L"), tr("R"), tr("S")); break;
case 5: snprintf(buf, sizeof(buf), "3/1 - %s, %s, %s, %s", tr("L"), tr("C"), tr("R"), tr("S")); break;
case 6: snprintf(buf, sizeof(buf), "2/2 - %s, %s, %s, %s", tr("L"), tr("R"), tr("SL"), tr("SR")); break;
case 7: snprintf(buf, sizeof(buf), "3/2 - %s, %s, %s, %s, %s", tr("L"), tr("C"), tr("R"), tr("SL"), tr("SR")); break;
default: snprintf(buf, sizeof(buf), "---");
}
}
else snprintf(buf, sizeof(buf), "---");
m_Osd->Text(OSDINFOWIN_X(3), OSDINFOWIN_Y(offset), buf, clrYellow, clrBackground, m_InfoWindow);
offset += cOsd::LineHeight() - DELTA;
m_Osd->Text(OSDINFOWIN_X(1), OSDINFOWIN_Y(offset), tr("Center Mix Level"), clrWhite, clrBackground, m_InfoWindow);
switch (m_Receiver->AC3CenterMixLevel()) {
case CML_MINUS_3dB: snprintf(buf, sizeof(buf), "-3.0 %s", tr("dB")); break;
case CML_MINUS_4_5dB: snprintf(buf, sizeof(buf), "-4.5 %s", tr("dB")); break;
case CML_MINUS_6dB: snprintf(buf, sizeof(buf), "-6.0 %s", tr("dB")); break;
case CML_RESERVED: snprintf(buf, sizeof(buf), "%s", tr("reserved")); break;
default: snprintf(buf, sizeof(buf), "---");
}
m_Osd->Text(OSDINFOWIN_X(3), OSDINFOWIN_Y(offset), buf, clrYellow, clrBackground, m_InfoWindow);
offset += cOsd::LineHeight() - DELTA;
m_Osd->Text(OSDINFOWIN_X(1), OSDINFOWIN_Y(offset), tr("Surround Mix Level"), clrWhite, clrBackground, m_InfoWindow);
switch (m_Receiver->AC3SurroundMixLevel()) {
case SML_MINUS_3dB: snprintf(buf, sizeof(buf), "-3 %s", tr("dB")); break;
case SML_MINUS_6dB: snprintf(buf, sizeof(buf), "-6 %s", tr("dB")); break;
case SML_0_dB: snprintf(buf, sizeof(buf), "0 %s", tr("dB")); break;
case SML_RESERVED: snprintf(buf, sizeof(buf), "%s", tr("reserved")); break;
default: snprintf(buf, sizeof(buf), "---");
}
m_Osd->Text(OSDINFOWIN_X(3), OSDINFOWIN_Y(offset), buf, clrYellow, clrBackground, m_InfoWindow);
offset += cOsd::LineHeight() - DELTA;
m_Osd->Text(OSDINFOWIN_X(1), OSDINFOWIN_Y(offset), tr("Dolby Surround Mode"), clrWhite, clrBackground, m_InfoWindow);
switch (m_Receiver->AC3DolbySurroundMode()) {
case DSM_NOT_INDICATED: snprintf(buf, sizeof(buf), "%s", tr("not indicated")); break;
case DSM_NOT_DOLBYSURROUND: snprintf(buf, sizeof(buf), "%s", tr("Off")); break;
case DSM_DOLBYSURROUND: snprintf(buf, sizeof(buf), "%s", tr("On")); break;
case DSM_RESERVED: snprintf(buf, sizeof(buf), "%s", tr("reserved")); break;
default: snprintf(buf, sizeof(buf), "---");
}
m_Osd->Text(OSDINFOWIN_X(3), OSDINFOWIN_Y(offset), buf, clrYellow, clrBackground, m_InfoWindow);
offset += cOsd::LineHeight() - DELTA;
m_Osd->Text(OSDINFOWIN_X(1), OSDINFOWIN_Y(offset), tr("Low Frequency Effects"), clrWhite, clrBackground, m_InfoWindow);
snprintf(buf, sizeof(buf), "%s", m_Receiver->AC3LfeOn() ? tr("On") : tr("Off"));
m_Osd->Text(OSDINFOWIN_X(3), OSDINFOWIN_Y(offset), buf, clrYellow, clrBackground, m_InfoWindow);
offset += cOsd::LineHeight() - DELTA;
m_Osd->Text(OSDINFOWIN_X(1), OSDINFOWIN_Y(offset), tr("Dialogue Normalization"), clrWhite, clrBackground, m_InfoWindow);
value = m_Receiver->AC3DialogLevel();
if (value > 0) snprintf(buf, sizeof(buf), "-%d %s", value, tr("dB"));
else snprintf(buf, sizeof(buf), "---");
m_Osd->Text(OSDINFOWIN_X(3), OSDINFOWIN_Y(offset), buf, clrYellow, clrBackground, m_InfoWindow);
offset += cOsd::LineHeight() - DELTA;
}
}
else /* modeBasic */ {
m_Osd->Fill(0, OSDINFOWIN_Y(0), OSDWIDTH, OSDINFOWIN_Y(OSDINFOHEIGHT), clrTransparent, m_InfoWindow);
}
#if (VDRVERSNUM >= 10300) || defined(ELCHIAIOVERSION)
m_Osd->SetFont(OldFont);
#endif
m_Osd->Flush();
}
}
void cFemonOsd::Action(void) void cFemonOsd::Action(void)
{ {
//printf("cFemonOsd::Action()\n"); //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) #if (VDRVERSNUM < 10300)
isyslog("femon plugin: thread started (pid = %d)", getpid()); isyslog("femon plugin: thread started (pid = %d)", getpid());
#endif #endif
m_Active = true; m_Active = true;
while (m_Active) { while (m_Active) {
if (m_Frontend != -1) { if (m_Frontend != -1) {
CHECK(ioctl(m_Frontend, FE_READ_STATUS, &fe_status)); CHECK(ioctl(m_Frontend, FE_READ_STATUS, &m_FrontendStatus));
CHECK(ioctl(m_Frontend, FE_READ_SIGNAL_STRENGTH, &signal)); CHECK(ioctl(m_Frontend, FE_READ_SIGNAL_STRENGTH, &m_Signal));
CHECK(ioctl(m_Frontend, FE_READ_SNR, &snr)); CHECK(ioctl(m_Frontend, FE_READ_SNR, &m_SNR));
CHECK(ioctl(m_Frontend, FE_READ_BER, &ber)); CHECK(ioctl(m_Frontend, FE_READ_BER, &m_BER));
CHECK(ioctl(m_Frontend, FE_READ_UNCORRECTED_BLOCKS, &unc)); CHECK(ioctl(m_Frontend, FE_READ_UNCORRECTED_BLOCKS, &m_UNC));
if (m_Osd) { DrawInfoWindow();
m_Osd->Clear(m_Window); DrawStatusWindow();
#if (VDRVERSNUM >= 10300) || defined(ELCHIAIOVERSION) if (femonConfig.syslogoutput) {
eDvbFont OldFont = m_Osd->SetFont(fontSml); isyslog("Card #%d (%s) STR: %04x SNR: %04x BER: %08x UNC: %08x |%c|%c|%c|%c|%c|", cDevice::ActualDevice()->CardIndex(), m_FrontendInfo.name, m_Signal, m_SNR, m_BER, m_UNC, (m_FrontendStatus & FE_HAS_LOCK) ? 'L' : ' ', (m_FrontendStatus & FE_HAS_SIGNAL) ? 'S' : ' ', (m_FrontendStatus & FE_HAS_CARRIER) ? 'C' : ' ', (m_FrontendStatus & FE_HAS_VITERBI) ? 'V' : ' ', (m_FrontendStatus & FE_HAS_SYNC) ? 'Z' : ' ');
#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();
} }
} }
usleep(100000L * femonConfig.interval); usleep(100000L * femonConfig.updateinterval);
} }
#if (VDRVERSNUM < 10300) #if (VDRVERSNUM < 10300)
isyslog("femon plugin: thread stopped (pid = %d)", getpid()); isyslog("femon plugin: thread stopped (pid = %d)", getpid());
@@ -151,7 +670,7 @@ void cFemonOsd::Show(void)
{ {
//printf("cFemonOsd::Show()\n"); //printf("cFemonOsd::Show()\n");
char *dev = NULL; char *dev = NULL;
asprintf(&dev, FE_DEVICE, cDevice::ActualDevice()->CardIndex(), 0); asprintf(&dev, FRONTEND_DEVICE, cDevice::ActualDevice()->CardIndex(), 0);
m_Frontend = open(dev, O_RDONLY | O_NONBLOCK); m_Frontend = open(dev, O_RDONLY | O_NONBLOCK);
free(dev); free(dev);
if (m_Frontend < 0) { if (m_Frontend < 0) {
@@ -161,28 +680,30 @@ void cFemonOsd::Show(void)
} }
if (ioctl(m_Frontend, FE_GET_INFO, &m_FrontendInfo) < 0) { if (ioctl(m_Frontend, FE_GET_INFO, &m_FrontendInfo) < 0) {
isyslog("cFemonOsd::Show() cannot read frontend info."); isyslog("cFemonOsd::Show() cannot read frontend info.");
m_Frontend = -1;
close(m_Frontend); close(m_Frontend);
m_Frontend = -1;
return; return;
} }
m_InfoTime = time_ms(); m_Osd = cOsd::OpenRaw((SCREENWIDTH - OSDWIDTH) / 2, (SCREENHEIGHT - OSDHEIGHT) / 2);
m_Osd = cOsd::OpenRaw(m_Xpos, m_Ypos);
if (m_Osd) { if (m_Osd) {
//printf("X: %d - Y: %d - W: %d - H: %d\n", m_Xpos, m_Ypos, m_Width, m_Height); #if (VDRVERSNUM >= 10300) || defined(ELCHIAIOVERSION)
m_Window = m_Osd->Create(0, 0, m_Width, m_Height, 4); eDvbFont OldFont = m_Osd->SetFont(m_Font);
m_Osd->AddColor(clrBackground, m_Window); #endif
m_Osd->AddColor(clrRed, m_Window); m_StatusWindow = m_Osd->Create(0, OSDSTATUSWIN_Y(0), OSDWIDTH, OSDSTATUSHEIGHT, 4);
m_Osd->AddColor(clrGreen, m_Window); m_InfoWindow = m_Osd->Create(0, OSDINFOWIN_Y(0), OSDWIDTH, OSDINFOHEIGHT, 2);
m_Osd->AddColor(clrYellow, m_Window); m_Osd->Clear();
m_Osd->AddColor(clrWhite, m_Window); m_Osd->Fill(0, OSDINFOWIN_Y(0), OSDWIDTH, OSDINFOWIN_Y(OSDINFOHEIGHT), clrTransparent, m_InfoWindow);
m_Osd->AddColor(clrBlack, m_Window); #if (VDRVERSNUM >= 10300) || defined(ELCHIAIOVERSION)
m_Osd->AddColor(clrTransparent, m_Window); m_Osd->SetFont(OldFont);
m_Osd->Clear(m_Window); #endif
m_Osd->Flush(); m_Osd->Flush();
if (m_Receiver) if (m_Receiver)
delete m_Receiver; delete m_Receiver;
m_Receiver = new cFemonReceiver(Channels.GetByNumber(cDevice::CurrentChannel())->Ca(), Channels.GetByNumber(cDevice::CurrentChannel())->Vpid(), Channels.GetByNumber(cDevice::CurrentChannel())->Apid1()); if (femonConfig.analyzestream) {
cDevice::ActualDevice()->AttachReceiver(m_Receiver); cChannel *channel = Channels.GetByNumber(cDevice::CurrentChannel());
m_Receiver = new cFemonReceiver(channel->Ca(), channel->Vpid(), channel->Apid1(), channel->Dpid1());
cDevice::ActualDevice()->AttachReceiver(m_Receiver);
}
Start(); Start();
} }
} }
@@ -191,8 +712,10 @@ void cFemonOsd::ChannelSwitch(const cDevice * device, int channelNumber)
{ {
//printf("cFemonOsd::ChannelSwitch()\n"); //printf("cFemonOsd::ChannelSwitch()\n");
char *dev = NULL; char *dev = NULL;
if (!device->IsPrimaryDevice() || !channelNumber || cDevice::PrimaryDevice()->CurrentChannel() != channelNumber)
return;
close(m_Frontend); close(m_Frontend);
asprintf(&dev, FE_DEVICE, cDevice::ActualDevice()->CardIndex(), 0); asprintf(&dev, FRONTEND_DEVICE, cDevice::ActualDevice()->CardIndex(), 0);
m_Frontend = open(dev, O_RDONLY | O_NONBLOCK); m_Frontend = open(dev, O_RDONLY | O_NONBLOCK);
free(dev); free(dev);
if (m_Frontend < 0) { if (m_Frontend < 0) {
@@ -202,33 +725,37 @@ void cFemonOsd::ChannelSwitch(const cDevice * device, int channelNumber)
} }
if (ioctl(m_Frontend, FE_GET_INFO, &m_FrontendInfo) < 0) { if (ioctl(m_Frontend, FE_GET_INFO, &m_FrontendInfo) < 0) {
isyslog("cFemonOsd::ChannelSwitch() cannot read frontend info."); isyslog("cFemonOsd::ChannelSwitch() cannot read frontend info.");
m_Frontend = -1;
close(m_Frontend); close(m_Frontend);
m_Frontend = -1;
return; return;
} }
if (m_Receiver) if (m_Receiver)
delete m_Receiver; delete m_Receiver;
m_Receiver = new cFemonReceiver(Channels.GetByNumber(cDevice::CurrentChannel())->Ca(), Channels.GetByNumber(cDevice::CurrentChannel())->Vpid(), Channels.GetByNumber(cDevice::CurrentChannel())->Apid1()); if (femonConfig.analyzestream) {
cDevice::ActualDevice()->AttachReceiver(m_Receiver); cChannel *channel = Channels.GetByNumber(cDevice::CurrentChannel());
m_InfoTime = time_ms(); m_Receiver = new cFemonReceiver(channel->Ca(), channel->Vpid(), channel->Apid1(), channel->Dpid1());
cDevice::ActualDevice()->AttachReceiver(m_Receiver);
}
} }
eOSState cFemonOsd::ProcessKey(eKeys Key) eOSState cFemonOsd::ProcessKey(eKeys Key)
{ {
eOSState state = cOsdObject::ProcessKey(Key); eOSState state = cOsdObject::ProcessKey(Key);
if (state == osUnknown) { if (state == osUnknown) {
switch (Key & ~k_Repeat) { switch (Key) {
case k0: case k0:
if (m_Number == 0) { if ((m_Number == 0) && (m_OldNumber != 0)) {
// keep the "Toggle channels" function working m_Number = m_OldNumber;
cRemote::Put(Key); m_OldNumber = cDevice::CurrentChannel();
Channels.SwitchTo(m_Number);
m_Number = 0;
return osContinue; return osContinue;
} }
case k1 ... k9: case k1 ... k9:
if (m_Number >= 0) { if (m_Number >= 0) {
m_Number = m_Number * 10 + Key - k0; m_Number = m_Number * 10 + Key - k0;
if (m_Number > 0) { if (m_Number > 0) {
DrawStatusWindow();
cChannel *ch = Channels.GetByNumber(m_Number); cChannel *ch = Channels.GetByNumber(m_Number);
m_InputTime = time_ms(); m_InputTime = time_ms();
// Lets see if there can be any useful further input: // Lets see if there can be any useful further input:
@@ -245,6 +772,7 @@ eOSState cFemonOsd::ProcessKey(eKeys Key)
} }
if (n > 0) { if (n > 0) {
// This channel is the only one that fits the input, so let's take it right away: // This channel is the only one that fits the input, so let's take it right away:
m_OldNumber = cDevice::CurrentChannel();
Channels.SwitchTo(m_Number); Channels.SwitchTo(m_Number);
m_Number = 0; m_Number = 0;
} }
@@ -253,24 +781,75 @@ eOSState cFemonOsd::ProcessKey(eKeys Key)
break; break;
case kBack: case kBack:
return osEnd; return osEnd;
case kGreen:
{
int CurrentAudioTrack = -1;
const char **AudioTracks = cDevice::PrimaryDevice()->GetAudioTracks(&CurrentAudioTrack);
if (AudioTracks) {
const char **at = &AudioTracks[CurrentAudioTrack];
if (!*++at)
at = AudioTracks;
cDevice::PrimaryDevice()->SetAudioTrack(at - AudioTracks);
if (femonConfig.analyzestream) {
cChannel *channel = Channels.GetByNumber(cDevice::CurrentChannel());
if (m_Receiver)
delete m_Receiver;
m_Receiver = new cFemonReceiver(channel->Ca(), channel->Vpid(), (at - AudioTracks) ? channel->Apid2() : channel->Apid1(), channel->Dpid1());
cDevice::ActualDevice()->AttachReceiver(m_Receiver);
}
}
}
break;
case kRight:
case kLeft:
{
int device = cDevice::ActualDevice()->DeviceNumber();
if (device >= 0) {
cChannel *channel = Channels.GetByNumber(cDevice::CurrentChannel());
for (int i = 0; i < cDevice::NumDevices() - 1; i++) {
if (NORMALKEY(Key) == kRight) {
if (++device >= cDevice::NumDevices()) device = 0;
}
else {
if (--device < 0) device = cDevice::NumDevices() - 1;
}
if (cDevice::GetDevice(device)->ProvidesChannel(channel)) {
//cStatus::MsgChannelSwitch(cDevice::GetDevice(device), 0);
//implement some tuning mechanism here
//cControl::Launch(new cTransferControl(cDevice::GetDevice(device), channel->Vpid(), channel->Apid1(), channel->Apid2(), channel->Dpid1(), channel->Dpid2($
//cStatus::MsgChannelSwitch(cDevice::GetDevice(device), channel->Number());
break;
}
}
}
}
break;
case kUp|k_Repeat:
case kUp: case kUp:
case kDown|k_Repeat:
case kDown: case kDown:
m_OldNumber = cDevice::CurrentChannel();
cDevice::SwitchChannel(NORMALKEY(Key) == kUp ? 1 : -1); cDevice::SwitchChannel(NORMALKEY(Key) == kUp ? 1 : -1);
m_Number = 0;
break; break;
case kNone: case kNone:
if (m_Number && (time_ms() - m_InputTime > CHANNELINPUT_TIMEOUT)) { if (m_Number && (time_ms() - m_InputTime > CHANNELINPUT_TIMEOUT)) {
if (Channels.GetByNumber(m_Number)) { if (Channels.GetByNumber(m_Number)) {
m_OldNumber = cDevice::CurrentChannel();
Channels.SwitchTo(m_Number); Channels.SwitchTo(m_Number);
m_Number = 0; m_Number = 0;
} }
else { else {
m_Number = 0;
m_InputTime = time_ms(); m_InputTime = time_ms();
m_Number = 0;
} }
} }
break; break;
case kOk: case kOk:
m_InfoTime = time_ms(); // toggle between display modes
if (++m_DisplayMode == modeAC3 && !Channels.GetByNumber(cDevice::CurrentChannel())->Dpid1()) m_DisplayMode++;
if (m_DisplayMode >= modeMaxNumber) m_DisplayMode = 0;
DrawInfoWindow();
break; break;
default: default:
break; break;

View File

@@ -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 #ifndef __FEMONOSD_H
#define __FEMONOSD_H #define __FEMONOSD_H
@@ -9,23 +17,29 @@
#include <vdr/status.h> #include <vdr/status.h>
#include <vdr/channels.h> #include <vdr/channels.h>
#include <vdr/font.h> #include <vdr/font.h>
#include <vdr/device.h> // only for TS_SIZE
class cFemonOsd : public cOsdObject, public cThread, public cStatus { class cFemonOsd : public cOsdObject, public cThread, public cStatus {
private: private:
bool m_Active; bool m_Active;
cOsdBase *m_Osd; cOsdBase *m_Osd;
tWindowHandle m_Window; tWindowHandle m_InfoWindow;
tWindowHandle m_StatusWindow;
cFemonReceiver *m_Receiver; cFemonReceiver *m_Receiver;
int m_Frontend; int m_Frontend;
struct dvb_frontend_info m_FrontendInfo; struct dvb_frontend_info m_FrontendInfo;
int m_Number; int m_Number;
int m_OldNumber;
int m_InputTime; int m_InputTime;
int m_InfoTime; uint16_t m_SNR;
int m_Width; uint16_t m_Signal;
int m_Height; uint32_t m_BER;
int m_Xpos; uint32_t m_UNC;
int m_Ypos; fe_status_t m_FrontendStatus;
int m_DisplayMode;
eDvbFont m_Font;
cMutex* m_Mutex;
void DrawStatusWindow(void);
void DrawInfoWindow(void);
protected: protected:
virtual void Action(void); virtual void Action(void);

View File

@@ -1,59 +1,326 @@
/* /*
* 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. * See the README file for copyright information and how to reach the author.
* *
* $Id$ * $Id$
*/ */
#include <unistd.h>
#include "femoncfg.h"
#include "femonreceiver.h" #include "femonreceiver.h"
cFemonReceiver::cFemonReceiver(int Ca, int Vpid, int Apid) #define TS_SIZE 188
:cReceiver(Ca, -1, 2, Vpid, Apid) #define PAY_START 0x40
#define ADAPT_FIELD 0x20
#define PAYLOAD 0x10
#define PTS_DTS_FLAGS 0xC0
cFemonReceiver::cFemonReceiver(int Ca, int Vpid, int Apid, int Dpid)
#if VDRVERSNUM >= 10300
:cReceiver(Ca, -1, 3, Vpid, Apid, Dpid), cThread("femon receiver")
#else
:cReceiver(Ca, -1, 3, Vpid, Apid, Dpid)
#endif
{ {
//printf("cFemonReceiver::cFemonReceiver()\n"); //printf("cFemonReceiver::cFemonReceiver()\n");
m_VPid = Vpid; m_Active = false;
m_APid = Apid; m_VideoPid = Vpid;
m_VideoCount = 0; m_AudioPid = Apid;
m_AudioCount = 0; m_AC3Pid = Dpid;
m_VideoValid = false;
m_VideoPacketCount = 0;
m_VideoHorizontalSize = 0;
m_VideoVerticalSize = 0;
m_VideoAspectRatio = AR_RESERVED;
m_VideoFormat = VF_UNKNOWN;
m_VideoFrameRate = 0.0;
m_VideoStreamBitrate = 0.0;
m_VideoBitrate = 0.0;
m_AudioValid = false;
m_AudioPacketCount = 0;
m_AudioStreamBitrate = -2.0;
m_AudioBitrate = 0.0;
m_AudioSamplingFreq = -1;
m_AudioMPEGLayer = 0;
m_AudioBitrate = 0.0;
m_AC3Valid = false;
m_AC3PacketCount = 0;
m_AC3StreamBitrate = 0;
m_AC3SamplingFreq = 0;
m_AC3Bitrate = 0;
m_AC3FrameSize = 0;
m_AC3BitStreamMode = FR_NOTVALID;
m_AC3AudioCodingMode = FR_NOTVALID;
m_AC3CenterMixLevel = FR_NOTVALID;
m_AC3SurroundMixLevel = FR_NOTVALID;
m_AC3DolbySurroundMode = FR_NOTVALID;
m_AC3LfeOn = false;
m_AC3DialogLevel = FR_NOTVALID;
} }
cFemonReceiver::~cFemonReceiver(void) cFemonReceiver::~cFemonReceiver(void)
{ {
//printf("cFemonReceiver::~cFemonReceiver()\n"); //printf("cFemonReceiver::~cFemonReceiver()\n");
if (m_Active) {
m_Active = false;
Cancel(0);
}
}
/* The following function originates from libdvbmpeg: */
void cFemonReceiver::GetVideoInfo(uint8_t *mbuf, int count)
{
//printf("cFemonReceiver::GetVideoInfo()\n");
uint8_t *headr;
int found = 0;
int c = 0;
m_VideoValid = false;
while ((found < 4) && ((c + 4) < count)) {
uint8_t *b;
b = mbuf + c;
if ((b[0] == 0x00) && (b[1] == 0x00) && (b[2] == 0x01) && (b[3] == 0xb3))
found = 4;
else
c++;
}
if ((!found) || ((c + 16) >= count)) return;
m_VideoValid = true;
headr = mbuf + c + 4;
m_VideoHorizontalSize = ((headr[1] & 0xF0) >> 4) | (headr[0] << 4);
m_VideoVerticalSize = ((headr[1] & 0x0F) << 8) | (headr[2]);
int sw = (int)((headr[3] & 0xF0) >> 4);
switch ( sw ){
case 1:
m_VideoAspectRatio = AR_1_1;
break;
case 2:
m_VideoAspectRatio = AR_4_3;
break;
case 3:
m_VideoAspectRatio = AR_16_9;
break;
case 4:
m_VideoAspectRatio = AR_2_21_1;
break;
case 5 ... 15:
default:
m_VideoAspectRatio = AR_RESERVED;
break;
}
sw = (int)(headr[3] & 0x0F);
switch ( sw ) {
case 1:
m_VideoFrameRate = 24000 / 1001.0;
m_VideoFormat = VF_UNKNOWN;
break;
case 2:
m_VideoFrameRate = 24.0;
m_VideoFormat = VF_UNKNOWN;
break;
case 3:
m_VideoFrameRate = 25.0;
m_VideoFormat = VF_PAL;
break;
case 4:
m_VideoFrameRate = 30000 / 1001.0;
m_VideoFormat = VF_NTSC;
break;
case 5:
m_VideoFrameRate = 30.0;
m_VideoFormat = VF_NTSC;
break;
case 6:
m_VideoFrameRate = 50.0;
m_VideoFormat = VF_PAL;
break;
case 7:
m_VideoFrameRate = 60.0;
m_VideoFormat = VF_NTSC;
break;
case 8:
m_VideoFrameRate = 60000 / 1001.0;
m_VideoFormat = VF_NTSC;
break;
case 9 ... 15:
default:
m_VideoFrameRate = 0;
m_VideoFormat = VF_UNKNOWN;
break;
}
m_VideoStreamBitrate = 400 * (((headr[4] << 10) & 0x0003FC00UL) | ((headr[5] << 2) & 0x000003FCUL) | (((headr[6] & 0xC0) >> 6) & 0x00000003UL)) / 1000000.0;
}
static unsigned int bitrates[3][16] =
{
{0, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448, 0},
{0, 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384, 0},
{0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 0}
};
static unsigned int samplerates[4] =
{441, 480, 320, 0};
/* The following function originates from libdvbmpeg: */
void cFemonReceiver::GetAudioInfo(uint8_t *mbuf, int count)
{
//printf("cFemonReceiver::GetAudioInfo()\n");
uint8_t *headr;
int found = 0;
int c = 0;
int tmp = 0;
m_AudioValid = false;
while (!found && (c < count)) {
uint8_t *b = mbuf + c;
if ((b[0] == 0xff) && ((b[1] & 0xf8) == 0xf8))
found = 1;
else
c++;
}
if ((!found) || ((c + 3) >= count)) return;
m_AudioValid = true;
headr = mbuf + c;
m_AudioMPEGLayer = 4 - ((headr[1] & 0x06) >> 1);
tmp = bitrates[(3 - ((headr[1] & 0x06) >> 1))][(headr[2] >> 4)] * 1000;
if (tmp == 0)
m_AudioStreamBitrate = (double)FR_FREE;
else if (tmp == 0xf)
m_AudioStreamBitrate = (double)FR_RESERVED;
else
m_AudioStreamBitrate = tmp / 1000.0;
tmp = samplerates[((headr[2] & 0x0c) >> 2)] * 100;
if (tmp == 3)
m_AudioSamplingFreq = FR_RESERVED;
else
m_AudioSamplingFreq = tmp;
}
static unsigned int ac3_bitrates[32] =
{32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384, 448, 512, 576, 640, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
static unsigned int ac3_freq[4] =
{480, 441, 320, 0};
static unsigned int ac3_frames[3][32] =
{
{64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384, 448, 512, 640, 768, 896, 1024, 1152, 1280, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{69, 87, 104, 121, 139, 174, 208, 243, 278, 348, 417, 487, 557, 696, 835, 975, 1114, 1253, 1393, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{96, 120, 144, 168, 192, 240, 288, 336, 384, 480, 576, 672, 768, 960, 1152, 1344, 1536, 1728, 1920, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
};
/*
** AC3 Audio Header: http://www.atsc.org/standards/a_52a.pdf
** The following function originates from libdvbmpeg:
*/
void cFemonReceiver::GetAC3Info(uint8_t *mbuf, int count)
{
uint8_t *headr;
int found = 0;
int c = 0;
uint8_t frame;
m_AC3Valid = false;
while (!found && (c < count)) {
uint8_t *b = mbuf + c;
if ((b[0] == 0x0b) && (b[1] == 0x77))
found = 1;
else
c++;
}
if ((!found) || ((c + 5) >= count)) return;
m_AC3Valid = true;
headr = mbuf + c + 2;
frame = (headr[2] & 0x3f);
m_AC3StreamBitrate = ac3_bitrates[frame >> 1];
int fr = (headr[2] & 0xc0 ) >> 6;
m_AC3SamplingFreq = ac3_freq[fr] * 100;
m_AC3FrameSize = ac3_frames[fr][frame >> 1];
if ((frame & 1) && (fr == 1)) m_AC3FrameSize++;
m_AC3FrameSize <<= 1;
m_AC3BitStreamMode = (headr[3] & 7);
m_AC3AudioCodingMode = (headr[4] & 0xE0) >> 5;
if ((m_AC3AudioCodingMode & 0x01) && (m_AC3AudioCodingMode != 0x01)) // if 3 front channels
m_AC3CenterMixLevel = (headr[4] & 0x18) >> 3;
else
m_AC3CenterMixLevel = FR_NOTVALID;
if (m_AC3AudioCodingMode & 0x04) // if a surround channel exists
m_AC3SurroundMixLevel = (headr[4] & 0x06) >> 1;
else
m_AC3SurroundMixLevel = FR_NOTVALID;
if (m_AC3AudioCodingMode == 0x02) // if in 2/0 mode
m_AC3DolbySurroundMode = ((headr[4] & 1) << 1) | ((headr[5] & 0x80) >> 7);
else
m_AC3DolbySurroundMode = FR_NOTVALID;
m_AC3LfeOn = (headr[5] & 0x40) >> 6;
m_AC3DialogLevel = (headr[5] & 0x3e) >> 1;
} }
void cFemonReceiver::Activate(bool On) void cFemonReceiver::Activate(bool On)
{ {
//printf("cFemonReceiver::Activate()\n"); //printf("cFemonReceiver::Activate()\n");
Start();
} }
void cFemonReceiver::Receive(uchar *Data, int Length) void cFemonReceiver::Receive(uchar *Data, int Length)
{ {
//printf("cFemonReceiver::Receive()\n"); //printf("cFemonReceiver::Receive()\n");
// TS packet length: TS_SIZE
if (Length == TS_SIZE) { if (Length == TS_SIZE) {
int pid = ((Data[1] & 0x1f) << 8) | (Data[2]); int pid = ((Data[1] & 0x1f) << 8) | (Data[2]);
if (pid == m_VPid) { if (pid == m_VideoPid) {
m_VideoCount++; m_VideoPacketCount++;
} }
else if (pid == m_APid) { else if (pid == m_AudioPid) {
m_AudioCount++; m_AudioPacketCount++;
} }
else if (pid == m_AC3Pid) {
m_AC3PacketCount++;
}
/* the following originates from libdvbmpeg: */
if (!(Data[3] & PAYLOAD)) {
return;
}
uint8_t off = 0;
if (Data[3] & ADAPT_FIELD) {
off = Data[4] + 1;
}
if (Data[1] & PAY_START) {
uint8_t *sb = Data + 4 + off;
if (sb[7] & PTS_DTS_FLAGS) {
uint8_t *pay = sb + sb[8] + 9;
int l = TS_SIZE - 13 - off - sb[8];
if (pid == m_VideoPid) {
GetVideoInfo(pay, l);
}
else if (pid == m_AudioPid) {
GetAudioInfo(pay, l);
}
else if (pid == m_AC3Pid) {
GetAC3Info(pay, l);
}
}
}
/* end */
} }
} }
int cFemonReceiver::VideoPacketCount(void) void cFemonReceiver::Action(void)
{ {
//printf("cFemonReceiver::VideoPacketCount()\n"); //printf("cFemonReceiver::Action()\n");
int count = m_VideoCount; #if (VDRVERSNUM < 10300)
m_VideoCount = 0; isyslog("femon receiver: thread started (pid = %d)", getpid());
return count; #endif
} m_Active = true;
while (m_Active) {
int cFemonReceiver::AudioPacketCount(void) // TS packet 188 bytes - 4 byte header; MPEG standard defines 1Mbit = 1000000bit
{ m_VideoBitrate = (8.0 * 184.0 * m_VideoPacketCount) / (femonConfig.calcinterval * 100000.0);
//printf("cFemonReceiver::AudioPacketCount()\n"); m_VideoPacketCount = 0;
int count = m_AudioCount; m_AudioBitrate = (8.0 * 184.0 * m_AudioPacketCount) / (femonConfig.calcinterval * 100.0);
m_AudioCount = 0; m_AudioPacketCount = 0;
return count; m_AC3Bitrate = (8.0 * 184.0 * m_AC3PacketCount) / (femonConfig.calcinterval * 100.0);
m_AC3PacketCount = 0;
usleep(100000L * femonConfig.calcinterval);
}
#if (VDRVERSNUM < 10300)
isyslog("femon receiver: thread stopped (pid = %d)", getpid());
#endif
} }

View File

@@ -1,26 +1,132 @@
/*
* 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 #ifndef __FEMONRECEIVER_H
#define __FEMONRECEIVER_H #define __FEMONRECEIVER_H
#include <vdr/device.h> // only for TS_SIZE #include <vdr/thread.h>
#include <vdr/receiver.h> #include <vdr/receiver.h>
class cFemonReceiver : public cReceiver { enum eVideoFormat {
VF_UNKNOWN = 0,
VF_PAL = 1,
VF_NTSC = 2,
};
enum eAspectRatio {
AR_RESERVED = 0,
AR_1_1 = 100,
AR_4_3 = 133,
AR_16_9 = 177,
AR_2_21_1 = 233,
};
enum eCenterMixLevel {
CML_MINUS_3dB = 0,
CML_MINUS_4_5dB = 1,
CML_MINUS_6dB = 2,
CML_RESERVED = 3,
};
enum eSurroundMixLevel {
SML_MINUS_3dB = 0,
SML_MINUS_6dB = 1,
SML_0_dB = 2,
SML_RESERVED = 3,
};
enum eDolbySurroundMode {
DSM_NOT_INDICATED = 0,
DSM_NOT_DOLBYSURROUND = 1,
DSM_DOLBYSURROUND = 2,
DSM_RESERVED = 3,
};
#define FR_RESERVED -1
#define FR_FREE -2
#define FR_NOTVALID -3
class cFemonReceiver : public cReceiver, public cThread {
private: private:
int m_VPid; bool m_Active;
int m_APid; int m_VideoPid;
int m_VideoCount; int m_AudioPid;
int m_AudioCount; int m_AC3Pid;
bool m_VideoValid;
int m_VideoPacketCount;
int m_VideoHorizontalSize;
int m_VideoVerticalSize;
int m_VideoAspectRatio;
int m_VideoFormat;
double m_VideoFrameRate;
double m_VideoStreamBitrate;
double m_VideoBitrate;
bool m_AudioValid;
int m_AudioPacketCount;
double m_AudioStreamBitrate;
double m_AudioBitrate;
int m_AudioSamplingFreq;
int m_AudioMPEGLayer;
bool m_AC3Valid;
int m_AC3PacketCount;
double m_AC3Bitrate;
int m_AC3FrameSize;
int m_AC3SamplingFreq;
int m_AC3StreamBitrate;
int m_AC3BitStreamMode;
int m_AC3AudioCodingMode;
int m_AC3CenterMixLevel;
int m_AC3SurroundMixLevel;
int m_AC3DolbySurroundMode;
bool m_AC3LfeOn;
int m_AC3DialogLevel;
void GetVideoInfo(uint8_t *mbuf, int count);
void GetAudioInfo(uint8_t *mbuf, int count);
void GetAC3Info(uint8_t *mbuf, int count);
protected: protected:
virtual void Activate(bool On); virtual void Activate(bool On);
virtual void Receive(uchar *Data, int Length); virtual void Receive(uchar *Data, int Length);
virtual void Action(void);
public: public:
cFemonReceiver(int Ca, int Vpid, int Apid); cFemonReceiver(int Ca, int Vpid, int Apid, int Dpid);
virtual ~cFemonReceiver(); virtual ~cFemonReceiver();
int VideoPacketCount(void); bool VideoValid(void) { return m_VideoValid; }; // boolean
int AudioPacketCount(void); int VideoHorizontalSize(void) { return m_VideoHorizontalSize; }; // pixels
int VideoVerticalSize(void) { return m_VideoVerticalSize; }; // pixels
int VideoAspectRatio(void) { return m_VideoAspectRatio; }; // eAspectRatio
int VideoFormat(void) { return m_VideoFormat; }; // eVideoFormat
double VideoFrameRate(void) { return m_VideoFrameRate; }; // Hz
double VideoStreamBitrate(void) { return m_VideoStreamBitrate; }; // Mbit/s
double VideoBitrate(void) { return m_VideoBitrate; }; // Mbit/s
bool AudioValid(void) { return m_AudioValid; }; // boolean
int AudioMPEGLayer(void) { return m_AudioMPEGLayer; }; // layer number
int AudioSamplingFreq(void) { return m_AudioSamplingFreq; }; // Hz
double AudioStreamBitrate(void) { return m_AudioStreamBitrate; }; // kbit/s
double AudioBitrate(void) { return m_AudioBitrate; }; // kbit/s
bool AC3Valid(void) { return m_AC3Valid; }; // boolean
int AC3SamplingFreq(void) { return m_AC3SamplingFreq; }; // Hz
double AC3StreamBitrate(void) { return m_AC3StreamBitrate; }; // kbit/s
double AC3Bitrate(void) { return m_AC3Bitrate; }; // kbit/s
int AC3FrameSize(void) { return m_AC3FrameSize; }; // Bytes
int AC3BitStreamMode(void) { return m_AC3BitStreamMode; }; // 0..7
int AC3AudioCodingMode(void) { return m_AC3AudioCodingMode; }; // 0..7
bool AC3_2_0(void) { return m_AC3AudioCodingMode == 2; }; // DD 2.0
bool AC3_5_1(void) { return m_AC3AudioCodingMode == 7; }; // DD 5.1
int AC3CenterMixLevel(void) { return m_AC3CenterMixLevel; }; // eCenterMixLevel
int AC3SurroundMixLevel(void) { return m_AC3SurroundMixLevel; }; // eSurroundMixLevel
int AC3DolbySurroundMode(void) { return m_AC3DolbySurroundMode; }; // eDolbySurroundMode
bool AC3LfeOn(void) { return m_AC3LfeOn; }; // boolean
int AC3DialogLevel(void) { return m_AC3DialogLevel; }; // -dB
}; };
#endif //__FEMONRECEIVER_H #endif //__FEMONRECEIVER_H