/* * addons.c: A plugin for the Video Disk Recorder * * See the README file for copyright information and how to reach the author. * * $Id: addons.c 1.11 2004/05/24 19:01:43 kls Exp $ */ #include #include #include #include #include #include #include #include "i18n.h" static const char *VERSION = "0.4.0"; static const char *DESCRIPTION = tr ("Manage addons"); static const char *MAINMENUENTRY = tr ("Addons"); static const char *addonslist = "/tmp/addons.list"; #define MAX_ADDONS 500 // enum { NONE, AKTIV, INAKTIV, UPDATE, INSTALL }; enum { NONE, DELETE, UPDATE, INSTALL, UNINSTALL, INSTALLED, UNINSTALLED, PLUGINS, SYSTEMS }; struct sAddons { char name[50]; char filename[200]; int status; }; bool restart = false; bool rebootpc = false; char readmetext[10001]; bool showReadme = false; class cPluginAddons : public cPlugin { private: // Add any member variables or functions you may need here. public: cPluginAddons (void); virtual ~cPluginAddons (); virtual const char *Version(void) { return VERSION; } virtual const char *Description(void) { return DESCRIPTION; } virtual const char *CommandLineHelp(void); virtual const char **SVDRPHelpPages(void); virtual cString SVDRPCommand(const char *Command, const char *Option, int &ReplyCode); virtual bool ProcessArgs(int argc, char *argv[]); virtual bool Start(void); virtual void Housekeeping(void); virtual const char *MainMenuEntry(void) { return MAINMENUENTRY; } virtual cOsdObject *MainMenuAction(void); virtual cMenuSetupPage *SetupMenu(void); virtual bool SetupParse(const char *Name, const char *Value); }; // ----------------------------------------------------------------------- // --- cMenuReadme ------------------------------------------------------- class cMenuReadme : public cOsdMenu { private: // char text[10001]; public: cMenuReadme (char *name=NULL); eOSState ProcessKey(eKeys k); virtual void Display(void); }; cMenuReadme::cMenuReadme (char *name) : cOsdMenu (tr ("Readme")) { FILE *in, *in2; char *command; char filename[200]; int len = 0; if (name) { Skins.Message (mtStatus, tr ("Searching for description ...")); Skins.Flush (); asprintf (&command, "addons.sh readme %s", name); if (system(command)) { Skins.Message (mtError, tr ("Error in searching for a description!")); } else { if ((in = fopen (addonslist, "r")) != NULL) { if (fscanf (in, "%200s", filename) != EOF) { if ((in2 = fopen (filename, "r")) != NULL) { if ((len = fread (readmetext, sizeof (char), 10000, in2)) != 0) { readmetext[len] = '\0'; } fclose (in2); } } fclose (in); } if (len == 0) { sprintf (readmetext, "%s", tr ("No description found for Addon")); } } } } void cMenuReadme::Display(void) { cOsdMenu::Display(); DisplayMenu()->SetText(readmetext, true); showReadme = false; } eOSState cMenuReadme::ProcessKey(eKeys k) { switch (k) { case kUp|k_Repeat: case kUp: case kDown|k_Repeat: case kDown: case kLeft|k_Repeat: case kLeft: case kRight|k_Repeat: case kRight: DisplayMenu ()->Scroll (k == kUp || k == kLeft, k == kLeft || k == kRight); return osContinue; default: break; } eOSState state = cOsdMenu::ProcessKey(k); switch(state) { case osUnknown: switch(k) { case kOk: state = osBack; break; default: state = osContinue; break; } break; default: break; } return(state); } // ------------------------------------------------------------------------ // --- cMenuPlugins ------------------------------------------------------- class cMenuPlugins : public cOsdMenu { private: int len; struct sAddons *addons; public: cMenuPlugins (void); ~cMenuPlugins (void); eOSState ProcessKey (eKeys k); void SetHelpKeys (void); }; cMenuPlugins::cMenuPlugins () : cOsdMenu (tr ("Plugins"), 30), len (0) { FILE *in = NULL; addons = (sAddons*) calloc (MAX_ADDONS, sizeof (sAddons)); Skins.Message (mtStatus, tr ("Searching for Plugins ...")); Skins.Flush (); if (system ("addons.sh list-plugins")) { Skins.Message(mtError, tr ("Error by searching for Plugins!")); } else { if ((in = fopen (addonslist, "r")) != NULL) { while (fscanf (in, "%50s\t%200s", addons[len].name, addons[len].filename) != EOF && len < MAX_ADDONS) { *strchr (addons[len].name, '_') = '\t'; addons[len].status = INSTALL; Add (new cOsdItem (addons[len].name)); len ++; } fclose (in); } if (len == 0) { addons[0].status = NONE; Add (new cOsdItem (tr ("No Plugins found"))); } } SetCurrent (First ()); SetHelpKeys (); } cMenuPlugins::~cMenuPlugins () { free (addons); } eOSState cMenuPlugins::ProcessKey (eKeys k) { char *command; eOSState state = cOsdMenu::ProcessKey (k); switch(state) { case osUnknown: switch(k) { case kOk: return AddSubMenu (new cMenuReadme (addons[Current ()].filename)); break; case kRed: // Addon installieren if (addons[Current ()].status == INSTALL) { Skins.Message (mtStatus, tr ("Loading Addon ...")); Skins.Flush (); asprintf (&command, "addons.sh install %s", addons[Current ()].filename); if (system(command)) { Skins.Message(mtError, tr ("Error by installing the Addon!")); } else { addons[Current ()].status = NONE; Skins.Message (mtStatus, NULL); restart = true; } } state = osContinue; break; case kGreen: // Addon bis zum nächsten Reboot Installieren if (addons[Current ()].status == INSTALL) { Skins.Message (mtStatus, tr ("Loading Addon ...")); Skins.Flush (); asprintf (&command, "addons.sh install-ones %s", addons[Current ()].filename); if (system(command)) { Skins.Message(mtError, tr ("Error by installing the Addon!")); } else { addons[Current ()].status = NONE; Skins.Message (mtStatus, NULL); restart = true; } } state = osContinue; break; case kBlue: // restart vdr if (restart) { if (Interface->Confirm (cRecordControls::Active() ? tr ("Recording - nevertheless restart VDR?") : tr ("Restart VDR?"))) { Skins.Message (mtStatus, tr ("Restarting VDR ...")); Skins.Flush (); //cThread::EmergencyExit(true); if (system ("addons.sh restart")) { Skins.Message (mtError, tr ("Error by restarting VDR!")); } else { return osEnd; } } } state = osContinue; break; default: break; } break; default: break; } if (!HasSubMenu() && k != kNone) SetHelpKeys (); return(state); } void cMenuPlugins::SetHelpKeys (void) { SetHelp ( (addons[Current ()].status==INSTALL) ? tr ("install") : "", (addons[Current ()].status==INSTALL) ? tr ("install-ones") : "", "", (restart) ? tr ("activate") : "" ); } // ------------------------------------------------------------------------ // --- cMenuSystems ------------------------------------------------------- class cMenuSystems : public cOsdMenu { private: int len; struct sAddons *addons; public: cMenuSystems (void); ~cMenuSystems (void); eOSState ProcessKey (eKeys k); void SetHelpKeys (void); }; cMenuSystems::cMenuSystems () : cOsdMenu (tr ("Systems"), 30), len (0) { FILE *in = NULL; addons = (sAddons*) calloc (MAX_ADDONS, sizeof (sAddons)); Skins.Message (mtStatus, tr ("Searching for system Addons ...")); Skins.Flush (); if (system ("addons.sh list-systems")) { Skins.Message(mtError, tr ("Error by searching for system Addons!")); } else { if ((in = fopen (addonslist, "r")) != NULL) { while (fscanf (in, "%50s\t%200s", addons[len].name, addons[len].filename) != EOF && len < MAX_ADDONS) { *strchr (addons[len].name, '_') = '\t'; addons[len].status = INSTALL; Add (new cOsdItem (addons[len].name)); len ++; } fclose (in); } if (len == 0) { addons[0].status = NONE; Add (new cOsdItem (tr ("No system Addons found"))); } } SetCurrent (First ()); SetHelpKeys (); } cMenuSystems::~cMenuSystems () { free (addons); } eOSState cMenuSystems::ProcessKey (eKeys k) { char *command; eOSState state = cOsdMenu::ProcessKey (k); switch(state) { case osUnknown: switch(k) { case kOk: return AddSubMenu (new cMenuReadme (addons[Current ()].filename)); break; case kRed: // Addon installieren if (addons[Current ()].status == INSTALL) { Skins.Message (mtStatus, tr ("Loading Addon ...")); Skins.Flush (); asprintf (&command, "addons.sh install %s", addons[Current ()].filename); if (system(command)) { Skins.Message(mtError, tr ("Error by installing the Addon!")); } else { addons[Current ()].status = NONE; Skins.Message (mtStatus, NULL); restart = true; } } state = osContinue; break; case kGreen: // Addon installieren if (addons[Current ()].status == INSTALL) { Skins.Message (mtStatus, tr ("Loading Addon ...")); Skins.Flush (); asprintf (&command, "addons.sh install-ones %s", addons[Current ()].filename); if (system(command)) { Skins.Message(mtError, tr ("Error by installing the Addon!")); } else { addons[Current ()].status = NONE; Skins.Message (mtStatus, NULL); restart = true; } } state = osContinue; break; case kBlue: // restart vdr if (restart) { if (Interface->Confirm (cRecordControls::Active() ? tr ("Recording - nevertheless restart VDR?") : tr ("Restart VDR?"))) { Skins.Message (mtStatus, tr ("Restarting VDR ...")); Skins.Flush (); //cThread::EmergencyExit(true); if (system ("addons.sh restart")) { Skins.Message (mtError, tr ("Error by restarting VDR!")); } else { return osEnd; } } } state = osContinue; break; default: break; } break; default: break; } if (!HasSubMenu() && k != kNone) SetHelpKeys (); return(state); } void cMenuSystems::SetHelpKeys (void) { SetHelp ( (addons[Current ()].status==INSTALL) ? tr ("install") : "", (addons[Current ()].status==INSTALL) ? tr ("install-ones") : "", "", (restart) ? tr ("activate") : "" ); } // -------------------------------------------------------------------------- // --- cMenuLoad ------------------------------------------------------- class cMenuLoad : public cOsdMenu { private: int len; struct sAddons *addons; public: cMenuLoad (void); ~cMenuLoad (void); eOSState ProcessKey (eKeys k); void SetHelpKeys (void); }; cMenuLoad::cMenuLoad (void) : cOsdMenu (tr ("Loading")), len (0) { FILE *in = NULL; addons = (sAddons*) calloc (MAX_ADDONS, sizeof (sAddons)); Skins.Message (mtStatus, tr ("Searching for retrofittable Addons ...")); Skins.Flush (); if (system ("addons.sh list-available")) { Skins.Message (mtError, tr ("Error by searching for retrofittable Addons!")); } else { if ((in = fopen (addonslist, "r")) != NULL) { while (fscanf (in, "%50s\t%200s", addons[len].name, addons[len].filename) != EOF && len < MAX_ADDONS) { addons[len].status = INSTALL; Add(new cOsdItem(addons[len].name)); len ++; } fclose (in); } } if (len > 0) { Add (new cOsdItem (tr ("----------"))); addons[len].status = NONE; len ++; } Add (new cOsdItem (tr ("System Addons"))); addons[len].status = SYSTEMS; len ++; Add (new cOsdItem (tr ("VDR Plugins"))); addons[len].status = PLUGINS; len ++; SetCurrent(First()); SetHelpKeys (); } cMenuLoad::~cMenuLoad () { free (addons); } eOSState cMenuLoad::ProcessKey (eKeys k) { char *command; eOSState state = cOsdMenu::ProcessKey (k); switch(state) { case osUnknown: switch(k) { case kOk: if (addons[Current ()].status == INSTALL) { return AddSubMenu (new cMenuReadme (addons[Current ()].filename)); } else if (addons[Current ()].status == SYSTEMS) { return AddSubMenu (new cMenuSystems ()); } else if (addons[Current ()].status == PLUGINS) { return AddSubMenu (new cMenuPlugins ()); } break; case kRed: // Addon installieren if (addons[Current ()].status == INSTALL) { Skins.Message (mtStatus, tr ("Loading Addon ...")); Skins.Flush (); asprintf (&command, "addons.sh install %s", addons[Current ()].filename); if (system(command)) { Skins.Message (mtError, tr ("Error by reloading the Addon!")); } else { addons[Current ()].status = INSTALLED; Skins.Message (mtStatus, NULL); restart = true; } } state = osContinue; break; case kGreen: // load installieren bis zum nächsten Systemstart if (addons[Current ()].status == INSTALL) { Skins.Message (mtStatus, tr ("Loading Addon ...")); Skins.Flush (); asprintf (&command, "addons.sh install-ones %s", addons[Current ()].filename); if (system(command)) { Skins.Message (mtError, tr ("Error by reloading the Addon!")); } else { addons[Current ()].status = INSTALLED; Skins.Message (mtStatus, NULL); restart = true; } } state = osContinue; break; case kYellow: // addon loeschen if (addons[Current ()].status == INSTALL || addons[Current ()].status == INSTALLED) { if (Interface->Confirm (tr ("Delete Addon?"))) { asprintf (&command, "addons.sh delete %s", addons[Current ()].filename); if (system(command)) { Skins.Message(mtError, tr ("Error by deleting the Addon!")); } else { addons[Current ()].status = NONE; } } } state = osContinue; break; case kBlue: // restart vdr if (restart) { if (Interface->Confirm (cRecordControls::Active() ? tr ("Recording - nevertheless restart VDR?") : tr ("Restart VDR?"))) { Skins.Message (mtStatus, tr ("Restarting VDR ...")); Skins.Flush (); //cThread::EmergencyExit(true); if (system ("addons.sh restart")) { Skins.Message (mtError, tr ("Error by restarting VDR!")); } else { return osEnd; } } } state = osContinue; break; default: break; } break; default: break; } if (!HasSubMenu() && k != kNone) SetHelpKeys (); return(state); } void cMenuLoad::SetHelpKeys (void) { SetHelp ( (addons[Current ()].status==INSTALL) ? tr ("load") : "", (addons[Current ()].status==INSTALL) ? tr ("load-ones") : "", (addons[Current ()].status==INSTALL) ? tr ("delete") : "", (restart) ? tr ("activate") : "" ); } // -------------------------------------------------------------------------- // --- cMenuUnload ------------------------------------------------------- class cMenuUnload : public cOsdMenu { private: int len; struct sAddons *addons; public: cMenuUnload (void); ~cMenuUnload (void); eOSState ProcessKey (eKeys k); void SetHelpKeys (void); }; cMenuUnload::cMenuUnload (void) : cOsdMenu (tr ("Unloading")), len (0) { FILE *in = NULL; addons = (sAddons*) calloc (MAX_ADDONS, sizeof (sAddons)); Skins.Message (mtStatus, tr ("Searching for Addons loaded ...")); Skins.Flush (); if (system ("addons.sh list")) { Skins.Message (mtError, tr ("Error by searching for loaded Addons!")); } else { if ((in = fopen (addonslist, "r")) != NULL) { while (fscanf (in, "%50s\t%200s", addons[len].name, addons[len].filename) != EOF && len < MAX_ADDONS) { addons[len].status = UNINSTALL; Add(new cOsdItem(addons[len].name)); len ++; } fclose (in); } if (len == 0) { addons[len].status = NONE; Add (new cOsdItem (tr ("No loaded Addons found"))); len ++; } } SetCurrent(First()); SetHelpKeys (); } cMenuUnload::~cMenuUnload () { free (addons); } eOSState cMenuUnload::ProcessKey (eKeys k) { char *command; eOSState state = cOsdMenu::ProcessKey (k); switch(state) { case osUnknown: switch(k) { case kOk: return AddSubMenu (new cMenuReadme (addons[Current ()].filename)); break; case kRed: // uninstall Addon if (addons[Current ()].status == UNINSTALL) { Skins.Message (mtStatus, tr ("Unloading Addon ...")); Skins.Flush (); asprintf (&command, "addons.sh uninstall %s", addons[Current ()].filename); if (system(command)) { Skins.Message (mtError, tr ("Error by unloading the Addon!")); } else { addons[Current ()].status = UNINSTALLED; Skins.Message (mtStatus, NULL); restart = true; } } state = osContinue; break; case kGreen: // uninstall Addon bis zum nächsten Systemstart if (addons[Current ()].status == UNINSTALL) { Skins.Message (mtStatus, tr ("Unloading Addon ...")); Skins.Flush (); asprintf (&command, "addons.sh uninstall-ones %s", addons[Current ()].filename); if (system(command)) { Skins.Message (mtError, tr ("Error by unloading the Addon!")); } else { addons[Current ()].status = UNINSTALLED; Skins.Message (mtStatus, NULL); restart = true; } } state = osContinue; break; case kYellow: // addon loeschen if (addons[Current ()].status == UNINSTALL || addons[Current ()].status == UNINSTALLED) { if (Interface->Confirm (tr ("Delete Addon?"))) { asprintf (&command, "addons.sh delete %s", addons[Current ()].filename); if (system(command)) { Skins.Message(mtError, tr ("Error by deleting the Addon!")); } else { addons[Current ()].status = NONE; } } } state = osContinue; break; case kBlue: // restart vdr if (restart) { if (Interface->Confirm (cRecordControls::Active() ? tr ("Recording - nevertheless restart VDR?") : tr ("Restart VDR?"))) { Skins.Message (mtStatus, tr ("Restarting VDR ...")); Skins.Flush (); //cThread::EmergencyExit(true); if (system ("addons.sh restart")) { Skins.Message (mtError, tr ("Error by restarting VDR!")); } else { return osEnd; } } } state = osContinue; break; default: break; } break; default: break; } if (!HasSubMenu() && k != kNone) SetHelpKeys (); return(state); } void cMenuUnload::SetHelpKeys (void) { SetHelp ( (addons[Current ()].status==UNINSTALL) ? tr ("unload") : "", (addons[Current ()].status==UNINSTALL) ? tr ("unload-ones") : "", (addons[Current ()].status==UNINSTALL || addons[Current ()].status==UNINSTALLED) ? tr ("delete") : "", (restart) ? tr ("activate") : "" ); } // ----------------------------------------------------------------------- // --- cMenuUpdate ------------------------------------------------------- class cMenuUpdate : public cOsdMenu { private: int len; struct sAddons *addons; public: cMenuUpdate (void); ~cMenuUpdate (void); eOSState ProcessKey (eKeys k); void SetHelpKeys (void); }; cMenuUpdate::cMenuUpdate () : cOsdMenu (tr ("Updates"), 30), len (0) { FILE *in = NULL; addons = (sAddons*) calloc (MAX_ADDONS, sizeof (sAddons)); Skins.Message (mtStatus, tr ("Searching for Updates ...")); Skins.Flush (); if (system ("addons.sh list-updates")) { Skins.Message (mtError, tr ("Error by searching for updates!")); } else { if ((in = fopen (addonslist, "r")) != NULL) { while (fscanf (in, "%50s\t%200s", addons[len].name, addons[len].filename) != EOF && len < MAX_ADDONS) { *strchr (addons[len].name, '_') = '\t'; addons[len].status = UPDATE; Add (new cOsdItem (addons[len].name)); len ++; } fclose (in); } if (len == 0) { addons[0].status = NONE; Add (new cOsdItem (tr ("No updates found"))); } } SetCurrent (First ()); SetHelpKeys (); } cMenuUpdate::~cMenuUpdate () { free (addons); } eOSState cMenuUpdate::ProcessKey (eKeys k) { char *command; eOSState state = cOsdMenu::ProcessKey (k); int i; switch(state) { case osUnknown: switch(k) { case kOk: return AddSubMenu (new cMenuReadme (addons[Current ()].filename)); break; case kRed: // Addon updaten if (addons[Current ()].status == UPDATE) { Skins.Message (mtStatus, tr ("Loading Addon ...")); Skins.Flush (); asprintf (&command, "addons.sh update %s", addons[Current ()].filename); if (system(command)) { Skins.Message(mtError, tr ("Error by update the Addon!")); } else { addons[Current ()].status = NONE; Skins.Message (mtStatus, NULL); rebootpc = true; } } state = osContinue; break; case kGreen: // Alle Addons updaten Skins.Message (mtStatus, tr ("Loading Addons ...")); Skins.Flush (); asprintf (&command, "addons.sh update-all"); if (system(command)) { Skins.Message(mtError, tr ("Error by update the Addon!")); } else { for (i=0; iConfirm (cRecordControls::Active() ? tr ("Recording - nevertheless reboot the system?") : tr ("Reboot the system?"))) { Skins.Message (mtStatus, tr ("Reboot system ...")); Skins.Flush (); //cThread::EmergencyExit(true); if (system ("addons.sh reboot")) { Skins.Message (mtError, tr ("Error by rebooting the system!")); } else { return osEnd; } } } state = osContinue; break; default: break; } break; default: break; } if (!HasSubMenu() && k != kNone) SetHelpKeys (); return(state); } void cMenuUpdate::SetHelpKeys (void) { SetHelp ( (addons[Current ()].status==UPDATE) ? tr ("update") : "", len ? tr ("update all") : "", "", (rebootpc) ? tr ("reboot") : "" ); } // --------------------------------------------------------------------- // --- cMenuMain ------------------------------------------------------- class cMenuAddons : public cOsdMenu { public: cMenuAddons (void); eOSState ProcessKey(eKeys k); }; cMenuAddons::cMenuAddons (void) : cOsdMenu (tr ("Addons")) { Add (new cOsdItem (tr ("Load"))); Add (new cOsdItem (tr ("Unload"))); Add (new cOsdItem (tr ("Update"))); SetCurrent(First()); } eOSState cMenuAddons::ProcessKey(eKeys k) { eOSState state = cOsdMenu::ProcessKey(k); switch(state) { case osUnknown: switch(k) { case kOk: if (Current ()==0) return AddSubMenu (new cMenuLoad); if (Current ()==1) return AddSubMenu (new cMenuUnload); if (Current ()==2) return AddSubMenu (new cMenuUpdate); break; default: break; } break; default: break; } return(state); } // --- cPluginAddons ---------------------------------------------------------- cPluginAddons::cPluginAddons(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! } cPluginAddons::~cPluginAddons() { // Clean up after yourself! } const char *cPluginAddons::CommandLineHelp(void) { // Return a string that describes all known command line options. return ""; } const char **cPluginAddons::SVDRPHelpPages(void) { static const char *HelpPages[] = { "MESG message\n" " Print the message on the OSD.\n", "ASK message\n" " Ask the message on the OSD and return true ore false.\n", "SHOW file\n" " Show the file on the OSD.", NULL }; return HelpPages; } cString cPluginAddons::SVDRPCommand(const char *Command, const char *Option, int &ReplyCode) { FILE *in; int len = 0; if (strcasecmp(Command, "MESG") == 0) { // we use the default reply code here //Skins.Message(mtStatus, cString::sprintf("%s", Option)); Skins.QueueMessage(mtInfo, cString::sprintf("%s", Option), 0, -1); ReplyCode = 250; return cString::sprintf("Message queued"); } if (strcasecmp(Command, "ASK") == 0) { if (Interface->Confirm(cString::sprintf("%s", Option))) { ReplyCode = 901; return cString::sprintf("yes"); } else { ReplyCode = 900; return cString::sprintf("no"); } } if (strcasecmp(Command, "SHOW") == 0) { // we use the default reply code here if ((in = fopen (Option, "r")) != NULL) { if ((len = fread (readmetext, sizeof (char), 10000, in)) != 0) { readmetext[len] = '\0'; } fclose (in); } else { ReplyCode = 501; return cString::sprintf("File not found"); } if (len) { showReadme = true; cRemote::CallPlugin(Name()); ReplyCode = 250; return cString::sprintf("Message queued"); } ReplyCode = 550; return cString::sprintf("Empty message"); // (new cMenuReadme ((char *) Option))->Display (); } return NULL; } bool cPluginAddons::ProcessArgs(int argc, char *argv[]) { // Implement command line argument processing here if applicable. return true; } bool cPluginAddons::Start(void) { // Start any background activities the plugin shall perform. return true; } void cPluginAddons::Housekeeping(void) { // Perform any cleanup or other regular tasks. } cOsdObject *cPluginAddons::MainMenuAction(void) { // Perform the action when selected from the main VDR menu. if (showReadme) { return new cMenuReadme (); } else { return new cMenuAddons (); } } cMenuSetupPage *cPluginAddons::SetupMenu(void) { // Return a setup menu in case the plugin supports one. return NULL; } bool cPluginAddons::SetupParse(const char *Name, const char *Value) { // Parse your own setup parameters and store their values. return false; } VDRPLUGINCREATOR(cPluginAddons); // Don't touch this!