/* * avards.c: A VDR plugin to adapt the WSS signal to the actual picture size * * Copyright (C) 2007 - 2009 Christoph Haubrich * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * Or, point your browser to http://www.gnu.org/licenses/old-licenses/gpl-2.0.html * * See the README file how to reach the author. * * $Id$ */ #include #include #include #include "avards.h" #if APIVERSNUM < 10507 #include "i18n.h" #define trNOOP(s) (s) #endif #include "setup.h" #include "detector.h" #include "avards_services.h" static const char *VERSION = "0.2.2"; static const char *DESCRIPTION = "Automatic Video Aspect Ratio Detection and Signaling"; #define DEFAULT_VIDEO_DEVICE "/dev/video0" #define DEFAULT_DVB_DEVICE "/dev/dvb/adapter0" #define DEFAULT_VBI_DEVICE "/dev/vbi0" #define DEFAULT_MAX_LOGO_WIDTH_PCT 20 #define DEFAULT_PAN_TONE_TOLERANCE 8 #define DEFAULT_PAN_TONE_BLACK_MAX 0 #define DEFAULT_OVERSCAN_PCT 3 #define DEFAULT_POLL_RATE_MS 80 #define DEFAULT_DELAY_CNT 5 cParameter config; class cPluginAvards : public cPlugin { private: // Add any member variables or functions you may need here. cDetector *detector; std::string m_mainMenuEntry; cString mainmenuentry; bool quirkmode; bool grabfromdevice; public: cPluginAvards(void); virtual ~cPluginAvards(); virtual const char *Version(void) { return VERSION; } virtual const char *Description(void) { return 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); virtual time_t WakeupTime(void); virtual const char *MainMenuEntry(void); virtual cOsdObject *MainMenuAction(void); virtual cMenuSetupPage *SetupMenu(void); virtual bool SetupParse(const char *Name, const char *Value); virtual bool Service(const char *Id, void *Data = NULL); virtual const char **SVDRPHelpPages(void); virtual cString SVDRPCommand(const char *Command, const char *Option, int &ReplyCode); }; cPluginAvards::cPluginAvards(void) { // 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! config.pszDevVideo = (char *)DEFAULT_VIDEO_DEVICE; config.pszDevDvbAdapter = (char *)DEFAULT_DVB_DEVICE; config.pszDevVbi = (char *)DEFAULT_VBI_DEVICE; config.ShowInMainMenu = true; config.AutoStart = false; config.Mode = MODE_AUTO; config.Overzoom = false; config.PanToneTolerance = DEFAULT_PAN_TONE_TOLERANCE; config.PanToneBlackMax = DEFAULT_PAN_TONE_BLACK_MAX; config.Overscan_pct = DEFAULT_OVERSCAN_PCT; config.ShowAllLines = false; config.MaxLogoWidth_pct = DEFAULT_MAX_LOGO_WIDTH_PCT; config.PollRate = DEFAULT_POLL_RATE_MS; config.Delay = DEFAULT_DELAY_CNT; config.ShowMsg = false; config.VDROSDisPAL = true; detector = NULL; mainmenuentry = NULL; quirkmode = false; grabfromdevice = true; } cPluginAvards::~cPluginAvards() { // Clean up after yourself! delete detector; detector = NULL; } const char *cPluginAvards::CommandLineHelp(void) { // Return a string that describes all known command line options. return " -v, --dev_video= Video device\n" " (default is " DEFAULT_VIDEO_DEVICE ")\n" " -d, --dev_dvb= DVB device\n" " (default is " DEFAULT_DVB_DEVICE ")\n" " -b, --dev_vbi= VBI device\n" " (default is " DEFAULT_VBI_DEVICE ")\n" " -q, --quirk-mode use 0x0e as default WSS code\n" " -g, --grab grab pictures from VDR instead directly from device\n"; } bool cPluginAvards::ProcessArgs(int argc, char *argv[]) { // Implement command line argument processing here if applicable. static struct option long_options[] = { { "dev_video", required_argument, 0, 'v' }, { "dev_dvb", required_argument, 0, 'd' }, { "dev_vbi", required_argument, 0, 'b' }, { "quirk-mode",no_argument, 0, 'q' }, { "grab", no_argument, 0, 'g' }, { NULL } }; int c; while ((c = getopt_long(argc, argv, "v:d:b:q:g", long_options, NULL)) != -1) { switch (c) { case 'v': config.pszDevVideo = optarg; break; case 'd': config.pszDevDvbAdapter = optarg; break; case 'b': config.pszDevVbi = optarg; break; case 'q': quirkmode = true; break; case 'g': grabfromdevice= false; break; default: return false; } } return true; } bool cPluginAvards::Initialize(void) { // Initialize any background activities the plugin shall perform. detector = new cDetector(quirkmode, grabfromdevice); return detector != NULL; } bool cPluginAvards::Start(void) { // Start any background activities the plugin shall perform. #if VDRVERSNUM < 10507 RegisterI18n(Phrases); #endif bool result = true; if (config.AutoStart) result = detector->StartUp(); return result; } void cPluginAvards::Stop(void) { // Stop any background activities the plugin shall perform. detector->Stop(); } void cPluginAvards::Housekeeping(void) { // Perform any cleanup or other regular tasks. } void cPluginAvards::MainThreadHook(void) { // Perform actions in the context of the main program thread. // WARNING: Use with great care - see PLUGINS.html! } cString cPluginAvards::Active(void) { // Return a message string if shutdown should be postponed return NULL; } time_t cPluginAvards::WakeupTime(void) { // Return custom wakeup time for shutdown script return 0; } const char *cPluginAvards::MainMenuEntry(void) { if (config.ShowInMainMenu) { const char *modes[MAX_MODES]; modes[0] = tr("auto"); modes[1] = tr("force 4:3"); modes[2] = tr("force L14:9"); modes[3] = tr("force L16:9"); modes[4] = tr("force L>16:9"); modes[5] = tr("force 16:9"); if (detector->Active()) mainmenuentry = cString::sprintf("%s (%s: %s)", tr("Avards stop"), tr("mode"), detector->GetWSSModeString()); else mainmenuentry = cString::sprintf("%s (%s: %s)", tr("Avards start"), tr("detection"), modes[config.Mode]); return (const char *)mainmenuentry; } return NULL; } cOsdObject *cPluginAvards::MainMenuAction(void) { // Perform the action when selected from the main VDR menu. if (detector->Active()) detector->Stop(); else detector->StartUp(); return NULL; } cMenuSetupPage *cPluginAvards::SetupMenu(void) { // Return a setup menu in case the plugin supports one. return new cMenuSetupAvards(); } bool cPluginAvards::SetupParse(const char *Name, const char *Value) { // Parse your own setup parameters and store their values. if (!strcasecmp(Name, "ShowInMainMenu")) config.ShowInMainMenu = atoi(Value); else if (!strcasecmp(Name, "AutoStart")) config.AutoStart = atoi(Value); else if (!strcasecmp(Name, "Mode")) config.Mode = atoi(Value); else if (!strcasecmp(Name, "Overzoom")) config.Overzoom = atoi(Value); else if (!strcasecmp(Name, "PanToneTolerance")) config.PanToneTolerance = atoi(Value); else if (!strcasecmp(Name, "PanToneBlackMax")) config.PanToneBlackMax = atoi(Value); else if (!strcasecmp(Name, "Overscan")) config.Overscan_pct = atoi(Value); else if (!strcasecmp(Name, "ShowAllLines")) config.ShowAllLines = atoi(Value); else if (!strcasecmp(Name, "LogoWidth")) config.MaxLogoWidth_pct = atoi(Value); else if (!strcasecmp(Name, "PollRate")) config.PollRate = atoi(Value); else if (!strcasecmp(Name, "Delay")) config.Delay = atoi(Value); else if (!strcasecmp(Name, "ShowMsg")) config.ShowMsg = atoi(Value); else if (!strcasecmp(Name, "VDROSDisPAL")) config.VDROSDisPAL = atoi(Value); else return false; return true; } bool cPluginAvards::Service(const char *Id, void *Data) { // Handle custom service requests from other plugins #if APIVERSNUM < 10504 if (strcmp(Id, AVARDS_MAXOSDSIZE_SERVICE_STRING_ID) == 0) { if (Data == NULL) return true; detector->GetMaxOSDSize((avards_MaxOSDsize_v1_0*)Data); return true; } #endif if (strcmp(Id, AVARDS_CURRENT_WSSMODE_SERVICE_STRING_ID) == 0) { if (Data == NULL) return true; ((avards_CurrentWssMode_v1_0*)Data)->ModeString = detector->GetWSSModeString(); return true; } if (strcmp(Id, AVARDS_CURRENT_VIDEO_FORMAT_SERVICE_STRING_ID) == 0) { if (Data == NULL) return true; detector->GetVideoFormat((avards_CurrentVideoFormat_v1_0*)Data); return true; } return false; } const char **cPluginAvards::SVDRPHelpPages(void) { // Return help text for SVDRP commands this plugin implements static const char *HelpPages[] = { "START\n" " Start AVARDS detection and WSS Signaling", "STOP\n" " Stop AVARDS detection and WSS Signaling", "STATUS [MODE]\n" " Get current status of AVARDS\n" " If the optional parameter MODE is given it will also show the actual WSS\n" " mode which is one of \"4:3\", \"L14:9\", \"16:9\", \"L16:9\" and \"L>16:9\"", NULL }; return HelpPages; } cString cPluginAvards::SVDRPCommand(const char *Command, const char *Option, int &ReplyCode) { // Process SVDRP commands this plugin implements if (strcasecmp(Command, "START") == 0) { if (detector->Active()) { ReplyCode = 910; return "Avards already running"; } else { detector->Start(); ReplyCode = 900; return "Avards started"; } } else if (strcasecmp(Command, "STOP") == 0) { if (detector->Active()) { detector->Stop(); ReplyCode = 900; return "Avards stopped"; } else { ReplyCode = 910; return "Avards was not running"; } } else if (strcasecmp(Command, "STATUS") == 0) { bool mode = false; if (*Option) { mode = strcasecmp(Option, "MODE") == 0; if (!mode) { ReplyCode = 504; return cString::sprintf("Unknown option: \"%s\"", Option); } } if (detector->Active()) { ReplyCode = 901; if (mode) { return cString::sprintf("Avards is active with mode \"%s\"", detector->GetWSSModeString()); } else return "Avards is active"; } else { ReplyCode = 902; return "Avards is not active"; } } return NULL; } VDRPLUGINCREATOR(cPluginAvards); // Don't touch this!