⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sc.c

📁 VDR softcam plugin 0.9.1
💻 C
📖 第 1 页 / 共 3 页
字号:
    if(dev->Cam()) str=dev->Cam()->CurrentKeyStr(num);    if(!str && num==0 && ScSetup.CapCheck(CardNum)) str=strdup(tr("(none)"));    }  return str;}bool cSoftCAM::Active(bool log){  for(int n=cDevice::NumDevices(); --n>=0;) {    cScDvbDevice *dev=dynamic_cast<cScDvbDevice *>(cDevice::GetDevice(n));    if(dev && dev->Cam() && dev->Cam()->Active(log)) return true;    }  return false;}void cSoftCAM::SetLogStatus(int CardNum, const cEcmInfo *ecm, bool on){  cScDvbDevice *dev=dynamic_cast<cScDvbDevice *>(cDevice::GetDevice(CardNum));  if(dev && dev->Cam()) dev->Cam()->LogEcmStatus(ecm,on);}void cSoftCAM::AddHook(int CardNum, cLogHook *hook){  cScDvbDevice *dev=dynamic_cast<cScDvbDevice *>(cDevice::GetDevice(CardNum));  if(dev && dev->Cam()) dev->Cam()->AddHook(hook);}bool cSoftCAM::TriggerHook(int CardNum, int id){  cScDvbDevice *dev=dynamic_cast<cScDvbDevice *>(cDevice::GetDevice(CardNum));  return dev && dev->Cam() && dev->Cam()->TriggerHook(id);}// --- cScHousekeeper ----------------------------------------------------------class cScHousekeeper : public cThread {protected:  virtual void Action(void);public:  cScHousekeeper(void);  ~cScHousekeeper();  };cScHousekeeper::cScHousekeeper(void):cThread("SC housekeeper"){  Start();}cScHousekeeper::~cScHousekeeper(){  Cancel(3);}void cScHousekeeper::Action(void){  int c=0;  while(Running()) {    if(++c==20) {      c=0;      for(int n=cDevice::NumDevices(); --n>=0;) {        cScDvbDevice *dev=dynamic_cast<cScDvbDevice *>(cDevice::GetDevice(n));        if(dev && dev->Cam()) dev->Cam()->HouseKeeping();        }      }    if(Feature.KeyFile()) keys.HouseKeeping();    if(!cSoftCAM::Active(false)) cStructLoaders::Purge();    cStructLoaders::Load(true);    cStructLoaders::Save();    cCondWait::SleepMs(987);    }}#ifndef STATICBUILD// --- cScDll ------------------------------------------------------------------class cScDll : public cSimpleItem {private:  char *fileName;  void *handle;public:  cScDll(const char *FileName);  ~cScDll();  bool Load(void);  };cScDll::cScDll(const char *FileName){  fileName=strdup(FileName);  handle=0;}cScDll::~cScDll(){  if(handle) dlclose(handle);  free(fileName);}bool cScDll::Load(void){  char *base=rindex(fileName,'/');  if(!base) base=fileName;  PRINTF(L_CORE_DYN,"loading library: %s",base);  if(!handle) {    handle=dlopen(fileName,RTLD_NOW|RTLD_LOCAL);    if(handle) return true;    PRINTF(L_GEN_ERROR,"dload: %s: %s",base,dlerror());    }  return false;}// --- cScDlls -----------------------------------------------------------------#define LIBSC_PREFIX  "libsc-"#define SO_INDICATOR   ".so."class cScDlls : public cSimpleList<cScDll> {private:  void *handle;public:  cScDlls(void);  ~cScDlls();  bool Load(void);  };cScDlls::cScDlls(void){  handle=0;}cScDlls::~cScDlls(){  Clear();  if(handle) dlclose(handle);  PRINTF(L_CORE_DYN,"unload done");}bool cScDlls::Load(void){  Dl_info info;  static int marker=0;  if(!dladdr((void *)&marker,&info)) {    PRINTF(L_GEN_ERROR,"dladdr: %s",dlerror());    return false;    }  // we have to re-dlopen our selfs as VDR doesn't use RTLD_GLOBAL  // but our symbols have to be available to the sub libs.  handle=dlopen(info.dli_fname,RTLD_NOW|RTLD_GLOBAL);  if(!handle) {    PRINTF(L_GEN_ERROR,"dlopen myself: %s",dlerror());    return false;    }  char *path=strdup(info.dli_fname);  char *p;  if((p=rindex(path,'/'))) *p=0;  PRINTF(L_CORE_DYN,"library path %sn",path);  char pat[32];  snprintf(pat,sizeof(pat),"%s*-%d%s%s",LIBSC_PREFIX,SCAPIVERS,SO_INDICATOR,APIVERSION);  bool res=true;  cReadDir dir(path);  struct dirent *e;  while((e=dir.Next())) {    if(!fnmatch(pat,e->d_name,FNM_PATHNAME|FNM_NOESCAPE)) {      cScDll *dll=new cScDll(AddDirectory(path,e->d_name));      if(dll) {        if(!dll->Load()) res=false;        Ins(dll);        }      }    }  free(path);  return res;}#endif// --- cScPlugin ---------------------------------------------------------------class cScPlugin : public cPlugin {private:#ifndef STATICBUILD  cScDlls dlls;#endif  cScHousekeeper *keeper;public:  cScPlugin(void);  virtual ~cScPlugin();  virtual const char *Version(void);  virtual const char *Description(void);  virtual const char *CommandLineHelp(void);  virtual bool ProcessArgs(int argc, char *argv[]);  virtual bool Initialize(void);  virtual bool Start(void);  virtual void Stop(void);#ifndef SASC  virtual void MainThreadHook(void);#endif  virtual cMenuSetupPage *SetupMenu(void);  virtual bool SetupParse(const char *Name, const char *Value);  virtual const char **SVDRPHelpPages(void);  virtual cString SVDRPCommand(const char *Command, const char *Option, int &ReplyCode);  };cScPlugin::cScPlugin(void){  static const char *logg[] = { trNOOP("off"),trNOOP("active CAIDs"),trNOOP("all CAIDs") };  static const char *skey[] = { trNOOP("comment out"),trNOOP("remove") };  static const char *ecache[] = { trNOOP("enabled"),trNOOP("read-only"),trNOOP("off") };  ScOpts=new cOpts(0,9);  ScOpts->Add(new cOptSel  ("AutoUpdate"   ,trNOOP("Update keys (AU)")     ,&ScSetup.AutoUpdate,3,logg));  ScOpts->Add(new cOptBool ("PrestartAU"   ,trNOOP("Start AU on EPG scan") ,&ScSetup.PrestartAU));  ScOpts->Add(new cOptSel  ("SuperKeys"    ,trNOOP("Superseded keys")      ,&ScSetup.SuperKeys,2,skey));  ScOpts->Add(new cOptBool ("ConcurrentFF" ,trNOOP("Concurrent FF streams"),&ScSetup.ConcurrentFF));  ScOpts->Add(new cOptBool ("ForceTranfer" ,trNOOP("Force TransferMode")   ,&ScSetup.ForceTransfer));  ScOpts->Add(new cOptBool ("LocalPriority",trNOOP("Prefer local systems") ,&ScSetup.LocalPriority));  ScOpts->Add(new cOptSel  ("EcmCache"     ,trNOOP("ECM cache")            ,&ScSetup.EcmCache,3,ecache));  ScOpts->Add(new cOptMInt ("ScCaps"       ,trNOOP("Active on DVB card")   , ScSetup.ScCaps,MAXSCCAPS,0));  ScOpts->Add(new cOptMInt ("CaIgnore"     ,trNOOP("Ignore CAID")          , ScSetup.CaIgnore,MAXCAIGN,2));  LogOpts=new cOpts(0,6);  LogOpts->Add(new cOptBool ("LogConsole"  ,trNOOP("Log to console")      ,&logcfg.logCon));  LogOpts->Add(new cOptBool ("LogFile"     ,trNOOP("Log to file")         ,&logcfg.logFile));  LogOpts->Add(new cOptStr  ("LogFileName" ,trNOOP("Filename")            ,logcfg.logFilename,sizeof(logcfg.logFilename),FileNameChars));  LogOpts->Add(new cOptInt  ("LogFileLimit",trNOOP("Filesize limit (KB)") ,&logcfg.maxFilesize,0,2000000));  LogOpts->Add(new cOptBool ("LogSyslog"   ,trNOOP("Log to syslog")       ,&logcfg.logSys));  LogOpts->Add(new cOptBool ("LogUserMsg"  ,trNOOP("Show user messages")  ,&logcfg.logUser));#ifndef STATICBUILD  dlls.Load();#endif  cScDvbDevice::Capture();  keeper=0;}cScPlugin::~cScPlugin(){  delete keeper;  delete ScOpts;  delete LogOpts;}bool cScPlugin::Initialize(void){  PRINTF(L_GEN_INFO,"SC version %s initializing",ScVersion);  return cScDvbDevice::Initialize();}bool cScPlugin::Start(void){  PRINTF(L_GEN_INFO,"SC version %s starting",ScVersion);  if(APIVERSNUM<MINAPIVERSNUM) {    PRINTF(L_GEN_ERROR,"SC plugin needs at least VDR API version %d.%d.%d",MIN_VERS,MIN_MAJOR,MIN_MINOR);    return false;    }  if(sizeof(int)!=4) {    PRINTF(L_GEN_ERROR,"compiled with 'int' as %d bit. Only supporting 32 bit.",(int)sizeof(int)*8);    return false;    }  if(sizeof(long long)!=8) {    PRINTF(L_GEN_ERROR,"compiled with 'long long' as %d bit. Only supporting 64 bit.",(int)sizeof(long long)*8);    return false;    }      ScPlugin=this;#if APIVERSNUM < 10507  RegisterI18n(ScPhrases);#endif  const char *cfgdir=ConfigDirectory(cfgsub);  filemaps.SetCfgDir(cfgdir);  cStructLoaders::SetCfgDir(cfgdir);  ScSetup.Check();  if(!cSoftCAM::Load(cfgdir)) return false;  if(Feature.SmartCard()) {#ifdef DEFAULT_PORT    smartcards.AddPort(DEFAULT_PORT);#endif    smartcards.LaunchWatcher();    }  cScDvbDevice::Startup();  keeper=new cScHousekeeper;  return true;}void cScPlugin::Stop(void){  delete keeper; keeper=0;  cScDvbDevice::Shutdown();  LogStatsDown();  cSoftCAM::Shutdown();#if APIVERSNUM < 10507  RegisterI18n(NULL);#endif  PRINTF(L_GEN_DEBUG,"SC cleanup done");}const char *cScPlugin::Version(void){  return ScVersion;}const char *cScPlugin::Description(void){  return tr("A software emulated CAM");}const char *cScPlugin::CommandLineHelp(void){  static char *help_str=0;    free(help_str);    //                                     for easier orientation, this is column 80|  asprintf(&help_str,"  -B N      --budget=N     forces DVB device N to budget mode (using FFdecsa)\n"                     "  -I        --inverse-cd   use inverse CD detection for the next serial device\n"                     "  -R        --inverse-rst  use inverse RESET for the next serial device\n"                     "  -C FREQ   --clock=FREQ   use FREQ as clock for the card reader on the next\n"                     "                           serial device (rather than 3.5712 MHz\n"                     "  -s DEV    --serial=DEV   activate Phoenix ISO interface on serial device DEV\n"                     "                           (default: %s)\n"                     "  -d CMD    --dialup=CMD   call CMD to start/stop dialup-network\n"                     "                           (default: %s)\n"                     "  -t SECS   --timeout=SECS shutdown timeout for dialup-network\n"                     "                           (default: %d secs)\n",                     "none","none",netTimeout/1000                     );  return help_str;}bool cScPlugin::ProcessArgs(int argc, char *argv[]){  static struct option long_options[] = {      { "serial",      required_argument, NULL, 's' },      { "inverse-cd",  no_argument,       NULL, 'I' },      { "inverse-rst", no_argument,       NULL, 'R' },      { "clock",       required_argument, NULL, 'C' },      { "dialup",      required_argument, NULL, 'd' },      { "external-au", required_argument, NULL, 'E' },      { "budget",      required_argument, NULL, 'B' },      { NULL }    };  int c, option_index=0;  bool invCD=false, invRST=false;  int clock=0;  while((c=getopt_long(argc,argv,"d:s:t:B:C:E:IR",long_options,&option_index))!=-1) {    switch (c) {      case 'I': invCD=true; break;      case 'R': invRST=true; break;      case 'C': clock=atoi(optarg); break;      case 's': smartcards.AddPort(optarg,invCD,invRST,clock); invCD=false; invRST=false; clock=0; break;      case 'd': netscript=optarg; break;      case 't': netTimeout=atoi(optarg)*1000; break;      case 'E': externalAU=optarg; break;      case 'B': cScDvbDevice::SetForceBudget(atoi(optarg)); break;      default:  return false;      }    }  return true;}cMenuSetupPage *cScPlugin::SetupMenu(void){  return new cMenuSetupSc(ConfigDirectory(cfgsub));}bool cScPlugin::SetupParse(const char *Name, const char *Value){  if((ScOpts && ScOpts->Parse(Name,Value)) ||     (LogOpts && LogOpts->Parse(Name,Value)) ||     cSystems::ConfigParse(Name,Value)) ;  else if(!strcasecmp(Name,"LogConfig")) cLogging::ParseConfig(Value);  else return false;  return true;}#ifndef SASCvoid cScPlugin::MainThreadHook(void){  int n=0;  cUserMsg *um;  while(++n<=10 && (um=ums.GetQueuedMsg())) {    Skins.QueueMessage(mtInfo,um->Message());    delete um;    }}#endif //SASCconst char **cScPlugin::SVDRPHelpPages(void){  static const char *HelpPages[] = {    "RELOAD\n"    "    Reload all configuration files.",    "KEY <string>\n",    "    Add key to the key database (as if it was received from EMM stream).",    "LOG <on|off> <class>[,<class>...]\n"    "    Turn the given message class(es) on or off.",    "LOGCFG\n"    "    Display available message classes and their status.",    "LOGFILE <on|off> [<filename>]\n"    "    Enables/disables logging to file and optionaly sets the filename.",    NULL    };  return HelpPages;}cString cScPlugin::SVDRPCommand(const char *Command, const char *Option, int &ReplyCode){  if(!strcasecmp(Command,"RELOAD")) {    if(cSoftCAM::Active(true)) {      ReplyCode=550;      return "Softcam active. Can't reload files now";      }    else {      if(cSoftCAM::Load(ConfigDirectory(cfgsub)))        return "Files reloaded successfully";      else {        ReplyCode=901;        return "Reloading files not entirely successfull";        }      }    }  else if(!strcasecmp(Command,"KEY")) {    if(Option && *Option) {      if(keys.NewKeyParse(skipspace(Option),"from SVDR"))        return "Key update successfull";      else {        ReplyCode=901;        return "Key already known or invalid key format";        }      }    else { ReplyCode=501; return "Missing args"; }    }  else if(!strcasecmp(Command,"LOG")) {    if(Option && *Option) {      char tmp[1024];      strn0cpy(tmp,Option,sizeof(tmp));      char *opt=tmp;      opt=skipspace(opt);      bool mode;      if(!strncasecmp(opt,"ON ",3)) { mode=true; opt+=3; }      else if(!strncasecmp(opt,"OFF ",4)) { mode=false; opt+=4; }      else { ReplyCode=501; return "Bad mode, valid: on off"; }      do {        char *s=index(opt,',');        if(s) *s++=0;        int c=cLogging::GetClassByName(opt);        if(c>=0) cLogging::SetModuleOption(c,mode);        else { ReplyCode=501; return "Unknown message class"; }        opt=s;        } while(opt);      ScSetup.Store(true);      Setup.Save();      return "Done";      }    else { ReplyCode=501; return "Missing args"; }    }  else if(!strcasecmp(Command,"LOGCFG")) {    cLineBuff lb(256);    for(int m=1; m<LMOD_MAX; m++) {      const char *name=cLogging::GetModuleName(LCLASS(m,0));      if(name) {        int o=cLogging::GetModuleOptions(LCLASS(m,0));        if(o>=0) {          for(int i=0; i<LOPT_NUM; i++) {            const char *opt;            if(i==0) opt="enable";            else opt=cLogging::GetOptionName(LCLASS(m,1<<i));            if(opt)              lb.Printf("%s.%s %s\n",name,opt,(o&(1<<i))?"on":"off");            }          }        }      }    if(lb.Length()>0) return lb.Line();    ReplyCode=901; return "No config available";    }  else if(!strcasecmp(Command,"LOGFILE")){    if(Option && *Option) {      char tmp[1024];      strn0cpy(tmp,Option,sizeof(tmp));      char *opt=tmp;      opt=skipspace(opt);      bool mode;      if(!strncasecmp(opt,"ON",2)) { mode=true; opt+=2; }      else if(!strncasecmp(opt,"OFF",3)) { mode=false; opt+=3; }      else { ReplyCode=501; return "Bad mode, valid: on off"; }      cLineBuff lb(256);      if(mode) {        logcfg.logFile=true;        if(*opt==' ' || *opt=='\t') {          opt=stripspace(skipspace(opt));          strn0cpy(logcfg.logFilename,opt,sizeof(logcfg.logFilename));          }        lb.Printf("logging to file enabled, file %s",logcfg.logFilename);        }      else {        logcfg.logFile=false;        lb.Printf("logging to file disabled");        }      ScSetup.Store(true);      Setup.Save();      return lb.Line();      }    else { ReplyCode=501; return "Missing args"; }    }  return NULL;}VDRPLUGINCREATOR(cScPlugin); // Don't touch this!

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -