vdr
2.0.2
Main Page
Namespaces
Classes
Files
File List
File Members
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
:
20
cFilterData
filterData
;
21
int
handle
;
22
int
used
;
23
cFilterHandle
(
const
cFilterData
&FilterData);
24
};
25
26
cFilterHandle::cFilterHandle
(
const
cFilterData
&FilterData)
27
{
28
filterData
= FilterData;
29
handle
= -1;
30
used
= 0;
31
}
32
33
// --- cSectionHandlerPrivate ------------------------------------------------
34
35
class
cSectionHandlerPrivate
{
36
public
:
37
cChannel
channel
;
38
};
39
40
// --- cSectionHandler -------------------------------------------------------
41
42
cSectionHandler::cSectionHandler
(
cDevice
*Device)
43
:
cThread
(
"section handler"
, true)
44
{
45
shp
=
new
cSectionHandlerPrivate
;
46
device
= Device;
47
statusCount
= 0;
48
on
=
false
;
49
waitForLock
=
false
;
50
lastIncompleteSection
= 0;
51
Start
();
52
}
53
54
cSectionHandler::~cSectionHandler
()
55
{
56
Cancel
(3);
57
cFilter
*fi;
58
while
((fi =
filters
.
First
()) != NULL)
59
Detach
(fi);
60
delete
shp
;
61
}
62
63
int
cSectionHandler::Source
(
void
)
64
{
65
return
shp
->
channel
.
Source
();
66
}
67
68
int
cSectionHandler::Transponder
(
void
)
69
{
70
return
shp
->
channel
.
Transponder
();
71
}
72
73
const
cChannel
*
cSectionHandler::Channel
(
void
)
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
117
void
cSectionHandler::Attach
(
cFilter
*Filter)
118
{
119
Lock
();
120
statusCount
++;
121
filters
.
Add
(Filter);
122
Filter->
sectionHandler
=
this
;
123
if
(
on
)
124
Filter->
SetStatus
(
true
);
125
Unlock
();
126
}
127
128
void
cSectionHandler::Detach
(
cFilter
*Filter)
129
{
130
Lock
();
131
statusCount
++;
132
Filter->
SetStatus
(
false
);
133
Filter->
sectionHandler
= NULL;
134
filters
.
Del
(Filter,
false
);
135
Unlock
();
136
}
137
138
void
cSectionHandler::SetChannel
(
const
cChannel
*Channel)
139
{
140
Lock
();
141
shp
->
channel
= Channel ? *Channel :
cChannel
();
142
Unlock
();
143
}
144
145
void
cSectionHandler::SetStatus
(
bool
On)
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
165
void
cSectionHandler::Action
(
void
)
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
}
225
Generated by
1.8.3.1