vdr  2.7.6
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 5.4 2022/12/06 12:25:08 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(NULL, true)
44 {
46  device = Device;
47  SetDescription("device %d section handler", device->DeviceNumber() + 1);
48  statusCount = 0;
49  on = false;
50  waitForLock = false;
51  flush = false;
52  startFilters = false;
53  Start();
54 }
55 
57 {
58  Cancel(3);
59  cFilter *fi;
60  while ((fi = filters.First()) != NULL)
61  Detach(fi);
62  delete shp;
63 }
64 
66 {
67  return shp->channel.Source();
68 }
69 
71 {
72  return shp->channel.Transponder();
73 }
74 
76 {
77  return &shp->channel;
78 }
79 
80 void cSectionHandler::Add(const cFilterData *FilterData)
81 {
82  Lock();
83  statusCount++;
84  cFilterHandle *fh;
85  for (fh = filterHandles.First(); fh; fh = filterHandles.Next(fh)) {
86  if (fh->filterData.Is(FilterData->pid, FilterData->tid, FilterData->mask))
87  break;
88  }
89  if (!fh) {
90  int handle = device->OpenFilter(FilterData->pid, FilterData->tid, FilterData->mask);
91  if (handle >= 0) {
92  fh = new cFilterHandle(*FilterData);
93  fh->handle = handle;
94  filterHandles.Add(fh);
95  }
96  }
97  if (fh)
98  fh->used++;
99  Unlock();
100 }
101 
102 void cSectionHandler::Del(const cFilterData *FilterData)
103 {
104  Lock();
105  statusCount++;
106  cFilterHandle *fh;
107  for (fh = filterHandles.First(); fh; fh = filterHandles.Next(fh)) {
108  if (fh->filterData.Is(FilterData->pid, FilterData->tid, FilterData->mask)) {
109  if (--fh->used <= 0) {
110  device->CloseFilter(fh->handle);
111  filterHandles.Del(fh);
112  break;
113  }
114  }
115  }
116  Unlock();
117 }
118 
120 {
121  Lock();
122  statusCount++;
123  filters.Add(Filter);
124  Filter->sectionHandler = this;
125  if (on)
126  Filter->SetStatus(true);
127  Unlock();
128 }
129 
131 {
132  Lock();
133  statusCount++;
134  Filter->SetStatus(false);
135  Filter->sectionHandler = NULL;
136  filters.Del(Filter, false);
137  Unlock();
138 }
139 
141 {
142  Lock();
143  shp->channel = Channel ? *Channel : cChannel();
144  Unlock();
145 }
146 
148 {
149  Lock();
150  if (on != On) {
151  if (!On || (device->HasLock() && startFilters)) {
152  statusCount++;
153  for (cFilter *fi = filters.First(); fi; fi = filters.Next(fi)) {
154  fi->SetStatus(false);
155  if (On)
156  fi->SetStatus(true);
157  }
158  flush = On;
159  if (flush)
160  flushTimer.Set();
161  on = On;
162  waitForLock = false;
163  }
164  else
165  waitForLock = On;
166  }
167  Unlock();
168 }
169 
170 #define FLUSH_TIME 100 // ms
171 
173 {
174  while (Running()) {
175 
176  Lock();
177  if (waitForLock) {
178  startFilters = true;
179  SetStatus(true);
180  startFilters = false;
181  }
182  int NumFilters = filterHandles.Count();
183  if (NumFilters == 0) {
184  Unlock();
185  cCondWait::SleepMs(100);
186  continue;
187  }
188  pollfd pfd[NumFilters];
189  for (cFilterHandle *fh = filterHandles.First(); fh; fh = filterHandles.Next(fh)) {
190  int i = fh->Index();
191  pfd[i].fd = fh->handle;
192  pfd[i].events = POLLIN;
193  pfd[i].revents = 0;
194  }
195  int oldStatusCount = statusCount;
196  Unlock();
197 
198  if (poll(pfd, NumFilters, (!on || waitForLock) ? 100 : 1000) > 0) {
199  for (int i = 0; i < NumFilters; i++) {
200  if (pfd[i].revents & POLLIN) {
201  cFilterHandle *fh = NULL;
202  LOCK_THREAD;
203  if (statusCount != oldStatusCount)
204  break;
205  for (fh = filterHandles.First(); fh; fh = filterHandles.Next(fh)) {
206  if (pfd[i].fd == fh->handle)
207  break;
208  }
209  if (fh) {
210  // Read section data:
211  unsigned char buf[4096]; // max. allowed size for any EIT section
212  int r = device->ReadFilter(fh->handle, buf, sizeof(buf));
213  if (flush)
214  continue; // we do the read anyway, to flush any data that might have come from a different transponder
215  if (r > 3) { // minimum number of bytes necessary to get section length
216  int len = (((buf[1] & 0x0F) << 8) | (buf[2] & 0xFF)) + 3;
217  if (len == r) {
218  // Distribute data to all attached filters:
219  int pid = fh->filterData.pid;
220  int tid = buf[0];
221  for (cFilter *fi = filters.First(); fi; fi = filters.Next(fi)) {
222  if (fi->Matches(pid, tid))
223  fi->Process(pid, tid, buf, len);
224  }
225  }
226  else
227  dsyslog("tp %d (%d/%02X) read incomplete section - len = %d, r = %d", Transponder(), fh->filterData.pid, buf[0], len, r);
228  }
229  }
230  }
231  }
232  if (flush)
234  }
235  }
236 }
int Source(void) const
Definition: channels.h:154
int Transponder(void) const
Returns the transponder frequency in MHz, plus the polarization in case of sat.
Definition: channels.c:155
static void SleepMs(int TimeoutMs)
Creates a cCondWait object and uses it to sleep for TimeoutMs milliseconds, immediately giving up the...
Definition: thread.c:73
virtual bool HasLock(int TimeoutMs=0) const
Returns true if the device has a lock on the requested transponder.
Definition: device.c:1011
int DeviceNumber(void) const
Returns the number of this device (0 ... numDevices - 1).
Definition: device.c:167
virtual void CloseFilter(int Handle)
Closes a file handle that has previously been opened by OpenFilter().
Definition: device.c:707
virtual int ReadFilter(int Handle, void *Buffer, size_t Length)
Reads data from a handle for the given filter.
Definition: device.c:702
virtual int OpenFilter(u_short Pid, u_char Tid, u_char Mask)
Opens a file handle for the given filter data.
Definition: device.c:697
bool Is(u_short Pid, u_char Tid, u_char Mask)
Definition: filter.c:103
u_short pid
Definition: filter.h:60
u_char tid
Definition: filter.h:61
u_char mask
Definition: filter.h:62
cFilterData filterData
Definition: sections.c:20
cFilterHandle(const cFilterData &FilterData)
Definition: sections.c:26
Definition: filter.h:74
cSectionHandler * sectionHandler
Definition: filter.h:77
virtual void SetStatus(bool On)
Turns this filter on or off, depending on the value of On.
Definition: filter.c:149
void Del(cListObject *Object, bool DeleteObject=true)
Definition: tools.c:2209
int Count(void) const
Definition: tools.h:627
void Add(cListObject *Object, cListObject *After=NULL)
Definition: tools.c:2177
const T * Next(const T *Object) const
< Returns the element immediately before Object in this list, or NULL if Object is the first element ...
Definition: tools.h:650
const T * First(void) const
Returns the first element in this list, or NULL if the list is empty.
Definition: tools.h:643
int Transponder(void)
Definition: sections.c:70
void SetChannel(const cChannel *Channel)
Definition: sections.c:140
cList< cFilterHandle > filterHandles
Definition: sections.h:34
int Source(void)
Definition: sections.c:65
cSectionHandlerPrivate * shp
Definition: sections.h:26
const cChannel * Channel(void)
Definition: sections.c:75
virtual ~cSectionHandler() override
Definition: sections.c:56
cTimeMs flushTimer
Definition: sections.h:32
cSectionHandler(cDevice *Device)
Definition: sections.c:42
virtual void Action(void) override
A derived cThread class must implement the code it wants to execute as a separate thread in this func...
Definition: sections.c:172
void Del(const cFilterData *FilterData)
Definition: sections.c:102
void Add(const cFilterData *FilterData)
Definition: sections.c:80
void SetStatus(bool On)
Definition: sections.c:147
bool waitForLock
Definition: sections.h:29
bool startFilters
Definition: sections.h:31
void Attach(cFilter *Filter)
Definition: sections.c:119
cList< cFilter > filters
Definition: sections.h:33
cDevice * device
Definition: sections.h:27
void Detach(cFilter *Filter)
Definition: sections.c:130
Definition: thread.h:79
void Unlock(void)
Definition: thread.h:95
void bool Start(void)
Sets the description of this thread, which will be used when logging starting or stopping of the thre...
Definition: thread.c:305
void SetDescription(const char *Description,...) __attribute__((format(printf
Definition: thread.c:268
bool Running(void)
Returns false if a derived cThread object shall leave its Action() function.
Definition: thread.h:101
void Lock(void)
Definition: thread.h:94
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:355
uint64_t Elapsed(void) const
Definition: tools.c:818
void Set(int Ms=0)
Sets the timer.
Definition: tools.c:808
#define FLUSH_TIME
Definition: sections.c:170
#define LOCK_THREAD
Definition: thread.h:167
#define dsyslog(a...)
Definition: tools.h:37