vdr  2.2.0
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 3.1 2015/01/14 11:35:53 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->CardIndex() + 1);
48  statusCount = 0;
49  on = false;
50  waitForLock = false;
52  Start();
53 }
54 
56 {
57  Cancel(3);
58  cFilter *fi;
59  while ((fi = filters.First()) != NULL)
60  Detach(fi);
61  delete shp;
62 }
63 
65 {
66  return shp->channel.Source();
67 }
68 
70 {
71  return shp->channel.Transponder();
72 }
73 
75 {
76  return &shp->channel;
77 }
78 
79 void cSectionHandler::Add(const cFilterData *FilterData)
80 {
81  Lock();
82  statusCount++;
83  cFilterHandle *fh;
84  for (fh = filterHandles.First(); fh; fh = filterHandles.Next(fh)) {
85  if (fh->filterData.Is(FilterData->pid, FilterData->tid, FilterData->mask))
86  break;
87  }
88  if (!fh) {
89  int handle = device->OpenFilter(FilterData->pid, FilterData->tid, FilterData->mask);
90  if (handle >= 0) {
91  fh = new cFilterHandle(*FilterData);
92  fh->handle = handle;
93  filterHandles.Add(fh);
94  }
95  }
96  if (fh)
97  fh->used++;
98  Unlock();
99 }
100 
101 void cSectionHandler::Del(const cFilterData *FilterData)
102 {
103  Lock();
104  statusCount++;
105  cFilterHandle *fh;
106  for (fh = filterHandles.First(); fh; fh = filterHandles.Next(fh)) {
107  if (fh->filterData.Is(FilterData->pid, FilterData->tid, FilterData->mask)) {
108  if (--fh->used <= 0) {
109  device->CloseFilter(fh->handle);
110  filterHandles.Del(fh);
111  break;
112  }
113  }
114  }
115  Unlock();
116 }
117 
119 {
120  Lock();
121  statusCount++;
122  filters.Add(Filter);
123  Filter->sectionHandler = this;
124  if (on)
125  Filter->SetStatus(true);
126  Unlock();
127 }
128 
130 {
131  Lock();
132  statusCount++;
133  Filter->SetStatus(false);
134  Filter->sectionHandler = NULL;
135  filters.Del(Filter, false);
136  Unlock();
137 }
138 
140 {
141  Lock();
142  shp->channel = Channel ? *Channel : cChannel();
143  Unlock();
144 }
145 
147 {
148  Lock();
149  if (on != On) {
150  if (!On || device->HasLock()) {
151  statusCount++;
152  for (cFilter *fi = filters.First(); fi; fi = filters.Next(fi)) {
153  fi->SetStatus(false);
154  if (On)
155  fi->SetStatus(true);
156  }
157  on = On;
158  waitForLock = false;
159  }
160  else
161  waitForLock = On;
162  }
163  Unlock();
164 }
165 
167 {
168  while (Running()) {
169 
170  Lock();
171  if (waitForLock)
172  SetStatus(true);
173  int NumFilters = filterHandles.Count();
174  pollfd pfd[NumFilters];
175  for (cFilterHandle *fh = filterHandles.First(); fh; fh = filterHandles.Next(fh)) {
176  int i = fh->Index();
177  pfd[i].fd = fh->handle;
178  pfd[i].events = POLLIN;
179  pfd[i].revents = 0;
180  }
181  int oldStatusCount = statusCount;
182  Unlock();
183 
184  if (poll(pfd, NumFilters, 1000) > 0) {
185  bool DeviceHasLock = device->HasLock();
186  if (!DeviceHasLock)
187  cCondWait::SleepMs(100);
188  for (int i = 0; i < NumFilters; i++) {
189  if (pfd[i].revents & POLLIN) {
190  cFilterHandle *fh = NULL;
191  LOCK_THREAD;
192  if (statusCount != oldStatusCount)
193  break;
194  for (fh = filterHandles.First(); fh; fh = filterHandles.Next(fh)) {
195  if (pfd[i].fd == fh->handle)
196  break;
197  }
198  if (fh) {
199  // Read section data:
200  unsigned char buf[4096]; // max. allowed size for any EIT section
201  int r = device->ReadFilter(fh->handle, buf, sizeof(buf));
202  if (!DeviceHasLock)
203  continue; // we do the read anyway, to flush any data that might have come from a different transponder
204  if (r > 3) { // minimum number of bytes necessary to get section length
205  int len = (((buf[1] & 0x0F) << 8) | (buf[2] & 0xFF)) + 3;
206  if (len == r) {
207  // Distribute data to all attached filters:
208  int pid = fh->filterData.pid;
209  int tid = buf[0];
210  for (cFilter *fi = filters.First(); fi; fi = filters.Next(fi)) {
211  if (fi->Matches(pid, tid))
212  fi->Process(pid, tid, buf, len);
213  }
214  }
215  else if (time(NULL) - lastIncompleteSection > 10) { // log them only every 10 seconds
216  dsyslog("read incomplete section - len = %d, r = %d", len, r);
217  lastIncompleteSection = time(NULL);
218  }
219  }
220  }
221  }
222  }
223  }
224  }
225 }
int Transponder(void)
Definition: sections.c:69
#define dsyslog(a...)
Definition: tools.h:36
void SetDescription(const char *Description,...) __attribute__((format(printf
Definition: thread.c:236
cList< cFilterHandle > filterHandles
Definition: sections.h:32
void Add(cListObject *Object, cListObject *After=NULL)
Definition: tools.c:2014
virtual int OpenFilter(u_short Pid, u_char Tid, u_char Mask)
Opens a file handle for the given filter data.
Definition: device.c:595
const cChannel * Channel(void)
Definition: sections.c:74
virtual int ReadFilter(int Handle, void *Buffer, size_t Length)
Reads data from a handle for the given filter.
Definition: device.c:600
virtual ~cSectionHandler()
Definition: sections.c:55
void Detach(cFilter *Filter)
Definition: sections.c:129
cDevice * device
Definition: sections.h:27
void SetStatus(bool On)
Definition: sections.c:146
u_short pid
Definition: filter.h:28
int Count(void) const
Definition: tools.h:485
void Add(const cFilterData *FilterData)
Definition: sections.c:79
int Transponder(void) const
Returns the transponder frequency in MHz, plus the polarization in case of sat.
Definition: channels.c:158
Definition: filter.h:41
void SetChannel(const cChannel *Channel)
Definition: sections.c:139
void Unlock(void)
Definition: thread.h:93
int Source(void)
Definition: sections.c:64
T * Next(const T *object) const
Definition: tools.h:495
int Source(void) const
Definition: channels.h:168
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:166
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:856
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)
Sets the description of this thread, which will be used when logging starting or stopping of the thre...
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:605
int CardIndex(void) const
Returns the card index of this device (0 ... MAXDEVICES - 1).
Definition: device.h:205
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:492
void Del(cListObject *Object, bool DeleteObject=true)
Definition: tools.c:2046
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:118
Definition: thread.h:77
cFilterData filterData
Definition: sections.c:20
#define LOCK_THREAD
Definition: thread.h:165
cFilterHandle(const cFilterData &FilterData)
Definition: sections.c:26
void Cancel(int WaitSeconds=0)
Cancels the thread by first setting &#39;running&#39; 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:109
void Del(const cFilterData *FilterData)
Definition: sections.c:101
void Lock(void)
Definition: thread.h:92