vdr  2.0.5
sections.c
Go to the documentation of this file.
1 /*
2  * sections.c: Section data handling
3  *
4  * See the main source file 'vdr.c' for copyright information and
5  * how to reach the author.
6  *
7  * $Id: sections.c 2.2 2012/10/04 12:21:59 kls Exp $
8  */
9 
10 #include "sections.h"
11 #include <unistd.h>
12 #include "channels.h"
13 #include "device.h"
14 #include "thread.h"
15 
16 // --- cFilterHandle----------------------------------------------------------
17 
18 class cFilterHandle : public cListObject {
19 public:
21  int handle;
22  int used;
23  cFilterHandle(const cFilterData &FilterData);
24  };
25 
27 {
28  filterData = FilterData;
29  handle = -1;
30  used = 0;
31 }
32 
33 // --- cSectionHandlerPrivate ------------------------------------------------
34 
36 public:
38  };
39 
40 // --- cSectionHandler -------------------------------------------------------
41 
43 :cThread("section handler", true)
44 {
46  device = Device;
47  statusCount = 0;
48  on = false;
49  waitForLock = false;
51  Start();
52 }
53 
55 {
56  Cancel(3);
57  cFilter *fi;
58  while ((fi = filters.First()) != NULL)
59  Detach(fi);
60  delete shp;
61 }
62 
64 {
65  return shp->channel.Source();
66 }
67 
69 {
70  return shp->channel.Transponder();
71 }
72 
74 {
75  return &shp->channel;
76 }
77 
78 void cSectionHandler::Add(const cFilterData *FilterData)
79 {
80  Lock();
81  statusCount++;
82  cFilterHandle *fh;
83  for (fh = filterHandles.First(); fh; fh = filterHandles.Next(fh)) {
84  if (fh->filterData.Is(FilterData->pid, FilterData->tid, FilterData->mask))
85  break;
86  }
87  if (!fh) {
88  int handle = device->OpenFilter(FilterData->pid, FilterData->tid, FilterData->mask);
89  if (handle >= 0) {
90  fh = new cFilterHandle(*FilterData);
91  fh->handle = handle;
92  filterHandles.Add(fh);
93  }
94  }
95  if (fh)
96  fh->used++;
97  Unlock();
98 }
99 
100 void cSectionHandler::Del(const cFilterData *FilterData)
101 {
102  Lock();
103  statusCount++;
104  cFilterHandle *fh;
105  for (fh = filterHandles.First(); fh; fh = filterHandles.Next(fh)) {
106  if (fh->filterData.Is(FilterData->pid, FilterData->tid, FilterData->mask)) {
107  if (--fh->used <= 0) {
108  device->CloseFilter(fh->handle);
109  filterHandles.Del(fh);
110  break;
111  }
112  }
113  }
114  Unlock();
115 }
116 
118 {
119  Lock();
120  statusCount++;
121  filters.Add(Filter);
122  Filter->sectionHandler = this;
123  if (on)
124  Filter->SetStatus(true);
125  Unlock();
126 }
127 
129 {
130  Lock();
131  statusCount++;
132  Filter->SetStatus(false);
133  Filter->sectionHandler = NULL;
134  filters.Del(Filter, false);
135  Unlock();
136 }
137 
139 {
140  Lock();
141  shp->channel = Channel ? *Channel : cChannel();
142  Unlock();
143 }
144 
146 {
147  Lock();
148  if (on != On) {
149  if (!On || device->HasLock()) {
150  statusCount++;
151  for (cFilter *fi = filters.First(); fi; fi = filters.Next(fi)) {
152  fi->SetStatus(false);
153  if (On)
154  fi->SetStatus(true);
155  }
156  on = On;
157  waitForLock = false;
158  }
159  else
160  waitForLock = On;
161  }
162  Unlock();
163 }
164 
166 {
167  while (Running()) {
168 
169  Lock();
170  if (waitForLock)
171  SetStatus(true);
172  int NumFilters = filterHandles.Count();
173  pollfd pfd[NumFilters];
174  for (cFilterHandle *fh = filterHandles.First(); fh; fh = filterHandles.Next(fh)) {
175  int i = fh->Index();
176  pfd[i].fd = fh->handle;
177  pfd[i].events = POLLIN;
178  pfd[i].revents = 0;
179  }
180  int oldStatusCount = statusCount;
181  Unlock();
182 
183  if (poll(pfd, NumFilters, 1000) > 0) {
184  bool DeviceHasLock = device->HasLock();
185  if (!DeviceHasLock)
186  cCondWait::SleepMs(100);
187  for (int i = 0; i < NumFilters; i++) {
188  if (pfd[i].revents & POLLIN) {
189  cFilterHandle *fh = NULL;
190  LOCK_THREAD;
191  if (statusCount != oldStatusCount)
192  break;
193  for (fh = filterHandles.First(); fh; fh = filterHandles.Next(fh)) {
194  if (pfd[i].fd == fh->handle)
195  break;
196  }
197  if (fh) {
198  // Read section data:
199  unsigned char buf[4096]; // max. allowed size for any EIT section
200  int r = device->ReadFilter(fh->handle, buf, sizeof(buf));
201  if (!DeviceHasLock)
202  continue; // we do the read anyway, to flush any data that might have come from a different transponder
203  if (r > 3) { // minimum number of bytes necessary to get section length
204  int len = (((buf[1] & 0x0F) << 8) | (buf[2] & 0xFF)) + 3;
205  if (len == r) {
206  // Distribute data to all attached filters:
207  int pid = fh->filterData.pid;
208  int tid = buf[0];
209  for (cFilter *fi = filters.First(); fi; fi = filters.Next(fi)) {
210  if (fi->Matches(pid, tid))
211  fi->Process(pid, tid, buf, len);
212  }
213  }
214  else if (time(NULL) - lastIncompleteSection > 10) { // log them only every 10 seconds
215  dsyslog("read incomplete section - len = %d, r = %d", len, r);
216  lastIncompleteSection = time(NULL);
217  }
218  }
219  }
220  }
221  }
222  }
223  }
224 }
int Transponder(void)
Definition: sections.c:68
#define dsyslog(a...)
Definition: tools.h:36
cList< cFilterHandle > filterHandles
Definition: sections.h:32
void Add(cListObject *Object, cListObject *After=NULL)
Definition: tools.c:1945
virtual int OpenFilter(u_short Pid, u_char Tid, u_char Mask)
Opens a file handle for the given filter data.
Definition: device.c:598
const cChannel * Channel(void)
Definition: sections.c:73
virtual int ReadFilter(int Handle, void *Buffer, size_t Length)
Reads data from a handle for the given filter.
Definition: device.c:603
virtual ~cSectionHandler()
Definition: sections.c:54
void Detach(cFilter *Filter)
Definition: sections.c:128
cDevice * device
Definition: sections.h:27
void SetStatus(bool On)
Definition: sections.c:145
u_short pid
Definition: filter.h:28
int Count(void) const
Definition: tools.h:475
void Add(const cFilterData *FilterData)
Definition: sections.c:78
int Transponder(void) const
Returns the transponder frequency in MHz, plus the polarization in case of sat.
Definition: channels.c:156
Definition: filter.h:41
void SetChannel(const cChannel *Channel)
Definition: sections.c:138
void Unlock(void)
Definition: thread.h:93
int Source(void)
Definition: sections.c:63
T * Next(const T *object) const
Definition: tools.h:485
int Source(void) const
Definition: channels.h:163
cSectionHandler(cDevice *Device)
Definition: sections.c:42
virtual void Action(void)
A derived cThread class must implement the code it wants to execute as a separate thread in this func...
Definition: sections.c:165
u_char mask
Definition: filter.h:30
virtual bool HasLock(int TimeoutMs=0) const
Returns true if the device has a lock on the requested transponder.
Definition: device.c:850
static void SleepMs(int TimeoutMs)
Creates a cCondWait object and uses it to sleep for TimeoutMs milliseconds, immediately giving up the...
Definition: thread.c:57
void bool Start(void)
Actually starts the thread.
Definition: thread.c:273
cSectionHandler * sectionHandler
Definition: filter.h:44
bool waitForLock
Definition: sections.h:29
u_char tid
Definition: filter.h:29
bool Running(void)
Returns false if a derived cThread object shall leave its Action() function.
Definition: thread.h:99
bool Is(u_short Pid, u_char Tid, u_char Mask)
Definition: filter.c:58
virtual void CloseFilter(int Handle)
Closes a file handle that has previously been opened by OpenFilter().
Definition: device.c:608
virtual void SetStatus(bool On)
Turns this filter on or off, depending on the value of On.
Definition: filter.c:104
T * First(void) const
Definition: tools.h:482
void Del(cListObject *Object, bool DeleteObject=true)
Definition: tools.c:1977
time_t lastIncompleteSection
Definition: sections.h:30
cList< cFilter > filters
Definition: sections.h:31
cSectionHandlerPrivate * shp
Definition: sections.h:26
void Attach(cFilter *Filter)
Definition: sections.c:117
Definition: thread.h:77
cFilterData filterData
Definition: sections.c:20
#define LOCK_THREAD
Definition: thread.h:161
cFilterHandle(const cFilterData &FilterData)
Definition: sections.c:26
void Cancel(int WaitSeconds=0)
Cancels the thread by first setting 'running' to false, so that the Action() loop can finish in an or...
Definition: thread.c:323
The cDevice class is the base from which actual devices can be derived.
Definition: device.h:104
void Del(const cFilterData *FilterData)
Definition: sections.c:100
void Lock(void)
Definition: thread.h:92