2004-02-15 03:20:00 +01:00
|
|
|
/*
|
2015-03-07 21:32:58 +01:00
|
|
|
* femon.c: Frontend Status Monitor plugin for the Video Disk Recorder
|
2004-02-15 03:20:00 +01:00
|
|
|
*
|
|
|
|
* See the README file for copyright information and how to reach the author.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
2015-03-07 21:09:18 +01:00
|
|
|
#include <getopt.h>
|
2007-05-01 03:20:00 +02:00
|
|
|
#include <vdr/menu.h>
|
2005-11-13 03:20:00 +01:00
|
|
|
#include <vdr/remote.h>
|
2010-10-29 20:16:01 +02:00
|
|
|
#include <vdr/player.h>
|
2015-03-07 19:37:07 +01:00
|
|
|
|
2015-03-07 21:32:58 +01:00
|
|
|
#include "config.h"
|
2005-08-28 03:20:00 +02:00
|
|
|
#include "femonservice.h"
|
2015-03-07 21:32:58 +01:00
|
|
|
#include "log.h"
|
|
|
|
#include "osd.h"
|
|
|
|
#include "tools.h"
|
|
|
|
#include "setup.h"
|
2004-02-15 03:20:00 +01:00
|
|
|
|
2017-06-25 13:07:10 +02:00
|
|
|
#if defined(APIVERSNUM) && APIVERSNUM < 20307
|
|
|
|
#error "VDR-2.3.7 API version or greater is required!"
|
2004-05-18 03:20:00 +02:00
|
|
|
#endif
|
|
|
|
|
2012-02-26 21:54:18 +01:00
|
|
|
#ifndef GITVERSION
|
|
|
|
#define GITVERSION ""
|
|
|
|
#endif
|
|
|
|
|
2015-09-19 16:01:01 +02:00
|
|
|
static const char VERSION[] = "2.3.0" GITVERSION;
|
2007-08-14 03:20:00 +02:00
|
|
|
static const char DESCRIPTION[] = trNOOP("DVB Signal Information Monitor (OSD)");
|
|
|
|
static const char MAINMENUENTRY[] = trNOOP("Signal Information");
|
|
|
|
|
|
|
|
class cPluginFemon : public cPlugin {
|
|
|
|
public:
|
|
|
|
cPluginFemon(void);
|
|
|
|
virtual ~cPluginFemon();
|
|
|
|
virtual const char *Version(void) { return VERSION; }
|
|
|
|
virtual const char *Description(void) { return tr(DESCRIPTION); }
|
|
|
|
virtual const char *CommandLineHelp(void);
|
|
|
|
virtual bool ProcessArgs(int argc, char *argv[]);
|
|
|
|
virtual bool Initialize(void);
|
|
|
|
virtual bool Start(void);
|
|
|
|
virtual void Stop(void);
|
|
|
|
virtual void Housekeeping(void);
|
|
|
|
virtual void MainThreadHook(void) {}
|
|
|
|
virtual cString Active(void) { return NULL; }
|
2015-03-07 20:37:46 +01:00
|
|
|
virtual const char *MainMenuEntry(void) { return (FemonConfig.GetHideMenu() ? NULL : tr(MAINMENUENTRY)); }
|
2007-08-14 03:20:00 +02:00
|
|
|
virtual cOsdObject *MainMenuAction(void);
|
|
|
|
virtual cMenuSetupPage *SetupMenu(void);
|
2015-03-07 17:22:02 +01:00
|
|
|
virtual bool SetupParse(const char *nameP, const char *valueP);
|
|
|
|
virtual bool Service(const char *idP, void *dataP);
|
2007-08-14 03:20:00 +02:00
|
|
|
virtual const char **SVDRPHelpPages(void);
|
2015-03-07 17:22:02 +01:00
|
|
|
virtual cString SVDRPCommand(const char *commandP, const char *optionP, int &replyCodeP);
|
2007-08-14 03:20:00 +02:00
|
|
|
};
|
|
|
|
|
2005-11-13 03:20:00 +01:00
|
|
|
cPluginFemon::cPluginFemon()
|
2004-02-15 03:20:00 +01:00
|
|
|
{
|
|
|
|
// Initialize any member variables here.
|
|
|
|
// DON'T DO ANYTHING ELSE THAT MAY HAVE SIDE EFFECTS, REQUIRE GLOBAL
|
|
|
|
// VDR OBJECTS TO EXIST OR PRODUCE ANY OUTPUT!
|
2015-03-07 21:09:18 +01:00
|
|
|
debug1("%s", __PRETTY_FUNCTION__);
|
2004-02-15 03:20:00 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
cPluginFemon::~cPluginFemon()
|
|
|
|
{
|
|
|
|
// Clean up after yourself!
|
2015-03-07 21:09:18 +01:00
|
|
|
debug1("%s", __PRETTY_FUNCTION__);
|
2004-02-15 03:20:00 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
const char *cPluginFemon::CommandLineHelp(void)
|
|
|
|
{
|
|
|
|
// Return a string that describes all known command line options.
|
2015-03-07 21:09:18 +01:00
|
|
|
return " -t <mode>, --trace=<mode> set the tracing mode\n";
|
2004-02-15 03:20:00 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
bool cPluginFemon::ProcessArgs(int argc, char *argv[])
|
|
|
|
{
|
|
|
|
// Implement command line argument processing here if applicable.
|
2015-03-07 21:09:18 +01:00
|
|
|
static const struct option long_options[] = {
|
|
|
|
{ "trace", required_argument, NULL, 't' },
|
|
|
|
{ NULL, no_argument, NULL, 0 }
|
|
|
|
};
|
|
|
|
|
|
|
|
cString server;
|
|
|
|
int c;
|
|
|
|
while ((c = getopt_long(argc, argv, "t:", long_options, NULL)) != -1) {
|
|
|
|
switch (c) {
|
|
|
|
case 't':
|
|
|
|
FemonConfig.SetTraceMode(strtol(optarg, NULL, 0));
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
2004-02-15 03:20:00 +01:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool cPluginFemon::Initialize(void)
|
|
|
|
{
|
|
|
|
// Initialize any background activities the plugin shall perform.
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool cPluginFemon::Start(void)
|
|
|
|
{
|
|
|
|
// Start any background activities the plugin shall perform.
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2005-02-24 03:20:00 +01:00
|
|
|
void cPluginFemon::Stop(void)
|
|
|
|
{
|
|
|
|
// Stop the background activities.
|
|
|
|
}
|
|
|
|
|
2004-02-15 03:20:00 +01:00
|
|
|
void cPluginFemon::Housekeeping(void)
|
|
|
|
{
|
|
|
|
// Perform any cleanup or other regular tasks.
|
|
|
|
}
|
|
|
|
|
|
|
|
cOsdObject *cPluginFemon::MainMenuAction(void)
|
|
|
|
{
|
|
|
|
// Perform the action when selected from the main VDR menu.
|
2015-03-07 21:09:18 +01:00
|
|
|
debug1("%s", __PRETTY_FUNCTION__);
|
2015-09-19 16:01:01 +02:00
|
|
|
LOCK_CHANNELS_READ;
|
|
|
|
if (cControl::Control() || (Channels->Count() <= 0))
|
2008-06-20 03:20:00 +02:00
|
|
|
Skins.Message(mtInfo, tr("Femon not available"));
|
2007-05-01 03:20:00 +02:00
|
|
|
else
|
|
|
|
return cFemonOsd::Instance(true);
|
|
|
|
return NULL;
|
2004-02-15 03:20:00 +01:00
|
|
|
}
|
|
|
|
|
2015-03-07 19:37:07 +01:00
|
|
|
cMenuSetupPage *cPluginFemon::SetupMenu(void)
|
|
|
|
{
|
|
|
|
// Return a setup menu in case the plugin supports one.
|
|
|
|
return new cMenuFemonSetup;
|
|
|
|
}
|
|
|
|
|
2015-03-07 17:22:02 +01:00
|
|
|
bool cPluginFemon::SetupParse(const char *nameP, const char *valueP)
|
2004-02-15 03:20:00 +01:00
|
|
|
{
|
|
|
|
// Parse your own setup parameters and store their values.
|
2015-03-07 20:37:46 +01:00
|
|
|
if (!strcasecmp(nameP, "HideMenu"))
|
|
|
|
FemonConfig.SetHideMenu(atoi(valueP));
|
|
|
|
else if (!strcasecmp(nameP, "DisplayMode"))
|
|
|
|
FemonConfig.SetDisplayMode(atoi(valueP));
|
|
|
|
else if (!strcasecmp(nameP, "Position"))
|
|
|
|
FemonConfig.SetPosition(atoi(valueP));
|
|
|
|
else if (!strcasecmp(nameP, "Skin"))
|
|
|
|
FemonConfig.SetSkin(atoi(valueP));
|
|
|
|
else if (!strcasecmp(nameP, "Theme"))
|
|
|
|
FemonConfig.SetTheme(atoi(valueP));
|
|
|
|
else if (!strcasecmp(nameP, "Downscale"))
|
|
|
|
FemonConfig.SetDownscale(atoi(valueP));
|
|
|
|
else if (!strcasecmp(nameP, "RedLimit"))
|
|
|
|
FemonConfig.SetRedLimit(atoi(valueP));
|
|
|
|
else if (!strcasecmp(nameP, "GreenLimit"))
|
|
|
|
FemonConfig.SetGreenLimit(atoi(valueP));
|
|
|
|
else if (!strcasecmp(nameP, "UpdateInterval"))
|
|
|
|
FemonConfig.SetUpdateInterval(atoi(valueP));
|
|
|
|
else if (!strcasecmp(nameP, "AnalStream"))
|
|
|
|
FemonConfig.SetAnalyzeStream(atoi(valueP));
|
|
|
|
else if (!strcasecmp(nameP, "CalcInterval"))
|
|
|
|
FemonConfig.SetCalcInterval(atoi(valueP));
|
|
|
|
else if (!strcasecmp(nameP, "UseSvdrp"))
|
|
|
|
FemonConfig.SetUseSvdrp(atoi(valueP));
|
|
|
|
else if (!strcasecmp(nameP, "ServerPort"))
|
|
|
|
FemonConfig.SetSvdrpPort(atoi(valueP));
|
|
|
|
else if (!strcasecmp(nameP, "ServerIp"))
|
|
|
|
FemonConfig.SetSvdrpIp(valueP);
|
2004-02-15 03:20:00 +01:00
|
|
|
else
|
|
|
|
return false;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2015-03-07 17:22:02 +01:00
|
|
|
bool cPluginFemon::Service(const char *idP, void *dataP)
|
2005-08-28 03:20:00 +02:00
|
|
|
{
|
2017-05-04 21:47:49 +02:00
|
|
|
if (strcmp(idP, "FemonService-v1.1") == 0) {
|
2015-03-07 17:22:02 +01:00
|
|
|
if (dataP) {
|
2017-05-04 21:47:49 +02:00
|
|
|
FemonService_v1_1 *data = reinterpret_cast<FemonService_v1_1*>(dataP);
|
|
|
|
cDevice *dev = cDevice::ActualDevice();
|
|
|
|
if (!dev)
|
2011-11-20 18:04:24 +01:00
|
|
|
return false;
|
2012-01-15 22:07:53 +01:00
|
|
|
data->fe_name = getFrontendName(dev);
|
|
|
|
data->fe_status = getFrontendStatus(dev);
|
2017-05-04 21:47:49 +02:00
|
|
|
data->fe_cnr = getCNR(dev);
|
2012-01-15 22:07:53 +01:00
|
|
|
data->fe_signal = getSignal(dev);
|
|
|
|
data->fe_ber = getBER(dev);
|
2017-05-04 21:47:49 +02:00
|
|
|
data->fe_per = getPER(dev);
|
2008-02-18 03:20:00 +01:00
|
|
|
data->video_bitrate = cFemonOsd::Instance() ? cFemonOsd::Instance()->GetVideoBitrate() : 0.0;
|
|
|
|
data->audio_bitrate = cFemonOsd::Instance() ? cFemonOsd::Instance()->GetAudioBitrate() : 0.0;
|
|
|
|
data->dolby_bitrate = cFemonOsd::Instance() ? cFemonOsd::Instance()->GetDolbyBitrate() : 0.0;
|
|
|
|
}
|
2005-08-28 03:20:00 +02:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
const char **cPluginFemon::SVDRPHelpPages(void)
|
2011-11-20 18:04:24 +01:00
|
|
|
{
|
2005-08-28 03:20:00 +02:00
|
|
|
static const char *HelpPages[] = {
|
2005-11-13 03:20:00 +01:00
|
|
|
"OPEN\n"
|
|
|
|
" Open femon plugin.",
|
|
|
|
"QUIT\n"
|
|
|
|
" Close femon plugin.",
|
|
|
|
"NEXT\n"
|
|
|
|
" Switch to next possible device.",
|
|
|
|
"PREV\n"
|
|
|
|
" Switch to previous possible device.",
|
2012-01-15 22:07:53 +01:00
|
|
|
"INFO <card index>\n"
|
|
|
|
" Print the frontend information.",
|
|
|
|
"NAME <card index>\n"
|
|
|
|
" Print the frontend name.",
|
|
|
|
"STAT <card index>\n"
|
|
|
|
" Print the frontend status.",
|
|
|
|
"STRG <card index>\n"
|
|
|
|
" Print the signal strength.",
|
|
|
|
"QUAL <card index>\n"
|
|
|
|
" Print the signal quality.",
|
|
|
|
"SGNL <card index>\n"
|
|
|
|
" Print the signal strength from driver.",
|
2017-05-04 21:47:49 +02:00
|
|
|
"CNRA <card index>\n"
|
|
|
|
" Print the carrier-to-noise ratio from driver.",
|
2012-01-15 22:07:53 +01:00
|
|
|
"BERA <card index>\n"
|
2017-05-04 21:47:49 +02:00
|
|
|
" Print the bit error rate from driver.",
|
|
|
|
"PERA <card index>\n"
|
|
|
|
" Print the packet error rate from driver.",
|
2005-08-28 03:20:00 +02:00
|
|
|
"VIBR\n"
|
2012-01-15 22:07:53 +01:00
|
|
|
" Print the current video bitrate [Mbit/s].",
|
2005-08-28 03:20:00 +02:00
|
|
|
"AUBR\n"
|
2012-01-15 22:07:53 +01:00
|
|
|
" Print the current audio bitrate [kbit/s].",
|
2005-11-13 03:20:00 +01:00
|
|
|
"DDBR\n"
|
2012-01-15 22:07:53 +01:00
|
|
|
" Print the current dolby bitrate [kbit/s].",
|
2015-03-07 21:09:18 +01:00
|
|
|
"TRAC [ <mode> ]\n"
|
|
|
|
" Gets and/or sets used tracing mode.\n",
|
2005-08-28 03:20:00 +02:00
|
|
|
NULL
|
|
|
|
};
|
|
|
|
return HelpPages;
|
|
|
|
}
|
|
|
|
|
2015-03-07 17:22:02 +01:00
|
|
|
cString cPluginFemon::SVDRPCommand(const char *commandP, const char *optionP, int &replyCodeP)
|
2005-08-28 03:20:00 +02:00
|
|
|
{
|
2017-05-04 21:47:49 +02:00
|
|
|
cDevice *dev = cDevice::ActualDevice();
|
2015-03-07 21:09:18 +01:00
|
|
|
if (strcasecmp(commandP, "TRAC") == 0) {
|
|
|
|
if (optionP && *optionP)
|
|
|
|
FemonConfig.SetTraceMode(strtol(optionP, NULL, 0));
|
|
|
|
return cString::sprintf("Tracing mode: 0x%04X\n", FemonConfig.GetTraceMode());
|
|
|
|
}
|
2015-03-07 17:22:02 +01:00
|
|
|
if (*optionP && isnumber(optionP)) {
|
2017-05-04 21:47:49 +02:00
|
|
|
cDevice *dev2 = cDevice::GetDevice(int(strtol(optionP, NULL, 10)));
|
2012-01-15 22:07:53 +01:00
|
|
|
if (dev2)
|
|
|
|
dev = dev2;
|
|
|
|
}
|
2013-11-19 21:29:36 +01:00
|
|
|
if (cReplayControl::NowReplaying() || !dev) {
|
2015-03-07 17:22:02 +01:00
|
|
|
replyCodeP = 550; // Requested action not taken
|
2013-11-19 21:29:36 +01:00
|
|
|
return cString("Cannot open femon plugin while replaying");
|
|
|
|
}
|
2015-03-07 17:22:02 +01:00
|
|
|
if (strcasecmp(commandP, "OPEN") == 0) {
|
2005-11-13 03:20:00 +01:00
|
|
|
if (!cFemonOsd::Instance())
|
2010-10-29 20:16:01 +02:00
|
|
|
cRemote::CallPlugin(Name());
|
2005-11-13 03:20:00 +01:00
|
|
|
return cString("Opening femon plugin");
|
|
|
|
}
|
2015-03-07 17:22:02 +01:00
|
|
|
else if (strcasecmp(commandP, "QUIT") == 0) {
|
2005-11-13 03:20:00 +01:00
|
|
|
if (cFemonOsd::Instance())
|
|
|
|
cRemote::Put(kBack);
|
|
|
|
return cString("Closing femon plugin");
|
|
|
|
}
|
2015-03-07 17:22:02 +01:00
|
|
|
else if (strcasecmp(commandP, "NEXT") == 0) {
|
2005-11-13 03:20:00 +01:00
|
|
|
if (cFemonOsd::Instance())
|
|
|
|
return cString::sprintf("Switching to next device: %s", cFemonOsd::Instance()->DeviceSwitch(1) ? "ok" : "failed");
|
|
|
|
else
|
|
|
|
return cString("Cannot switch device");
|
|
|
|
}
|
2015-03-07 17:22:02 +01:00
|
|
|
else if (strcasecmp(commandP, "PREV") == 0) {
|
2005-11-13 03:20:00 +01:00
|
|
|
if (cFemonOsd::Instance())
|
|
|
|
return cString::sprintf("Switching to previous device: %s", cFemonOsd::Instance()->DeviceSwitch(-1) ? "ok" : "failed");
|
|
|
|
else
|
|
|
|
return cString("Cannot switch device");
|
|
|
|
}
|
2015-03-07 17:22:02 +01:00
|
|
|
else if (strcasecmp(commandP, "INFO") == 0) {
|
2012-01-15 22:07:53 +01:00
|
|
|
return getFrontendInfo(dev);
|
2006-09-17 03:20:00 +02:00
|
|
|
}
|
2015-03-07 17:22:02 +01:00
|
|
|
else if (strcasecmp(commandP, "NAME") == 0) {
|
2012-01-15 22:07:53 +01:00
|
|
|
return getFrontendName(dev);
|
2005-08-28 03:20:00 +02:00
|
|
|
}
|
2015-03-07 17:22:02 +01:00
|
|
|
else if (strcasecmp(commandP, "STAT") == 0) {
|
2012-01-15 22:07:53 +01:00
|
|
|
return getFrontendStatus(dev);
|
2005-08-28 03:20:00 +02:00
|
|
|
}
|
2015-03-07 17:22:02 +01:00
|
|
|
else if (strcasecmp(commandP, "STRG") == 0) {
|
2012-01-15 22:07:53 +01:00
|
|
|
return cString::sprintf("%d on device #%d", dev->SignalStrength(), dev->CardIndex());
|
2011-09-03 22:00:33 +02:00
|
|
|
}
|
2015-03-07 17:22:02 +01:00
|
|
|
else if (strcasecmp(commandP, "QUAL") == 0) {
|
2012-01-15 22:07:53 +01:00
|
|
|
return cString::sprintf("%d on device #%d", dev->SignalQuality(), dev->CardIndex());
|
2011-09-03 22:00:33 +02:00
|
|
|
}
|
2015-03-07 17:22:02 +01:00
|
|
|
else if (strcasecmp(commandP, "SGNL") == 0) {
|
2017-05-04 21:47:49 +02:00
|
|
|
return cString::sprintf("%.2f dBm on device #%d", getSignal(dev), dev->CardIndex());
|
2005-08-28 03:20:00 +02:00
|
|
|
}
|
2017-05-04 21:47:49 +02:00
|
|
|
else if (strcasecmp(commandP, "CNRA") == 0) {
|
|
|
|
return cString::sprintf("%.2f dB on device #%d", getCNR(dev), dev->CardIndex());
|
2005-08-28 03:20:00 +02:00
|
|
|
}
|
2015-03-07 17:22:02 +01:00
|
|
|
else if (strcasecmp(commandP, "BERA") == 0) {
|
2017-05-04 21:47:49 +02:00
|
|
|
return cString::sprintf("%.0f on device #%d", getBER(dev), dev->CardIndex());
|
2005-08-28 03:20:00 +02:00
|
|
|
}
|
2017-05-04 21:47:49 +02:00
|
|
|
else if (strcasecmp(commandP, "PERA") == 0) {
|
|
|
|
return cString::sprintf("%.0f on device #%d", getPER(dev), dev->CardIndex());
|
2005-08-28 03:20:00 +02:00
|
|
|
}
|
2015-03-07 17:22:02 +01:00
|
|
|
else if (strcasecmp(commandP, "VIBR") == 0) {
|
2005-11-13 03:20:00 +01:00
|
|
|
if (cFemonOsd::Instance())
|
2006-09-17 03:20:00 +02:00
|
|
|
return cString::sprintf("%s on device #%d", *getBitrateMbits(cFemonOsd::Instance()->GetVideoBitrate()), cDevice::ActualDevice()->CardIndex());
|
2005-11-13 03:20:00 +01:00
|
|
|
else
|
|
|
|
return cString::sprintf("--- Mbit/s on device #%d", cDevice::ActualDevice()->CardIndex());
|
2005-08-28 03:20:00 +02:00
|
|
|
}
|
2015-03-07 17:22:02 +01:00
|
|
|
else if (strcasecmp(commandP, "AUBR") == 0) {
|
2005-11-13 03:20:00 +01:00
|
|
|
if (cFemonOsd::Instance())
|
2006-09-17 03:20:00 +02:00
|
|
|
return cString::sprintf("%s on device #%d", *getBitrateKbits(cFemonOsd::Instance()->GetAudioBitrate()), cDevice::ActualDevice()->CardIndex());
|
2005-11-13 03:20:00 +01:00
|
|
|
else
|
|
|
|
return cString::sprintf("--- kbit/s on device #%d", cDevice::ActualDevice()->CardIndex());
|
|
|
|
}
|
2015-03-07 17:22:02 +01:00
|
|
|
else if (strcasecmp(commandP, "DDBR") == 0) {
|
2005-11-13 03:20:00 +01:00
|
|
|
if (cFemonOsd::Instance())
|
2006-09-17 03:20:00 +02:00
|
|
|
return cString::sprintf("%s on device #%d", *getBitrateKbits(cFemonOsd::Instance()->GetDolbyBitrate()), cDevice::ActualDevice()->CardIndex());
|
2005-11-13 03:20:00 +01:00
|
|
|
else
|
|
|
|
return cString::sprintf("--- kbit/s on device #%d", cDevice::ActualDevice()->CardIndex());
|
2005-08-28 03:20:00 +02:00
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2004-02-15 03:20:00 +01:00
|
|
|
VDRPLUGINCREATOR(cPluginFemon); // Don't touch this!
|