SASC-NG
DVBSoftCAM

filter.c

Go to the documentation of this file.
00001 /*
00002  * Softcam plugin to VDR (C++)
00003  *
00004  * This code is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License
00006  * as published by the Free Software Foundation; either version 2
00007  * of the License, or (at your option) any later version.
00008  *
00009  * This code is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software
00016  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00017  * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
00018  */
00019 
00020 #include <stdlib.h>
00021 #include <stdio.h>
00022 #include <errno.h>
00023 #include <fcntl.h>
00024 #include <sys/ioctl.h>
00025 #include <sys/poll.h>
00026 #include <unistd.h>
00027 
00028 #include <linux/dvb/dmx.h>
00029 
00030 #include <vdr/device.h>
00031 #include <vdr/tools.h>
00032 
00033 #include "filter.h"
00034 #include "misc.h"
00035 #include "log-core.h"
00036 
00037 // -- cPidFilter ------------------------------------------------------------------
00038 
00039 cPidFilter::cPidFilter(const char *Id, int Num, cDevice *Device, unsigned int IdleTime)
00040 {
00041   device=Device;
00042   idleTime=IdleTime;
00043   id=0; fd=-1; forceRun=false; userData=0;
00044   id=bprintf("%s/%d",Id,Num);
00045   PRINTF(L_CORE_ACTION,"new filter '%s' (%d ms)",id,idleTime);
00046 }
00047 
00048 cPidFilter::~cPidFilter()
00049 {
00050   cMutexLock lock(this);
00051   Stop();
00052   PRINTF(L_CORE_ACTION,"filter '%s' removed",id);
00053   free(id);
00054 }
00055 
00056 void cPidFilter::Flush(void)
00057 {
00058   cMutexLock lock(this);
00059   if(fd>=0) {
00060     unsigned char buff[MAX_SECT_SIZE];
00061     while(read(fd,buff,sizeof(buff))>0);
00062     }
00063 }
00064 
00065 void cPidFilter::Start(int Pid, int Section, int Mask)
00066 {
00067   cMutexLock lock(this);
00068   Stop();
00069   fd=device->OpenFilter(Pid,Section,Mask);
00070   if(fd>=0) {
00071     pid=Pid;
00072 
00073     LBSTART(L_CORE_ACTION);
00074     LBPUT("filter '%s' -> pid=0x%04x sct=0x%02x/0x%02x matching",id,Pid,Section,Mask);
00075     int Mode=0;
00076     int mam =Mask &  (~Mode);
00077     int manm=Mask & ~(~Mode);
00078     for(int i=0; i<256; i++) {
00079       int xxxor=Section ^ i;
00080       if((mam&xxxor) || (manm && !(manm&xxxor))) {}
00081       else
00082         LBPUT(" 0x%02x",i);
00083       }
00084     LBEND();
00085     }
00086 }
00087 
00088 void cPidFilter::Stop(void)
00089 {
00090   cMutexLock lock(this);
00091   if(fd>=0) { device->CloseFilter(fd); fd=-1; }
00092 }
00093 
00094 void cPidFilter::SetBuffSize(int BuffSize)
00095 {
00096   cMutexLock lock(this);
00097   if(fd>=0) {
00098     Stop();
00099     int s=max(BuffSize,8192);
00100     CHECK(ioctl(fd,DMX_SET_BUFFER_SIZE,s));
00101     }
00102 }
00103 
00104 int cPidFilter::SetIdleTime(unsigned int IdleTime)
00105 {
00106   int i=idleTime;
00107   idleTime=IdleTime;
00108   return i;
00109 }
00110 
00111 void cPidFilter::Wakeup(void)
00112 {
00113   cMutexLock lock(this);
00114   forceRun=true;
00115   PRINTF(L_CORE_ACTION,"filter '%s': wakeup",id);
00116 }
00117 
00118 int cPidFilter::Pid(void)
00119 {
00120   return Active() ? pid : -1;
00121 }
00122 
00123 // -- cAction ------------------------------------------------------------------
00124 
00125 cAction::cAction(const char *Id, cDevice *Device, const char *DevId)
00126 {
00127   device=Device; devId=DevId;
00128   id=bprintf("%s %s",Id,DevId);
00129   unique=0; pri=-1;
00130   SetDescription("%s filter",id);
00131 }
00132 
00133 cAction::~cAction()
00134 {
00135   Cancel(2);
00136   DelAllFilter();
00137   PRINTF(L_CORE_ACTION,"%s: stopped",id);
00138   free(id);
00139 }
00140 
00141 cPidFilter *cAction::CreateFilter(int Num, int IdleTime)
00142 {
00143   return new cPidFilter(id,Num,device,IdleTime);
00144 }
00145 
00146 cPidFilter *cAction::NewFilter(int IdleTime)
00147 {
00148   Lock();
00149   cPidFilter *filter=CreateFilter(unique++,IdleTime);
00150   if(filter) {
00151     if(!Active()) {
00152       Start();
00153       PRINTF(L_CORE_ACTION,"%s: started",id);
00154       }
00155     filters.Add(filter);
00156     }
00157   else
00158     PRINTF(L_CORE_ACTION,"%s: failed to create filter",id);
00159   Unlock();
00160   return filter;
00161 }
00162 
00163 cPidFilter *cAction::IdleFilter(void)
00164 {
00165   Lock();
00166   cPidFilter *filter;
00167   for(filter=filters.First(); filter; filter=filters.Next(filter))
00168     if(!filter->Active()) break;
00169   Unlock();
00170   return filter;
00171 }
00172 
00173 void cAction::DelFilter(cPidFilter *filter)
00174 {
00175   Lock();
00176   filters.Del(filter);
00177   Unlock();
00178 }
00179 
00180 void cAction::DelAllFilter(void)
00181 {
00182   Lock();
00183   filters.Clear();
00184   unique=0;
00185   Unlock();
00186 }
00187 
00188 void cAction::Priority(int Pri)
00189 {
00190   pri=Pri;
00191 }
00192 
00193 void cAction::Action(void)
00194 {
00195   if(pri>0) SetPriority(pri);
00196   struct pollfd *pfd=0;
00197   while(Running()) {
00198     if(filters.Count()<=0) {
00199       cCondWait::SleepMs(100);
00200       }
00201     else {
00202       // first build pfd data
00203       Lock();
00204       delete[] pfd; pfd=new struct pollfd[filters.Count()];
00205       if(!pfd) {
00206         PRINTF(L_GEN_ERROR,"action %s: pollfd: out of memory",id);
00207         break;
00208         }
00209       int num=0;
00210       cPidFilter *filter;
00211       for(filter=filters.First(); filter; filter=filters.Next(filter))
00212         if(filter->Active()) {
00213           memset(&pfd[num],0,sizeof(struct pollfd));
00214           pfd[num].fd=filter->fd;
00215           pfd[num].events=POLLIN;
00216           num++;
00217           }
00218       Unlock();
00219 
00220       // now poll for data
00221       int r=poll(pfd,num,60);
00222       if(r<0 && errno!=EINTR) {
00223         PRINTF(L_GEN_ERROR,"action %s poll: %s",id,strerror(errno));
00224         break;
00225         }
00226       if(r>0) {
00227         for(r=0 ; r<num ; r++)
00228           if(pfd[r].revents&POLLIN) {
00229             Lock();
00230             for(filter=filters.First(); filter; filter=filters.Next(filter)) {
00231               if(filter->fd==pfd[r].fd) {
00232                 unsigned char buff[MAX_SECT_SIZE];
00233                 int n=read(filter->fd,buff,sizeof(buff));
00234                 if(n<0 && errno!=EAGAIN) {
00235                   if(errno==EOVERFLOW) {
00236                     filter->Flush();
00237                     //PRINTF(L_GEN_ERROR,"action %s read: Buffer overflow",filter->id);
00238                     }
00239                   else PRINTF(L_GEN_ERROR,"action %s read: %s",filter->id,strerror(errno));
00240                   }
00241                 if(n>0) {
00242                   filter->lastTime.Set(); filter->forceRun=false;
00243                   Process(filter,buff,n);
00244                   // don't make any assumption about data-structs here
00245                   // Process() may have changed them
00246                   }
00247                 break;
00248                 }
00249               }
00250             Unlock();
00251             }
00252         }
00253 
00254       // call filters which are idle too long
00255       Lock();
00256       do {
00257         r=0;
00258         for(filter=filters.First(); filter; filter=filters.Next(filter)) {
00259           if(filter->forceRun || (filter->idleTime && filter->lastTime.Elapsed()>filter->idleTime)) {
00260             filter->lastTime.Set(); filter->forceRun=false;
00261             Process(filter,0,0);
00262             // don't make any assumption about data-structs here
00263             // Process() may have changed them
00264             r=1; break;
00265             }
00266           }
00267         } while(r);
00268       Unlock();
00269       }
00270     }
00271   delete[] pfd;
00272 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines