line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Linux::DVB::DVBT::Advert::Config ;
|
2
|
|
|
|
|
|
|
|
3
|
|
|
|
|
|
|
=head1 NAME
|
4
|
|
|
|
|
|
|
|
5
|
|
|
|
|
|
|
Linux::DVB::DVBT::Advert::Config - Advert detection config file
|
6
|
|
|
|
|
|
|
|
7
|
|
|
|
|
|
|
=head1 SYNOPSIS
|
8
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
use Linux::DVB::DVBT::Advert::Config ;
|
10
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
|
12
|
|
|
|
|
|
|
=head1 DESCRIPTION
|
13
|
|
|
|
|
|
|
|
14
|
|
|
|
|
|
|
This module provides the configuration file utilities for the advert detection and removal utilities.
|
15
|
|
|
|
|
|
|
|
16
|
|
|
|
|
|
|
=head2 Settings
|
17
|
|
|
|
|
|
|
|
18
|
|
|
|
|
|
|
Settings are passed into the routines via a HASH ref. Settings also come from the default set, and
|
19
|
|
|
|
|
|
|
from any config file parameters. The order of priority for these settings is:
|
20
|
|
|
|
|
|
|
|
21
|
|
|
|
|
|
|
=over 4
|
22
|
|
|
|
|
|
|
|
23
|
|
|
|
|
|
|
Default settings I
|
24
|
|
|
|
|
|
|
|
25
|
|
|
|
|
|
|
Config file (Generic section)
|
26
|
|
|
|
|
|
|
|
27
|
|
|
|
|
|
|
Config file (Channel-specific section)
|
28
|
|
|
|
|
|
|
|
29
|
|
|
|
|
|
|
Settings used for detection
|
30
|
|
|
|
|
|
|
|
31
|
|
|
|
|
|
|
Settings HASH ref I
|
32
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
=back
|
34
|
|
|
|
|
|
|
|
35
|
|
|
|
|
|
|
Note that the "settings used for detection" only apply if the results from detection are saved in a file,
|
36
|
|
|
|
|
|
|
and then this file is read in for analysis (see L)
|
37
|
|
|
|
|
|
|
|
38
|
|
|
|
|
|
|
Settings are split between those that control the detection phase, and those that control the
|
39
|
|
|
|
|
|
|
analysis phase:
|
40
|
|
|
|
|
|
|
|
41
|
|
|
|
|
|
|
=head3 Detection Settings
|
42
|
|
|
|
|
|
|
|
43
|
|
|
|
|
|
|
Most of the detection settings (other than detection_method) can safely be left to their default values.
|
44
|
|
|
|
|
|
|
|
45
|
|
|
|
|
|
|
|
46
|
|
|
|
|
|
|
=over 4
|
47
|
|
|
|
|
|
|
|
48
|
|
|
|
|
|
|
=item B
|
49
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
Normally leave this set to the default (all methods used). Sometimes you may want to disable all advert detection (for non-commercial
|
51
|
|
|
|
|
|
|
channels), or possibly disable logo detection for channels that display a logo at all times.
|
52
|
|
|
|
|
|
|
|
53
|
|
|
|
|
|
|
This variable is actually a bitmap of flags: setting a bit enables the corresponding method. If you know what you want, you can specify
|
54
|
|
|
|
|
|
|
the variable as a decimal or hex value. It's recommended, however, to use the following symbols:
|
55
|
|
|
|
|
|
|
|
56
|
|
|
|
|
|
|
=over 4
|
57
|
|
|
|
|
|
|
|
58
|
|
|
|
|
|
|
=item I
|
59
|
|
|
|
|
|
|
|
60
|
|
|
|
|
|
|
Use this symbol on it's own to disable advert detection
|
61
|
|
|
|
|
|
|
|
62
|
|
|
|
|
|
|
=item I
|
63
|
|
|
|
|
|
|
|
64
|
|
|
|
|
|
|
Use this symbol to specify the built-in default detection method (usually means use all methods)
|
65
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
=item I
|
67
|
|
|
|
|
|
|
|
68
|
|
|
|
|
|
|
Black frame detection. This is where "black" (or dark) frames are expected to appear before and after advert
|
69
|
|
|
|
|
|
|
breaks.
|
70
|
|
|
|
|
|
|
|
71
|
|
|
|
|
|
|
=item I
|
72
|
|
|
|
|
|
|
|
73
|
|
|
|
|
|
|
Logo detection. This is where the channel logo is expected to be present during programs, but absent during adverts.
|
74
|
|
|
|
|
|
|
|
75
|
|
|
|
|
|
|
=item I |
76
|
|
|
|
|
|
|
|
77
|
|
|
|
|
|
|
Silence (audio volume) detection. Quiet (or silent) periods are expected before and after adverts.
|
78
|
|
|
|
|
|
|
|
79
|
|
|
|
|
|
|
=back
|
80
|
|
|
|
|
|
|
|
81
|
|
|
|
|
|
|
The symbols above can be combined to specify the complete detection method. Use '+' or '-' before the
|
82
|
|
|
|
|
|
|
symbol to enable or disable the method respectively. Using a '+' or '-' before the first symbol specified,
|
83
|
|
|
|
|
|
|
results in the symbols being added/subtracted from the default set. Otherwise the set specified are used
|
84
|
|
|
|
|
|
|
to fully define the methods to use.
|
85
|
|
|
|
|
|
|
|
86
|
|
|
|
|
|
|
Example: "detection_method = logo + black" means to use only black frame and logo detection.
|
87
|
|
|
|
|
|
|
|
88
|
|
|
|
|
|
|
Example: "detection_method = -logo" means to use default detection methods but disable logo detection.
|
89
|
|
|
|
|
|
|
|
90
|
|
|
|
|
|
|
Example: "detection_method = disable" means to disable advert detection.
|
91
|
|
|
|
|
|
|
|
92
|
|
|
|
|
|
|
|
93
|
|
|
|
|
|
|
=item B
|
94
|
|
|
|
|
|
|
|
95
|
|
|
|
|
|
|
Black frame detection: sets the threshold for the step difference of scene score between frames for a scene change
|
96
|
|
|
|
|
|
|
to be detected.
|
97
|
|
|
|
|
|
|
|
98
|
|
|
|
|
|
|
=item B
|
99
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
Black frame detection: scene change detection percentage above which is deemed a scene change frame
|
101
|
|
|
|
|
|
|
|
102
|
|
|
|
|
|
|
=item B
|
103
|
|
|
|
|
|
|
|
104
|
|
|
|
|
|
|
Black frame detection: maximum pixel value for the pixel to be determined as "black"
|
105
|
|
|
|
|
|
|
|
106
|
|
|
|
|
|
|
=item B
|
107
|
|
|
|
|
|
|
|
108
|
|
|
|
|
|
|
Black frame detection: maximum brightness percentage under which is treated as black
|
109
|
|
|
|
|
|
|
|
110
|
|
|
|
|
|
|
=item B
|
111
|
|
|
|
|
|
|
|
112
|
|
|
|
|
|
|
Black frame detection: step difference of the brightness score between frames used to detect a black frame
|
113
|
|
|
|
|
|
|
|
114
|
|
|
|
|
|
|
=item B
|
115
|
|
|
|
|
|
|
|
116
|
|
|
|
|
|
|
Black frame detection: percentage of frame to use for black frame detection (for example, setting this to 90% results
|
117
|
|
|
|
|
|
|
in 5% of the edges around the frame to be ignored)
|
118
|
|
|
|
|
|
|
|
119
|
|
|
|
|
|
|
=item B
|
120
|
|
|
|
|
|
|
|
121
|
|
|
|
|
|
|
Black frame detection: pixel value used for brightness detection
|
122
|
|
|
|
|
|
|
|
123
|
|
|
|
|
|
|
=item B
|
124
|
|
|
|
|
|
|
|
125
|
|
|
|
|
|
|
Black frame detection: noise level used for black frame uniformity detection
|
126
|
|
|
|
|
|
|
|
127
|
|
|
|
|
|
|
|
128
|
|
|
|
|
|
|
|
129
|
|
|
|
|
|
|
=item B
|
130
|
|
|
|
|
|
|
|
131
|
|
|
|
|
|
|
Logo detection: Step size used for moving between pixels in all logo detection functions. For example, setting this to 2 skips
|
132
|
|
|
|
|
|
|
every other pixel, resulting in halving the amount of dtaa to process.
|
133
|
|
|
|
|
|
|
|
134
|
|
|
|
|
|
|
=item B
|
135
|
|
|
|
|
|
|
|
136
|
|
|
|
|
|
|
Logo detection: Once a logo has been possibly detected, this is a check to ensure that the area of the screen used by the logo
|
137
|
|
|
|
|
|
|
is no greater than this value. Otherwise the detected region cannot be a valid logo and is discarded.
|
138
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
=item B
|
140
|
|
|
|
|
|
|
|
141
|
|
|
|
|
|
|
Logo detection: Number of image frames stored in a rolling detection buffer. The number of frames skipped between each stored frame is set by L
|
142
|
|
|
|
|
|
|
|
143
|
|
|
|
|
|
|
=item B
|
144
|
|
|
|
|
|
|
|
145
|
|
|
|
|
|
|
Logo detection: Number of frames to skip between used frames. This creates a bigger discrepancy between images and makes the logo
|
146
|
|
|
|
|
|
|
area easier to detect.
|
147
|
|
|
|
|
|
|
|
148
|
|
|
|
|
|
|
=item B
|
149
|
|
|
|
|
|
|
|
150
|
|
|
|
|
|
|
Logo detection: level used to decided whether this is a logo edge
|
151
|
|
|
|
|
|
|
|
152
|
|
|
|
|
|
|
=item B
|
153
|
|
|
|
|
|
|
|
154
|
|
|
|
|
|
|
Logo detection: The logo detection score is averaged over this number of frames.
|
155
|
|
|
|
|
|
|
|
156
|
|
|
|
|
|
|
=item B
|
157
|
|
|
|
|
|
|
|
158
|
|
|
|
|
|
|
Logo detection: maximum period (in frames) to use for detecting a logo. If a logo has not been found when we reach this number of frames
|
159
|
|
|
|
|
|
|
from the start of the video, then logo detection is cancelled.
|
160
|
|
|
|
|
|
|
|
161
|
|
|
|
|
|
|
=item B
|
162
|
|
|
|
|
|
|
|
163
|
|
|
|
|
|
|
Logo detection: perecntage of total frame to use for logo detection
|
164
|
|
|
|
|
|
|
|
165
|
|
|
|
|
|
|
=item B
|
166
|
|
|
|
|
|
|
|
167
|
|
|
|
|
|
|
Logo detection: number of times a logo result is re-checked. Once a logo area is detected, the process is re-started this many times
|
168
|
|
|
|
|
|
|
to ensure we don't have a false detection.
|
169
|
|
|
|
|
|
|
|
170
|
|
|
|
|
|
|
=item B
|
171
|
|
|
|
|
|
|
|
172
|
|
|
|
|
|
|
Logo detection: the logo detection score % must be above this value before a frame is flagged as containing a logo.
|
173
|
|
|
|
|
|
|
|
174
|
|
|
|
|
|
|
=item B
|
175
|
|
|
|
|
|
|
|
176
|
|
|
|
|
|
|
Logo detection: number of pixels to use in logo edge detection
|
177
|
|
|
|
|
|
|
|
178
|
|
|
|
|
|
|
|
179
|
|
|
|
|
|
|
=item B
|
180
|
|
|
|
|
|
|
|
181
|
|
|
|
|
|
|
Silence detection: adds "fuzziness" to detection of silence frames
|
182
|
|
|
|
|
|
|
|
183
|
|
|
|
|
|
|
=back
|
184
|
|
|
|
|
|
|
|
185
|
|
|
|
|
|
|
|
186
|
|
|
|
|
|
|
=head3 Analysis Settings
|
187
|
|
|
|
|
|
|
|
188
|
|
|
|
|
|
|
The analysis settings consist of a global set of settings that are used in all cases. Also, each detection mode (black frame, logo etc)
|
189
|
|
|
|
|
|
|
has it's own set of settings that may be set to over-ride the global set. In the same manner as the detection settings, each set if prefixed
|
190
|
|
|
|
|
|
|
by it's own namespace (e.g. for black frame detection use 'frame.' etc).
|
191
|
|
|
|
|
|
|
|
192
|
|
|
|
|
|
|
=over 4
|
193
|
|
|
|
|
|
|
|
194
|
|
|
|
|
|
|
=item B
|
195
|
|
|
|
|
|
|
|
196
|
|
|
|
|
|
|
The maximum length of a single advert (in frames). Multiple adverts may be joined to form the total advert/commercial break between
|
197
|
|
|
|
|
|
|
program sections.
|
198
|
|
|
|
|
|
|
|
199
|
|
|
|
|
|
|
=item B
|
200
|
|
|
|
|
|
|
|
201
|
|
|
|
|
|
|
The minimum length of a single advert (in frames).
|
202
|
|
|
|
|
|
|
|
203
|
|
|
|
|
|
|
=item B
|
204
|
|
|
|
|
|
|
|
205
|
|
|
|
|
|
|
The minimum length (in frames) of a section of program.
|
206
|
|
|
|
|
|
|
|
207
|
|
|
|
|
|
|
=item B
|
208
|
|
|
|
|
|
|
|
209
|
|
|
|
|
|
|
(UNUSED) Expected amount of padding (in frames) before the start of a program recording.
|
210
|
|
|
|
|
|
|
|
211
|
|
|
|
|
|
|
=item B
|
212
|
|
|
|
|
|
|
|
213
|
|
|
|
|
|
|
(UNUSED) Expected amount of padding (in frames) at the start of a program recording.
|
214
|
|
|
|
|
|
|
|
215
|
|
|
|
|
|
|
=item B
|
216
|
|
|
|
|
|
|
|
217
|
|
|
|
|
|
|
Minimum number of frames to be contracted into a block.
|
218
|
|
|
|
|
|
|
|
219
|
|
|
|
|
|
|
=item B
|
220
|
|
|
|
|
|
|
|
221
|
|
|
|
|
|
|
fuzziness window when contracting frames into a block
|
222
|
|
|
|
|
|
|
|
223
|
|
|
|
|
|
|
=item B
|
224
|
|
|
|
|
|
|
|
225
|
|
|
|
|
|
|
widest gap (no valid frames) over which to span when contracting frames into a block
|
226
|
|
|
|
|
|
|
|
227
|
|
|
|
|
|
|
=item B
|
228
|
|
|
|
|
|
|
|
229
|
|
|
|
|
|
|
window (in frames) in which to reduce the end of the program to the nearest gap
|
230
|
|
|
|
|
|
|
|
231
|
|
|
|
|
|
|
=item B
|
232
|
|
|
|
|
|
|
|
233
|
|
|
|
|
|
|
frame gap used for reducing program end point
|
234
|
|
|
|
|
|
|
|
235
|
|
|
|
|
|
|
|
236
|
|
|
|
|
|
|
=back
|
237
|
|
|
|
|
|
|
|
238
|
|
|
|
|
|
|
Black frame settings (see above to descriptions):
|
239
|
|
|
|
|
|
|
|
240
|
|
|
|
|
|
|
=over 4
|
241
|
|
|
|
|
|
|
|
242
|
|
|
|
|
|
|
=item B
|
243
|
|
|
|
|
|
|
|
244
|
|
|
|
|
|
|
=item B
|
245
|
|
|
|
|
|
|
|
246
|
|
|
|
|
|
|
=item B
|
247
|
|
|
|
|
|
|
|
248
|
|
|
|
|
|
|
=item B
|
249
|
|
|
|
|
|
|
|
250
|
|
|
|
|
|
|
=item B
|
251
|
|
|
|
|
|
|
|
252
|
|
|
|
|
|
|
=item B
|
253
|
|
|
|
|
|
|
|
254
|
|
|
|
|
|
|
=item B
|
255
|
|
|
|
|
|
|
|
256
|
|
|
|
|
|
|
=item B
|
257
|
|
|
|
|
|
|
|
258
|
|
|
|
|
|
|
=item B
|
259
|
|
|
|
|
|
|
|
260
|
|
|
|
|
|
|
=item B
|
261
|
|
|
|
|
|
|
|
262
|
|
|
|
|
|
|
=item B
|
263
|
|
|
|
|
|
|
|
264
|
|
|
|
|
|
|
=item B
|
265
|
|
|
|
|
|
|
|
266
|
|
|
|
|
|
|
=back
|
267
|
|
|
|
|
|
|
|
268
|
|
|
|
|
|
|
Logo frame settings (see above to descriptions):
|
269
|
|
|
|
|
|
|
|
270
|
|
|
|
|
|
|
=over 4
|
271
|
|
|
|
|
|
|
|
272
|
|
|
|
|
|
|
=item B
|
273
|
|
|
|
|
|
|
|
274
|
|
|
|
|
|
|
=item B
|
275
|
|
|
|
|
|
|
|
276
|
|
|
|
|
|
|
=item B
|
277
|
|
|
|
|
|
|
|
278
|
|
|
|
|
|
|
=item B
|
279
|
|
|
|
|
|
|
|
280
|
|
|
|
|
|
|
=item B
|
281
|
|
|
|
|
|
|
|
282
|
|
|
|
|
|
|
=item B
|
283
|
|
|
|
|
|
|
|
284
|
|
|
|
|
|
|
=item B
|
285
|
|
|
|
|
|
|
|
286
|
|
|
|
|
|
|
=item B
|
287
|
|
|
|
|
|
|
|
288
|
|
|
|
|
|
|
=item B
|
289
|
|
|
|
|
|
|
|
290
|
|
|
|
|
|
|
=item B
|
291
|
|
|
|
|
|
|
|
292
|
|
|
|
|
|
|
=item B
|
293
|
|
|
|
|
|
|
|
294
|
|
|
|
|
|
|
=item B
|
295
|
|
|
|
|
|
|
|
296
|
|
|
|
|
|
|
=item B
|
297
|
|
|
|
|
|
|
|
298
|
|
|
|
|
|
|
=item B
|
299
|
|
|
|
|
|
|
|
300
|
|
|
|
|
|
|
=back
|
301
|
|
|
|
|
|
|
|
302
|
|
|
|
|
|
|
Silence frame settings (see above to descriptions):
|
303
|
|
|
|
|
|
|
|
304
|
|
|
|
|
|
|
=over 4
|
305
|
|
|
|
|
|
|
|
306
|
|
|
|
|
|
|
=item B
|
307
|
|
|
|
|
|
|
|
308
|
|
|
|
|
|
|
=item B
|
309
|
|
|
|
|
|
|
|
310
|
|
|
|
|
|
|
=item B
|
311
|
|
|
|
|
|
|
|
312
|
|
|
|
|
|
|
=item B
|
313
|
|
|
|
|
|
|
|
314
|
|
|
|
|
|
|
=item B
|
315
|
|
|
|
|
|
|
|
316
|
|
|
|
|
|
|
=item B
|
317
|
|
|
|
|
|
|
|
318
|
|
|
|
|
|
|
=item B
|
319
|
|
|
|
|
|
|
|
320
|
|
|
|
|
|
|
=item B
|
321
|
|
|
|
|
|
|
|
322
|
|
|
|
|
|
|
=item B
|
323
|
|
|
|
|
|
|
|
324
|
|
|
|
|
|
|
=item B
|
325
|
|
|
|
|
|
|
|
326
|
|
|
|
|
|
|
=item B
|
327
|
|
|
|
|
|
|
|
328
|
|
|
|
|
|
|
=item B
|
329
|
|
|
|
|
|
|
|
330
|
|
|
|
|
|
|
=back
|
331
|
|
|
|
|
|
|
|
332
|
|
|
|
|
|
|
=head2 Config File
|
333
|
|
|
|
|
|
|
|
334
|
|
|
|
|
|
|
The configuration file is of the form:
|
335
|
|
|
|
|
|
|
|
336
|
|
|
|
|
|
|
# global settings
|
337
|
|
|
|
|
|
|
detection_method = 15
|
338
|
|
|
|
|
|
|
frame.max_black = 48
|
339
|
|
|
|
|
|
|
frame.window_percent = 95
|
340
|
|
|
|
|
|
|
frame.max_brightness = 60
|
341
|
|
|
|
|
|
|
frame.test_brightness = 40
|
342
|
|
|
|
|
|
|
frame.brightness_jump = 200
|
343
|
|
|
|
|
|
|
frame.schange_cutlevel = 85
|
344
|
|
|
|
|
|
|
frame.schange_jump = 30
|
345
|
|
|
|
|
|
|
frame.noise_level = 5
|
346
|
|
|
|
|
|
|
logo.window_percent = 95
|
347
|
|
|
|
|
|
|
logo.logo_window = 50
|
348
|
|
|
|
|
|
|
logo.logo_edge_radius = 2
|
349
|
|
|
|
|
|
|
logo.logo_edge_step = 1
|
350
|
|
|
|
|
|
|
logo.logo_edge_threshold = 5
|
351
|
|
|
|
|
|
|
logo.logo_checking_period = 30000
|
352
|
|
|
|
|
|
|
logo.logo_skip_frames = 25
|
353
|
|
|
|
|
|
|
logo.logo_num_checks = 5
|
354
|
|
|
|
|
|
|
logo.logo_ok_percent = 80
|
355
|
|
|
|
|
|
|
logo.logo_max_percentage_of_screen = 10
|
356
|
|
|
|
|
|
|
logo.logo_ave_points = 250
|
357
|
|
|
|
|
|
|
audio.scale = 1
|
358
|
|
|
|
|
|
|
audio.silence_threshold = -80
|
359
|
|
|
|
|
|
|
|
360
|
|
|
|
|
|
|
# Channel-specific settings
|
361
|
|
|
|
|
|
|
[Dave]
|
362
|
|
|
|
|
|
|
logo.logo_skip_frames = 30
|
363
|
|
|
|
|
|
|
logo.logo_num_checks = 2
|
364
|
|
|
|
|
|
|
logo.logo_ok_percent = 85
|
365
|
|
|
|
|
|
|
|
366
|
|
|
|
|
|
|
|
367
|
|
|
|
|
|
|
=head2 Config File Search Path
|
368
|
|
|
|
|
|
|
|
369
|
|
|
|
|
|
|
Some of the functions (for example L) accept an optional search path. If this is specified then the same
|
370
|
|
|
|
|
|
|
search path will be used from that point on (until a different search path is specified).
|
371
|
|
|
|
|
|
|
|
372
|
|
|
|
|
|
|
By default, the search path is set to attempt to match with L on those platforms that support that path; otherwise
|
373
|
|
|
|
|
|
|
the user's home directory is used.
|
374
|
|
|
|
|
|
|
|
375
|
|
|
|
|
|
|
Setting the search path allows the module to attempt to read/write the configuration file from multiple directories. This allows there to
|
376
|
|
|
|
|
|
|
be a common global file used by all users, but each user may then create their own configuration file to over ride the global one however
|
377
|
|
|
|
|
|
|
they choose.
|
378
|
|
|
|
|
|
|
|
379
|
|
|
|
|
|
|
The format for the search path is an ARRAY ref list of directories, for example:
|
380
|
|
|
|
|
|
|
|
381
|
|
|
|
|
|
|
[ '/etc/dvb', '~/.tv' ]
|
382
|
|
|
|
|
|
|
|
383
|
|
|
|
|
|
|
or
|
384
|
|
|
|
|
|
|
|
385
|
|
|
|
|
|
|
[ 'c:\tv', 'd:\profiles\user\tv' ]
|
386
|
|
|
|
|
|
|
|
387
|
|
|
|
|
|
|
|
388
|
|
|
|
|
|
|
=cut
|
389
|
|
|
|
|
|
|
|
390
|
|
|
|
|
|
|
|
391
|
12
|
|
|
12
|
|
67
|
use strict ;
|
|
12
|
|
|
|
|
23
|
|
|
12
|
|
|
|
|
443
|
|
392
|
12
|
|
|
12
|
|
62
|
use Carp ;
|
|
12
|
|
|
|
|
21
|
|
|
12
|
|
|
|
|
654
|
|
393
|
|
|
|
|
|
|
|
394
|
12
|
|
|
12
|
|
65
|
use File::Spec ;
|
|
12
|
|
|
|
|
18
|
|
|
12
|
|
|
|
|
248
|
|
395
|
12
|
|
|
12
|
|
1619
|
use Data::Dumper ;
|
|
12
|
|
|
|
|
11635
|
|
|
12
|
|
|
|
|
687
|
|
396
|
|
|
|
|
|
|
|
397
|
12
|
|
|
12
|
|
11752
|
use Linux::DVB::DVBT::Advert::Constants ;
|
|
12
|
|
|
|
|
28
|
|
|
12
|
|
|
|
|
11530
|
|
398
|
|
|
|
|
|
|
|
399
|
|
|
|
|
|
|
our $VERSION = '1.03' ;
|
400
|
|
|
|
|
|
|
our $DEBUG = 0 ;
|
401
|
|
|
|
|
|
|
|
402
|
|
|
|
|
|
|
our $DEFAULT_CONFIG_PATH ;
|
403
|
|
|
|
|
|
|
our $FILENAME = 'dvb-adv' ;
|
404
|
|
|
|
|
|
|
|
405
|
|
|
|
|
|
|
my %NUMERALS = (
|
406
|
|
|
|
|
|
|
'one' => 1,
|
407
|
|
|
|
|
|
|
'two' => 2,
|
408
|
|
|
|
|
|
|
'three' => 3,
|
409
|
|
|
|
|
|
|
'four' => 4,
|
410
|
|
|
|
|
|
|
'five' => 5,
|
411
|
|
|
|
|
|
|
'six' => 6,
|
412
|
|
|
|
|
|
|
'seven' => 7,
|
413
|
|
|
|
|
|
|
'eight' => 8,
|
414
|
|
|
|
|
|
|
'nine' => 9,
|
415
|
|
|
|
|
|
|
) ;
|
416
|
|
|
|
|
|
|
|
417
|
|
|
|
|
|
|
|
418
|
|
|
|
|
|
|
#============================================================================================
|
419
|
|
|
|
|
|
|
our $ADVERT_GLOBAL_SECTION = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA__GLOBAL__" ;
|
420
|
|
|
|
|
|
|
our $METHOD_VAR = "detection_method" ;
|
421
|
|
|
|
|
|
|
our $METHOD_DISABLE = "disable" ;
|
422
|
|
|
|
|
|
|
our $METHOD_DISABLE_REGEXP = "none|$METHOD_DISABLE" ;
|
423
|
|
|
|
|
|
|
|
424
|
|
|
|
|
|
|
my %SETTINGS_COMMENTS = (
|
425
|
|
|
|
|
|
|
|
426
|
|
|
|
|
|
|
'max_advert' => 'maximum length of a single advert (in frames)',
|
427
|
|
|
|
|
|
|
'min_advert' => 'minimum length of advert period (cut period) excludes prog change (in frames)',
|
428
|
|
|
|
|
|
|
'min_program' => 'minimum length of a program (in frames)',
|
429
|
|
|
|
|
|
|
'start_pad' => 'padding at start of recording (in frames)',
|
430
|
|
|
|
|
|
|
'end_pad' => 'padding at end of recording (in frames)',
|
431
|
|
|
|
|
|
|
'min_frames' => 'minimum number of frames to be contracted into a block',
|
432
|
|
|
|
|
|
|
'frame_window' => 'fuzziness window when contracting frames into a block',
|
433
|
|
|
|
|
|
|
'max_gap' => 'widest gap (no valid frames) over which to span when contracting frames into a block',
|
434
|
|
|
|
|
|
|
'reduce_end' => 'window (in frames) in which to reduce the end of the program to the nearest gap',
|
435
|
|
|
|
|
|
|
'reduce_min_gap' => 'frame gap used for reducing program end point',
|
436
|
|
|
|
|
|
|
'detection_method' => 'advert detection method specified numerically or in symbols e.g. logo+black',
|
437
|
|
|
|
|
|
|
|
438
|
|
|
|
|
|
|
'logo.logo_edge_step' => 'pixel step size for logo detection',
|
439
|
|
|
|
|
|
|
'logo.logo_window' => 'number of frames stored in the logo detection buffer',
|
440
|
|
|
|
|
|
|
'logo.logo_max_percentage_of_screen' => 'maximum size of a logo (anything larger is discarded)',
|
441
|
|
|
|
|
|
|
'logo.logo_skip_frames' => 'number of frames to skip between logo detection',
|
442
|
|
|
|
|
|
|
'logo.logo_edge_threshold' => 'level used to decided whether this is a logo edge',
|
443
|
|
|
|
|
|
|
'logo.logo_ave_points' => 'logo averaging buffer size',
|
444
|
|
|
|
|
|
|
'logo.logo_checking_period' => 'maximum period (in frames) to use for detecting a logo',
|
445
|
|
|
|
|
|
|
'logo.window_percent' => 'percentage of frame to use for detection',
|
446
|
|
|
|
|
|
|
'logo.logo_num_checks' => 'number of logo re-checks',
|
447
|
|
|
|
|
|
|
'logo.logo_ok_percent' => 'percentage over which logo detection is deemed a match',
|
448
|
|
|
|
|
|
|
'logo.logo_edge_radius' => 'number of pixels to use in logo edge detection',
|
449
|
|
|
|
|
|
|
'logo.logo_rise_threshold' => 'percentage over which logo detection is deemed a match : going from non-logo to logo frames',
|
450
|
|
|
|
|
|
|
'logo.logo_fall_threshold' => 'percentage over which logo detection is deemed a match : going from logo to non-logo frames',
|
451
|
|
|
|
|
|
|
|
452
|
|
|
|
|
|
|
'frame.schange_jump' => 'sceen change detection level step',
|
453
|
|
|
|
|
|
|
'frame.schange_cutlevel' => 'scene change detection percentage above which is deemed a scene change frame',
|
454
|
|
|
|
|
|
|
'frame.max_black' => 'maximum pixel value under which pixel is treated as black',
|
455
|
|
|
|
|
|
|
'frame.max_brightness' => 'maximum brightness percentage under which is treated as black',
|
456
|
|
|
|
|
|
|
'frame.brightness_jump' => 'difference level between frames used to detect a black frame',
|
457
|
|
|
|
|
|
|
'frame.window_percent' => 'percentage of frame to use for detection',
|
458
|
|
|
|
|
|
|
'frame.test_brightness' => 'pixel value used for brightness detection',
|
459
|
|
|
|
|
|
|
'frame.noise_level' => 'noise level used for black frame uniformity detection',
|
460
|
|
|
|
|
|
|
|
461
|
|
|
|
|
|
|
'audio.silence_window' => 'adds "fuzziness" to detection of silence frames',
|
462
|
|
|
|
|
|
|
|
463
|
|
|
|
|
|
|
) ;
|
464
|
|
|
|
|
|
|
|
465
|
|
|
|
|
|
|
|
466
|
|
|
|
|
|
|
my @SETTINGS_REGIONS = (
|
467
|
|
|
|
|
|
|
'global', 'frame', 'logo', 'audio',
|
468
|
|
|
|
|
|
|
) ;
|
469
|
|
|
|
|
|
|
my %SETTINGS_TEMPLATE = (
|
470
|
|
|
|
|
|
|
|
471
|
|
|
|
|
|
|
'global' => [
|
472
|
|
|
|
|
|
|
'# ------------------------------------------------',
|
473
|
|
|
|
|
|
|
'# Global settings.',
|
474
|
|
|
|
|
|
|
'#',
|
475
|
|
|
|
|
|
|
'# Any settings here propagate down any unset ',
|
476
|
|
|
|
|
|
|
'# detection-specific settings',
|
477
|
|
|
|
|
|
|
'# ------------------------------------------------',
|
478
|
|
|
|
|
|
|
'',
|
479
|
|
|
|
|
|
|
'# -- Settings used by detection algorithms (XS) --',
|
480
|
|
|
|
|
|
|
'',
|
481
|
|
|
|
|
|
|
'detection_method',
|
482
|
|
|
|
|
|
|
'',
|
483
|
|
|
|
|
|
|
'# -- Settings used by analysis algorithms (Perl) --',
|
484
|
|
|
|
|
|
|
'',
|
485
|
|
|
|
|
|
|
'max_advert',
|
486
|
|
|
|
|
|
|
'min_advert',
|
487
|
|
|
|
|
|
|
'min_program',
|
488
|
|
|
|
|
|
|
'start_pad',
|
489
|
|
|
|
|
|
|
'end_pad',
|
490
|
|
|
|
|
|
|
'min_frames',
|
491
|
|
|
|
|
|
|
'frame_window',
|
492
|
|
|
|
|
|
|
'max_gap',
|
493
|
|
|
|
|
|
|
'reduce_end',
|
494
|
|
|
|
|
|
|
'reduce_min_gap',
|
495
|
|
|
|
|
|
|
'increase_start',
|
496
|
|
|
|
|
|
|
'increase_min_gap',
|
497
|
|
|
|
|
|
|
'',
|
498
|
|
|
|
|
|
|
],
|
499
|
|
|
|
|
|
|
|
500
|
|
|
|
|
|
|
'frame' => [
|
501
|
|
|
|
|
|
|
'# ------------------------------------------------',
|
502
|
|
|
|
|
|
|
'# Frame detection specific settings.',
|
503
|
|
|
|
|
|
|
'# ------------------------------------------------',
|
504
|
|
|
|
|
|
|
'',
|
505
|
|
|
|
|
|
|
'# -- Settings used by detection algorithms (XS) --',
|
506
|
|
|
|
|
|
|
'',
|
507
|
|
|
|
|
|
|
'frame.schange_jump',
|
508
|
|
|
|
|
|
|
'frame.schange_cutlevel',
|
509
|
|
|
|
|
|
|
'frame.max_black',
|
510
|
|
|
|
|
|
|
'frame.max_brightness',
|
511
|
|
|
|
|
|
|
'frame.brightness_jump',
|
512
|
|
|
|
|
|
|
'frame.window_percent',
|
513
|
|
|
|
|
|
|
'frame.test_brightness',
|
514
|
|
|
|
|
|
|
'frame.noise_level',
|
515
|
|
|
|
|
|
|
'',
|
516
|
|
|
|
|
|
|
'# -- Settings used by analysis algorithms (Perl) --',
|
517
|
|
|
|
|
|
|
'',
|
518
|
|
|
|
|
|
|
'frame.max_advert',
|
519
|
|
|
|
|
|
|
'frame.min_advert',
|
520
|
|
|
|
|
|
|
'frame.min_program',
|
521
|
|
|
|
|
|
|
'frame.start_pad',
|
522
|
|
|
|
|
|
|
'frame.end_pad',
|
523
|
|
|
|
|
|
|
'frame.min_frames',
|
524
|
|
|
|
|
|
|
'frame.frame_window',
|
525
|
|
|
|
|
|
|
'frame.max_gap',
|
526
|
|
|
|
|
|
|
'frame.reduce_end',
|
527
|
|
|
|
|
|
|
'frame.reduce_min_gap',
|
528
|
|
|
|
|
|
|
'frame.increase_start',
|
529
|
|
|
|
|
|
|
'frame.increase_min_gap',
|
530
|
|
|
|
|
|
|
'',
|
531
|
|
|
|
|
|
|
],
|
532
|
|
|
|
|
|
|
|
533
|
|
|
|
|
|
|
'logo' => [
|
534
|
|
|
|
|
|
|
'# ------------------------------------------------',
|
535
|
|
|
|
|
|
|
'# Logo detection specific settings.',
|
536
|
|
|
|
|
|
|
'# ------------------------------------------------',
|
537
|
|
|
|
|
|
|
'',
|
538
|
|
|
|
|
|
|
'# -- Settings used by detection algorithms (XS) --',
|
539
|
|
|
|
|
|
|
'',
|
540
|
|
|
|
|
|
|
'logo.logo_edge_step',
|
541
|
|
|
|
|
|
|
'logo.logo_max_percentage_of_screen',
|
542
|
|
|
|
|
|
|
'logo.logo_window',
|
543
|
|
|
|
|
|
|
'logo.logo_skip_frames',
|
544
|
|
|
|
|
|
|
'logo.logo_edge_threshold',
|
545
|
|
|
|
|
|
|
'logo.logo_ave_points',
|
546
|
|
|
|
|
|
|
'logo.logo_checking_period',
|
547
|
|
|
|
|
|
|
'logo.window_percent',
|
548
|
|
|
|
|
|
|
'logo.logo_num_checks',
|
549
|
|
|
|
|
|
|
'logo.logo_ok_percent',
|
550
|
|
|
|
|
|
|
'logo.logo_edge_radius',
|
551
|
|
|
|
|
|
|
'',
|
552
|
|
|
|
|
|
|
'# -- Settings used by analysis algorithms (Perl) --',
|
553
|
|
|
|
|
|
|
'',
|
554
|
|
|
|
|
|
|
'logo.max_advert',
|
555
|
|
|
|
|
|
|
'logo.min_advert',
|
556
|
|
|
|
|
|
|
'logo.min_program',
|
557
|
|
|
|
|
|
|
'logo.start_pad',
|
558
|
|
|
|
|
|
|
'logo.end_pad',
|
559
|
|
|
|
|
|
|
'logo.min_frames',
|
560
|
|
|
|
|
|
|
'logo.frame_window',
|
561
|
|
|
|
|
|
|
'logo.max_gap',
|
562
|
|
|
|
|
|
|
'logo.reduce_end',
|
563
|
|
|
|
|
|
|
'logo.reduce_min_gap',
|
564
|
|
|
|
|
|
|
'logo.increase_start',
|
565
|
|
|
|
|
|
|
'logo.increase_min_gap',
|
566
|
|
|
|
|
|
|
'logo.logo_rise_threshold',
|
567
|
|
|
|
|
|
|
'logo.logo_fall_threshold',
|
568
|
|
|
|
|
|
|
'',
|
569
|
|
|
|
|
|
|
],
|
570
|
|
|
|
|
|
|
|
571
|
|
|
|
|
|
|
'audio' => [
|
572
|
|
|
|
|
|
|
'# ------------------------------------------------',
|
573
|
|
|
|
|
|
|
'# Audio detection specific settings.',
|
574
|
|
|
|
|
|
|
'# ------------------------------------------------',
|
575
|
|
|
|
|
|
|
'',
|
576
|
|
|
|
|
|
|
'# -- Settings used by detection algorithms (XS) --',
|
577
|
|
|
|
|
|
|
'',
|
578
|
|
|
|
|
|
|
'audio.silence_window',
|
579
|
|
|
|
|
|
|
'',
|
580
|
|
|
|
|
|
|
'# -- Settings used by analysis algorithms (Perl) --',
|
581
|
|
|
|
|
|
|
'',
|
582
|
|
|
|
|
|
|
'audio.max_advert',
|
583
|
|
|
|
|
|
|
'audio.min_advert',
|
584
|
|
|
|
|
|
|
'audio.min_program',
|
585
|
|
|
|
|
|
|
'audio.start_pad',
|
586
|
|
|
|
|
|
|
'audio.end_pad',
|
587
|
|
|
|
|
|
|
'audio.min_frames',
|
588
|
|
|
|
|
|
|
'audio.frame_window',
|
589
|
|
|
|
|
|
|
'audio.max_gap',
|
590
|
|
|
|
|
|
|
'audio.reduce_end',
|
591
|
|
|
|
|
|
|
'audio.reduce_min_gap',
|
592
|
|
|
|
|
|
|
'audio.increase_start',
|
593
|
|
|
|
|
|
|
'audio.increase_min_gap',
|
594
|
|
|
|
|
|
|
'',
|
595
|
|
|
|
|
|
|
],
|
596
|
|
|
|
|
|
|
) ;
|
597
|
|
|
|
|
|
|
|
598
|
|
|
|
|
|
|
|
599
|
|
|
|
|
|
|
#============================================================================================
|
600
|
|
|
|
|
|
|
BEGIN {
|
601
|
|
|
|
|
|
|
|
602
|
|
|
|
|
|
|
## Default for Linux::DVB::DVBT
|
603
|
12
|
|
|
12
|
|
52
|
$DEFAULT_CONFIG_PATH = [ qw(/etc/dvb ~/.tv) ] ;
|
604
|
|
|
|
|
|
|
|
605
|
12
|
|
|
|
|
23
|
my $home ;
|
606
|
12
|
50
|
33
|
|
|
174
|
if ( exists $ENV{HOME} and defined $ENV{HOME} )
|
607
|
|
|
|
|
|
|
{
|
608
|
12
|
|
|
|
|
49
|
$home = $ENV{HOME};
|
609
|
|
|
|
|
|
|
}
|
610
|
|
|
|
|
|
|
|
611
|
|
|
|
|
|
|
## Check OS
|
612
|
12
|
50
|
33
|
|
|
63364
|
if ( $^O eq 'MSWin32' )
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
613
|
|
|
|
|
|
|
{
|
614
|
|
|
|
|
|
|
# All versions of Windows
|
615
|
|
|
|
|
|
|
|
616
|
|
|
|
|
|
|
# Do we have a user profile?
|
617
|
0
|
0
|
0
|
|
|
0
|
if ( !$home && exists $ENV{USERPROFILE} && $ENV{USERPROFILE} )
|
|
|
|
0
|
|
|
|
|
618
|
|
|
|
|
|
|
{
|
619
|
0
|
|
|
|
|
0
|
$home = $ENV{USERPROFILE};
|
620
|
|
|
|
|
|
|
}
|
621
|
|
|
|
|
|
|
|
622
|
|
|
|
|
|
|
# Some Windows use something like $ENV{HOME}
|
623
|
0
|
0
|
0
|
|
|
0
|
if ( !$home && exists $ENV{HOMEDRIVE} && exists $ENV{HOMEPATH} && $ENV{HOMEDRIVE} && $ENV{HOMEPATH} )
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
624
|
|
|
|
|
|
|
{
|
625
|
0
|
|
|
|
|
0
|
$home = File::Spec->catpath($ENV{HOMEDRIVE}, $ENV{HOMEPATH}, '');
|
626
|
|
|
|
|
|
|
}
|
627
|
|
|
|
|
|
|
|
628
|
0
|
|
|
|
|
0
|
$DEFAULT_CONFIG_PATH = [] ;
|
629
|
0
|
0
|
0
|
|
|
0
|
if ($home && -d $home)
|
630
|
|
|
|
|
|
|
{
|
631
|
0
|
|
|
|
|
0
|
$home =~ s%\\%/%g ;
|
632
|
0
|
|
|
|
|
0
|
push @$DEFAULT_CONFIG_PATH, "$home/tv" ;
|
633
|
|
|
|
|
|
|
}
|
634
|
|
|
|
|
|
|
|
635
|
|
|
|
|
|
|
# add current dir
|
636
|
0
|
|
|
|
|
0
|
push @$DEFAULT_CONFIG_PATH, "." ;
|
637
|
|
|
|
|
|
|
}
|
638
|
|
|
|
|
|
|
elsif ( $^O eq 'darwin')
|
639
|
|
|
|
|
|
|
{
|
640
|
0
|
0
|
|
|
|
0
|
if (!$home)
|
641
|
|
|
|
|
|
|
{
|
642
|
0
|
|
|
|
|
0
|
$home = (getpwuid($<))[7];
|
643
|
|
|
|
|
|
|
}
|
644
|
|
|
|
|
|
|
|
645
|
0
|
|
|
|
|
0
|
$DEFAULT_CONFIG_PATH = [] ;
|
646
|
0
|
0
|
0
|
|
|
0
|
if ($home && -d $home)
|
647
|
|
|
|
|
|
|
{
|
648
|
0
|
|
|
|
|
0
|
push @$DEFAULT_CONFIG_PATH, "$home/tv" ;
|
649
|
|
|
|
|
|
|
}
|
650
|
|
|
|
|
|
|
|
651
|
|
|
|
|
|
|
# add current dir
|
652
|
0
|
|
|
|
|
0
|
push @$DEFAULT_CONFIG_PATH, "." ;
|
653
|
|
|
|
|
|
|
}
|
654
|
|
|
|
|
|
|
elsif ( $^O eq 'MacOS' )
|
655
|
|
|
|
|
|
|
{
|
656
|
0
|
0
|
|
|
|
0
|
if (!$home)
|
657
|
|
|
|
|
|
|
{
|
658
|
|
|
|
|
|
|
# On some platforms getpwuid dies if called at all
|
659
|
0
|
|
|
|
|
0
|
local $SIG{'__DIE__'} = '';
|
660
|
0
|
|
|
|
|
0
|
$home = (getpwuid($<))[7];
|
661
|
|
|
|
|
|
|
}
|
662
|
|
|
|
|
|
|
|
663
|
0
|
|
|
|
|
0
|
$DEFAULT_CONFIG_PATH = [] ;
|
664
|
0
|
0
|
0
|
|
|
0
|
if ($home && -d $home)
|
665
|
|
|
|
|
|
|
{
|
666
|
0
|
|
|
|
|
0
|
push @$DEFAULT_CONFIG_PATH, "$home/tv" ;
|
667
|
|
|
|
|
|
|
}
|
668
|
|
|
|
|
|
|
|
669
|
|
|
|
|
|
|
# add current dir
|
670
|
0
|
|
|
|
|
0
|
push @$DEFAULT_CONFIG_PATH, "." ;
|
671
|
|
|
|
|
|
|
}
|
672
|
|
|
|
|
|
|
elsif ( ($^O eq 'linux') || ($^O eq 'cygwin') )
|
673
|
|
|
|
|
|
|
{
|
674
|
|
|
|
|
|
|
# Default to Linux::DVB::DVBT
|
675
|
|
|
|
|
|
|
}
|
676
|
|
|
|
|
|
|
else
|
677
|
|
|
|
|
|
|
{
|
678
|
|
|
|
|
|
|
# Default to Unix semantics
|
679
|
0
|
|
|
|
|
0
|
$DEFAULT_CONFIG_PATH = [ qw(/etc/dvb ~/.tv .) ] ;
|
680
|
|
|
|
|
|
|
}
|
681
|
|
|
|
|
|
|
|
682
|
|
|
|
|
|
|
|
683
|
|
|
|
|
|
|
|
684
|
|
|
|
|
|
|
#print "Search Path:\n" ;
|
685
|
|
|
|
|
|
|
#foreach (@$DEFAULT_CONFIG_PATH)
|
686
|
|
|
|
|
|
|
#{
|
687
|
|
|
|
|
|
|
# print " $_\n" ;
|
688
|
|
|
|
|
|
|
#}
|
689
|
|
|
|
|
|
|
|
690
|
|
|
|
|
|
|
|
691
|
|
|
|
|
|
|
}
|
692
|
|
|
|
|
|
|
|
693
|
|
|
|
|
|
|
|
694
|
|
|
|
|
|
|
|
695
|
|
|
|
|
|
|
#============================================================================================
|
696
|
|
|
|
|
|
|
|
697
|
|
|
|
|
|
|
=head2 Functions
|
698
|
|
|
|
|
|
|
|
699
|
|
|
|
|
|
|
=over 4
|
700
|
|
|
|
|
|
|
|
701
|
|
|
|
|
|
|
=cut
|
702
|
|
|
|
|
|
|
|
703
|
|
|
|
|
|
|
|
704
|
|
|
|
|
|
|
#----------------------------------------------------------------------
|
705
|
|
|
|
|
|
|
|
706
|
|
|
|
|
|
|
=item B
|
707
|
|
|
|
|
|
|
|
708
|
|
|
|
|
|
|
Read the advert settings file and return a HASH ref containing the settings.
|
709
|
|
|
|
|
|
|
|
710
|
|
|
|
|
|
|
Optionally set the search path (see L)
|
711
|
|
|
|
|
|
|
|
712
|
|
|
|
|
|
|
See L
|
713
|
|
|
|
|
|
|
|
714
|
|
|
|
|
|
|
=cut
|
715
|
|
|
|
|
|
|
|
716
|
|
|
|
|
|
|
sub read_dvb_adv
|
717
|
|
|
|
|
|
|
{
|
718
|
5
|
|
|
5
|
1
|
9
|
my ($search_path) = @_ ;
|
719
|
|
|
|
|
|
|
|
720
|
5
|
|
33
|
|
|
17
|
$search_path ||= $DEFAULT_CONFIG_PATH ;
|
721
|
5
|
|
|
|
|
12
|
$DEFAULT_CONFIG_PATH = $search_path ;
|
722
|
|
|
|
|
|
|
|
723
|
5
|
|
|
|
|
23
|
my $adv_settings_href = {
|
724
|
|
|
|
|
|
|
"$ADVERT_GLOBAL_SECTION" => {},
|
725
|
|
|
|
|
|
|
} ;
|
726
|
|
|
|
|
|
|
|
727
|
|
|
|
|
|
|
## Optional file so allow for it to be not present
|
728
|
5
|
|
|
|
|
27
|
my @fnames = read_filenames($search_path) ;
|
729
|
5
|
|
|
|
|
12
|
foreach my $fname (@fnames)
|
730
|
|
|
|
|
|
|
{
|
731
|
6
|
|
|
|
|
24
|
my %dvb_adv = (
|
732
|
|
|
|
|
|
|
"$ADVERT_GLOBAL_SECTION" => {},
|
733
|
|
|
|
|
|
|
) ;
|
734
|
6
|
100
|
|
|
|
375
|
if (open my $fh, "<$fname")
|
735
|
|
|
|
|
|
|
{
|
736
|
5
|
|
|
|
|
8
|
my $line ;
|
737
|
5
|
|
|
|
|
12
|
my $channel = $ADVERT_GLOBAL_SECTION ;
|
738
|
5
|
|
|
|
|
293
|
while(defined($line=<$fh>))
|
739
|
|
|
|
|
|
|
{
|
740
|
1074
|
|
|
|
|
1263
|
chomp $line ;
|
741
|
1074
|
100
|
|
|
|
4669
|
next if $line =~ /^\s*#/ ; # skip comments
|
742
|
|
|
|
|
|
|
|
743
|
468
|
100
|
|
|
|
700
|
if ($line =~ /\[([^]]+)\]/)
|
744
|
|
|
|
|
|
|
{
|
745
|
16
|
|
|
|
|
48
|
$channel=$1;
|
746
|
|
|
|
|
|
|
}
|
747
|
|
|
|
|
|
|
else
|
748
|
|
|
|
|
|
|
{
|
749
|
452
|
|
100
|
|
|
1042
|
$dvb_adv{$channel} ||= {} ;
|
750
|
452
|
|
|
|
|
858
|
parse_assignment($line, $dvb_adv{$channel}) ;
|
751
|
|
|
|
|
|
|
}
|
752
|
|
|
|
|
|
|
}
|
753
|
5
|
|
|
|
|
78
|
close $fh ;
|
754
|
|
|
|
|
|
|
|
755
|
|
|
|
|
|
|
# combine
|
756
|
5
|
|
|
|
|
21
|
$adv_settings_href = Linux::DVB::DVBT::Advert::Config::merge_settings(
|
757
|
|
|
|
|
|
|
$adv_settings_href,
|
758
|
|
|
|
|
|
|
\%dvb_adv,
|
759
|
|
|
|
|
|
|
) ;
|
760
|
|
|
|
|
|
|
}
|
761
|
|
|
|
|
|
|
|
762
|
|
|
|
|
|
|
}
|
763
|
|
|
|
|
|
|
|
764
|
5
|
|
|
|
|
25
|
return $adv_settings_href ;
|
765
|
|
|
|
|
|
|
}
|
766
|
|
|
|
|
|
|
|
767
|
|
|
|
|
|
|
|
768
|
|
|
|
|
|
|
#----------------------------------------------------------------------
|
769
|
|
|
|
|
|
|
|
770
|
|
|
|
|
|
|
=item B
|
771
|
|
|
|
|
|
|
|
772
|
|
|
|
|
|
|
Write advert config information
|
773
|
|
|
|
|
|
|
|
774
|
|
|
|
|
|
|
Optionally set the search path (see L)
|
775
|
|
|
|
|
|
|
|
776
|
|
|
|
|
|
|
=cut
|
777
|
|
|
|
|
|
|
|
778
|
|
|
|
|
|
|
sub write_dvb_adv
|
779
|
|
|
|
|
|
|
{
|
780
|
0
|
|
|
0
|
1
|
0
|
my ($href, $search_path) = @_ ;
|
781
|
|
|
|
|
|
|
|
782
|
0
|
|
0
|
|
|
0
|
$search_path ||= $DEFAULT_CONFIG_PATH ;
|
783
|
0
|
|
|
|
|
0
|
$DEFAULT_CONFIG_PATH = $search_path ;
|
784
|
|
|
|
|
|
|
|
785
|
|
|
|
|
|
|
## write settings
|
786
|
0
|
|
|
|
|
0
|
do_write_dvb_adv(write_filename($search_path), $href) ;
|
787
|
|
|
|
|
|
|
}
|
788
|
|
|
|
|
|
|
|
789
|
|
|
|
|
|
|
#----------------------------------------------------------------------
|
790
|
|
|
|
|
|
|
|
791
|
|
|
|
|
|
|
=item B
|
792
|
|
|
|
|
|
|
|
793
|
|
|
|
|
|
|
Returns the advert config file writeable filename path
|
794
|
|
|
|
|
|
|
|
795
|
|
|
|
|
|
|
Optionally set the search path (see L)
|
796
|
|
|
|
|
|
|
|
797
|
|
|
|
|
|
|
=cut
|
798
|
|
|
|
|
|
|
|
799
|
|
|
|
|
|
|
sub write_filename
|
800
|
|
|
|
|
|
|
{
|
801
|
0
|
|
|
0
|
1
|
0
|
my ($search_path) = @_ ;
|
802
|
|
|
|
|
|
|
|
803
|
0
|
|
0
|
|
|
0
|
$search_path ||= $DEFAULT_CONFIG_PATH ;
|
804
|
0
|
|
|
|
|
0
|
$DEFAULT_CONFIG_PATH = $search_path ;
|
805
|
|
|
|
|
|
|
|
806
|
0
|
|
|
|
|
0
|
my $dir = write_dir($search_path, $FILENAME) ;
|
807
|
|
|
|
|
|
|
|
808
|
0
|
|
|
|
|
0
|
return "$dir/$FILENAME" ;
|
809
|
|
|
|
|
|
|
}
|
810
|
|
|
|
|
|
|
|
811
|
|
|
|
|
|
|
#----------------------------------------------------------------------
|
812
|
|
|
|
|
|
|
|
813
|
|
|
|
|
|
|
=item B
|
814
|
|
|
|
|
|
|
|
815
|
|
|
|
|
|
|
Returns an array of found file paths for all readable advert config files found in search path
|
816
|
|
|
|
|
|
|
|
817
|
|
|
|
|
|
|
Optionally set the search path (see L)
|
818
|
|
|
|
|
|
|
|
819
|
|
|
|
|
|
|
=cut
|
820
|
|
|
|
|
|
|
|
821
|
|
|
|
|
|
|
sub read_filenames
|
822
|
|
|
|
|
|
|
{
|
823
|
5
|
|
|
5
|
1
|
869
|
my ($search_path) = @_ ;
|
824
|
|
|
|
|
|
|
|
825
|
5
|
|
33
|
|
|
16
|
$search_path ||= $DEFAULT_CONFIG_PATH ;
|
826
|
5
|
|
|
|
|
10
|
$DEFAULT_CONFIG_PATH = $search_path ;
|
827
|
|
|
|
|
|
|
|
828
|
5
|
|
|
|
|
20
|
my @files = read_dir($search_path, $FILENAME) ;
|
829
|
5
|
50
|
|
|
|
527
|
print "read_filenames() dirs=@files\n" if $DEBUG ;
|
830
|
5
|
|
|
|
|
16
|
foreach my $file (@files)
|
831
|
|
|
|
|
|
|
{
|
832
|
6
|
|
|
|
|
31
|
$file .= "/$FILENAME" ;
|
833
|
|
|
|
|
|
|
}
|
834
|
|
|
|
|
|
|
|
835
|
5
|
50
|
|
|
|
520
|
print "read_filenames() = @files\n" if $DEBUG ;
|
836
|
|
|
|
|
|
|
|
837
|
5
|
|
|
|
|
31
|
return @files ;
|
838
|
|
|
|
|
|
|
}
|
839
|
|
|
|
|
|
|
|
840
|
|
|
|
|
|
|
#----------------------------------------------------------------------
|
841
|
|
|
|
|
|
|
|
842
|
|
|
|
|
|
|
=item B
|
843
|
|
|
|
|
|
|
|
844
|
|
|
|
|
|
|
Write a default advert config information file
|
845
|
|
|
|
|
|
|
|
846
|
|
|
|
|
|
|
Optionally set the search path (see L)
|
847
|
|
|
|
|
|
|
|
848
|
|
|
|
|
|
|
=cut
|
849
|
|
|
|
|
|
|
|
850
|
|
|
|
|
|
|
sub write_default_dvb_adv
|
851
|
|
|
|
|
|
|
{
|
852
|
0
|
|
|
0
|
1
|
0
|
my ($href, $search_path) = @_ ;
|
853
|
|
|
|
|
|
|
|
854
|
0
|
|
0
|
|
|
0
|
$search_path ||= $DEFAULT_CONFIG_PATH ;
|
855
|
0
|
|
|
|
|
0
|
$DEFAULT_CONFIG_PATH = $search_path ;
|
856
|
|
|
|
|
|
|
|
857
|
|
|
|
|
|
|
# Add some example settings
|
858
|
0
|
|
|
|
|
0
|
my $settings_href = { %$href } ;
|
859
|
0
|
|
|
|
|
0
|
$settings_href->{'Dave'} = {
|
860
|
|
|
|
|
|
|
'reduce_end' => 900,
|
861
|
|
|
|
|
|
|
'reduce_min_gap' => 50,
|
862
|
|
|
|
|
|
|
} ;
|
863
|
0
|
|
|
|
|
0
|
$settings_href->{'BBC1'} = {
|
864
|
|
|
|
|
|
|
'detection_method' => 'disable',
|
865
|
|
|
|
|
|
|
} ;
|
866
|
0
|
|
|
|
|
0
|
$settings_href->{'BBC2'} = {
|
867
|
|
|
|
|
|
|
'detection_method' => 'disable',
|
868
|
|
|
|
|
|
|
} ;
|
869
|
|
|
|
|
|
|
# $settings_href->{'BBC3'} = {
|
870
|
|
|
|
|
|
|
# 'detection_method' => 'disable',
|
871
|
|
|
|
|
|
|
# } ;
|
872
|
|
|
|
|
|
|
# $settings_href->{'BBC4'} = {
|
873
|
|
|
|
|
|
|
# 'detection_method' => 'disable',
|
874
|
|
|
|
|
|
|
# } ;
|
875
|
0
|
|
|
|
|
0
|
$settings_href->{'Virgin1'} = {
|
876
|
|
|
|
|
|
|
'detection_method' => 'disable',
|
877
|
|
|
|
|
|
|
} ;
|
878
|
|
|
|
|
|
|
|
879
|
0
|
0
|
|
|
|
0
|
print Data::Dumper->Dump(["write_default_dvb_adv() settings:", $href]) if $DEBUG ;
|
880
|
|
|
|
|
|
|
|
881
|
|
|
|
|
|
|
# comment everything EXCEPT detection_method
|
882
|
0
|
|
|
|
|
0
|
my $commented_href = {} ;
|
883
|
|
|
|
|
|
|
|
884
|
0
|
|
|
|
|
0
|
foreach my $section (keys %$settings_href)
|
885
|
|
|
|
|
|
|
{
|
886
|
0
|
|
|
|
|
0
|
foreach my $field (sort keys %{$href->{$section}})
|
|
0
|
|
|
|
|
0
|
|
887
|
|
|
|
|
|
|
{
|
888
|
0
|
|
|
|
|
0
|
my $val = $href->{$section}{$field} ;
|
889
|
0
|
0
|
|
|
|
0
|
if (ref($val) eq 'HASH')
|
890
|
|
|
|
|
|
|
{
|
891
|
0
|
|
|
|
|
0
|
foreach my $subvar (sort keys %{$val})
|
|
0
|
|
|
|
|
0
|
|
892
|
|
|
|
|
|
|
{
|
893
|
0
|
0
|
|
|
|
0
|
next if $subvar eq $METHOD_VAR ;
|
894
|
0
|
|
|
|
|
0
|
$commented_href->{$section}{$field}{$subvar} = 1 ;
|
895
|
|
|
|
|
|
|
}
|
896
|
|
|
|
|
|
|
}
|
897
|
|
|
|
|
|
|
else
|
898
|
|
|
|
|
|
|
{
|
899
|
0
|
0
|
|
|
|
0
|
next if $field eq $METHOD_VAR ;
|
900
|
0
|
|
|
|
|
0
|
$commented_href->{$section}{$field} = 1 ;
|
901
|
|
|
|
|
|
|
}
|
902
|
|
|
|
|
|
|
}
|
903
|
|
|
|
|
|
|
}
|
904
|
|
|
|
|
|
|
|
905
|
|
|
|
|
|
|
## write example settings
|
906
|
0
|
|
|
|
|
0
|
do_write_dvb_adv(write_filename($search_path), $settings_href, $commented_href) ;
|
907
|
|
|
|
|
|
|
}
|
908
|
|
|
|
|
|
|
|
909
|
|
|
|
|
|
|
|
910
|
|
|
|
|
|
|
# ============================================================================================
|
911
|
|
|
|
|
|
|
# PROTECTED
|
912
|
|
|
|
|
|
|
|
913
|
|
|
|
|
|
|
#----------------------------------------------------------------------
|
914
|
|
|
|
|
|
|
# Uses optional $commented_href which comments out any matching elements
|
915
|
|
|
|
|
|
|
# This is only used for writing default config files (i.e. allows for
|
916
|
|
|
|
|
|
|
# commented examples)
|
917
|
|
|
|
|
|
|
#
|
918
|
|
|
|
|
|
|
sub do_write_dvb_adv
|
919
|
|
|
|
|
|
|
{
|
920
|
0
|
|
|
0
|
0
|
0
|
my ($fname, $href, $commented_href) = @_ ;
|
921
|
|
|
|
|
|
|
|
922
|
0
|
|
0
|
|
|
0
|
$commented_href ||= {} ;
|
923
|
|
|
|
|
|
|
|
924
|
0
|
0
|
|
|
|
0
|
open my $fh, ">$fname" or die "Error: Unable to write $fname : $!" ;
|
925
|
|
|
|
|
|
|
|
926
|
|
|
|
|
|
|
# Write config information
|
927
|
|
|
|
|
|
|
#
|
928
|
|
|
|
|
|
|
|
929
|
|
|
|
|
|
|
## Global first then channel specific (sort automatically picks global key first)
|
930
|
0
|
|
|
|
|
0
|
my %seen ;
|
931
|
0
|
|
|
|
|
0
|
foreach my $section (sort keys %$href)
|
932
|
|
|
|
|
|
|
{
|
933
|
0
|
0
|
|
|
|
0
|
if ($section ne $ADVERT_GLOBAL_SECTION)
|
934
|
|
|
|
|
|
|
{
|
935
|
0
|
|
|
|
|
0
|
print $fh "\n\n" ;
|
936
|
0
|
|
|
|
|
0
|
print $fh "# ====================================================================\n" ;
|
937
|
0
|
|
|
|
|
0
|
print $fh "# $section channel-specific settings\n" ;
|
938
|
0
|
|
|
|
|
0
|
print $fh "# ====================================================================\n" ;
|
939
|
0
|
|
|
|
|
0
|
print $fh "[$section]\n" ;
|
940
|
|
|
|
|
|
|
}
|
941
|
|
|
|
|
|
|
else
|
942
|
|
|
|
|
|
|
{
|
943
|
0
|
|
|
|
|
0
|
print $fh "\n\n" ;
|
944
|
0
|
|
|
|
|
0
|
print $fh "# ====================================================================\n" ;
|
945
|
0
|
|
|
|
|
0
|
print $fh "# Global settings\n" ;
|
946
|
0
|
|
|
|
|
0
|
print $fh "# \n" ;
|
947
|
0
|
|
|
|
|
0
|
print $fh "# (These settings propagate to any unset channel-specific settings)\n" ;
|
948
|
0
|
|
|
|
|
0
|
print $fh "# ====================================================================\n" ;
|
949
|
|
|
|
|
|
|
}
|
950
|
0
|
|
|
|
|
0
|
print $fh "\n\n" ;
|
951
|
|
|
|
|
|
|
|
952
|
0
|
|
0
|
|
|
0
|
$seen{$section} ||= {} ;
|
953
|
|
|
|
|
|
|
|
954
|
|
|
|
|
|
|
## Drive output from template
|
955
|
0
|
|
|
|
|
0
|
for my $region (@SETTINGS_REGIONS)
|
956
|
|
|
|
|
|
|
{
|
957
|
0
|
|
|
|
|
0
|
my $buffer = "" ;
|
958
|
0
|
|
|
|
|
0
|
my $clear_buffer = 0 ;
|
959
|
|
|
|
|
|
|
|
960
|
0
|
|
|
|
|
0
|
foreach my $line (@{$SETTINGS_TEMPLATE{$region}})
|
|
0
|
|
|
|
|
0
|
|
961
|
|
|
|
|
|
|
{
|
962
|
0
|
0
|
0
|
|
|
0
|
if (!$line || ($line =~ /#/))
|
963
|
|
|
|
|
|
|
{
|
964
|
0
|
0
|
|
|
|
0
|
$buffer = "" if $clear_buffer ;
|
965
|
0
|
|
|
|
|
0
|
$buffer .= "$line\n" ;
|
966
|
|
|
|
|
|
|
}
|
967
|
|
|
|
|
|
|
else
|
968
|
|
|
|
|
|
|
{
|
969
|
|
|
|
|
|
|
# this is a variable
|
970
|
0
|
|
|
|
|
0
|
++$clear_buffer ;
|
971
|
0
|
|
|
|
|
0
|
my $printed = 0 ;
|
972
|
0
|
|
|
|
|
0
|
my ($field, $subvar) = _field_parse($line) ;
|
973
|
0
|
|
|
|
|
0
|
my $comment = _lookup_comment($field, $subvar) ;
|
974
|
|
|
|
|
|
|
|
975
|
0
|
|
|
|
|
0
|
my $val = $href->{$section}{$field} ;
|
976
|
0
|
0
|
|
|
|
0
|
if ($subvar)
|
977
|
|
|
|
|
|
|
{
|
978
|
0
|
0
|
0
|
|
|
0
|
if (exists($val->{$subvar}) && defined($val->{$subvar}))
|
979
|
|
|
|
|
|
|
{
|
980
|
0
|
|
|
|
|
0
|
print $fh $buffer ;
|
981
|
0
|
|
|
|
|
0
|
++$printed ;
|
982
|
|
|
|
|
|
|
|
983
|
0
|
0
|
|
|
|
0
|
print $fh "# $comment\n" if $comment ;
|
984
|
0
|
0
|
|
|
|
0
|
print $fh "#" if ($commented_href->{$section}{$field}{$subvar}) ;
|
985
|
0
|
|
|
|
|
0
|
print $fh "$field.$subvar = $val->{$subvar}\n" ;
|
986
|
|
|
|
|
|
|
}
|
987
|
|
|
|
|
|
|
|
988
|
0
|
|
0
|
|
|
0
|
$seen{$section}{$field} ||= {} ;
|
989
|
0
|
|
|
|
|
0
|
$seen{$field}{$subvar} = 1 ;
|
990
|
|
|
|
|
|
|
}
|
991
|
|
|
|
|
|
|
else
|
992
|
|
|
|
|
|
|
{
|
993
|
0
|
0
|
|
|
|
0
|
if (defined($val))
|
994
|
|
|
|
|
|
|
{
|
995
|
0
|
|
|
|
|
0
|
print $fh $buffer ;
|
996
|
0
|
|
|
|
|
0
|
++$printed ;
|
997
|
|
|
|
|
|
|
|
998
|
0
|
0
|
|
|
|
0
|
print $fh "# $comment\n" if $comment ;
|
999
|
0
|
0
|
|
|
|
0
|
print $fh "#" if ($commented_href->{$section}{$field}) ;
|
1000
|
|
|
|
|
|
|
|
1001
|
0
|
0
|
|
|
|
0
|
if ($field eq $METHOD_VAR)
|
1002
|
|
|
|
|
|
|
{
|
1003
|
0
|
|
|
|
|
0
|
my $str = method_string($val) ;
|
1004
|
0
|
|
|
|
|
0
|
print $fh "$field = $str\n" ;
|
1005
|
|
|
|
|
|
|
}
|
1006
|
|
|
|
|
|
|
else
|
1007
|
|
|
|
|
|
|
{
|
1008
|
0
|
|
|
|
|
0
|
print $fh "$field = $val\n" ;
|
1009
|
|
|
|
|
|
|
}
|
1010
|
|
|
|
|
|
|
}
|
1011
|
0
|
|
|
|
|
0
|
$seen{$section}{$field} = 1 ;
|
1012
|
|
|
|
|
|
|
}
|
1013
|
|
|
|
|
|
|
|
1014
|
0
|
0
|
|
|
|
0
|
if ($printed)
|
1015
|
|
|
|
|
|
|
{
|
1016
|
0
|
|
|
|
|
0
|
print $fh "\n" ;
|
1017
|
0
|
|
|
|
|
0
|
$buffer = "" ;
|
1018
|
|
|
|
|
|
|
}
|
1019
|
|
|
|
|
|
|
}
|
1020
|
|
|
|
|
|
|
}
|
1021
|
|
|
|
|
|
|
|
1022
|
|
|
|
|
|
|
# ## Catch any "unseen" (i.e. I've forgotten to update the templates!)
|
1023
|
|
|
|
|
|
|
# foreach my $field (sort keys %{$href->{$section}})
|
1024
|
|
|
|
|
|
|
# {
|
1025
|
|
|
|
|
|
|
# my $val = $href->{$section}{$field} ;
|
1026
|
|
|
|
|
|
|
# if (ref($val) eq 'HASH')
|
1027
|
|
|
|
|
|
|
# {
|
1028
|
|
|
|
|
|
|
# foreach my $subvar (sort keys %{$val})
|
1029
|
|
|
|
|
|
|
# {
|
1030
|
|
|
|
|
|
|
# next if ($seen{$section}{$field}{$subvar}) ;
|
1031
|
|
|
|
|
|
|
# print $fh "$field.$subvar = $val->{$subvar}\n" ;
|
1032
|
|
|
|
|
|
|
# }
|
1033
|
|
|
|
|
|
|
# }
|
1034
|
|
|
|
|
|
|
# else
|
1035
|
|
|
|
|
|
|
# {
|
1036
|
|
|
|
|
|
|
# next if ($seen{$section}{$field}) ;
|
1037
|
|
|
|
|
|
|
#
|
1038
|
|
|
|
|
|
|
# if ($field eq $METHOD_VAR)
|
1039
|
|
|
|
|
|
|
# {
|
1040
|
|
|
|
|
|
|
# my $str = method_string($val) ;
|
1041
|
|
|
|
|
|
|
# print $fh "$field = $str\n" ;
|
1042
|
|
|
|
|
|
|
# }
|
1043
|
|
|
|
|
|
|
# else
|
1044
|
|
|
|
|
|
|
# {
|
1045
|
|
|
|
|
|
|
# if ($val =~ /\S+/)
|
1046
|
|
|
|
|
|
|
# {
|
1047
|
|
|
|
|
|
|
# print $fh "$field = $val\n" ;
|
1048
|
|
|
|
|
|
|
# }
|
1049
|
|
|
|
|
|
|
# }
|
1050
|
|
|
|
|
|
|
# }
|
1051
|
|
|
|
|
|
|
# }
|
1052
|
|
|
|
|
|
|
}
|
1053
|
|
|
|
|
|
|
|
1054
|
0
|
|
|
|
|
0
|
print $fh "\n" ;
|
1055
|
|
|
|
|
|
|
}
|
1056
|
|
|
|
|
|
|
|
1057
|
0
|
|
|
|
|
0
|
close $fh ;
|
1058
|
|
|
|
|
|
|
}
|
1059
|
|
|
|
|
|
|
|
1060
|
|
|
|
|
|
|
|
1061
|
|
|
|
|
|
|
#----------------------------------------------------------------------
|
1062
|
|
|
|
|
|
|
sub method_string
|
1063
|
|
|
|
|
|
|
{
|
1064
|
0
|
|
|
0
|
0
|
0
|
my ($val) = @_ ;
|
1065
|
0
|
|
|
|
|
0
|
my $method_str = "" ;
|
1066
|
|
|
|
|
|
|
|
1067
|
0
|
0
|
|
|
|
0
|
if ($val == 0)
|
1068
|
|
|
|
|
|
|
{
|
1069
|
|
|
|
|
|
|
## disabled
|
1070
|
0
|
|
|
|
|
0
|
$method_str = $METHOD_DISABLE ;
|
1071
|
|
|
|
|
|
|
}
|
1072
|
|
|
|
|
|
|
else
|
1073
|
|
|
|
|
|
|
{
|
1074
|
|
|
|
|
|
|
## special
|
1075
|
0
|
|
|
|
|
0
|
foreach my $method_key (keys %{$Linux::DVB::DVBT::Advert::Constants::CONSTANTS{'Advert'}{'detection_method_special'}})
|
|
0
|
|
|
|
|
0
|
|
1076
|
|
|
|
|
|
|
{
|
1077
|
0
|
|
|
|
|
0
|
my $method_val = $Linux::DVB::DVBT::Advert::Constants::CONSTANTS{'Advert'}{'detection_method_special'}{$method_key} ;
|
1078
|
0
|
0
|
|
|
|
0
|
if ($val == $method_val)
|
1079
|
|
|
|
|
|
|
{
|
1080
|
0
|
|
|
|
|
0
|
$method_str = $method_key ;
|
1081
|
0
|
|
|
|
|
0
|
last ;
|
1082
|
|
|
|
|
|
|
}
|
1083
|
|
|
|
|
|
|
}
|
1084
|
|
|
|
|
|
|
}
|
1085
|
|
|
|
|
|
|
|
1086
|
|
|
|
|
|
|
## Not found it yet, so work out the string
|
1087
|
0
|
0
|
|
|
|
0
|
if (!$method_str)
|
1088
|
|
|
|
|
|
|
{
|
1089
|
0
|
|
|
|
|
0
|
foreach my $method_key (keys %{$Linux::DVB::DVBT::Advert::Constants::CONSTANTS{'Advert'}{'detection_method'}})
|
|
0
|
|
|
|
|
0
|
|
1090
|
|
|
|
|
|
|
{
|
1091
|
0
|
|
|
|
|
0
|
my $method_val = $Linux::DVB::DVBT::Advert::Constants::CONSTANTS{'Advert'}{'detection_method'}{$method_key} ;
|
1092
|
0
|
0
|
|
|
|
0
|
if ($val & $method_val)
|
1093
|
|
|
|
|
|
|
{
|
1094
|
0
|
0
|
|
|
|
0
|
$method_str .= " + " if $method_str ;
|
1095
|
0
|
|
|
|
|
0
|
$method_str .= $method_key ;
|
1096
|
|
|
|
|
|
|
}
|
1097
|
|
|
|
|
|
|
}
|
1098
|
|
|
|
|
|
|
}
|
1099
|
|
|
|
|
|
|
|
1100
|
0
|
0
|
|
|
|
0
|
if (!$method_str)
|
1101
|
|
|
|
|
|
|
{
|
1102
|
|
|
|
|
|
|
# error catchall
|
1103
|
0
|
|
|
|
|
0
|
$method_str = 'default' ;
|
1104
|
|
|
|
|
|
|
}
|
1105
|
|
|
|
|
|
|
|
1106
|
0
|
|
|
|
|
0
|
return $method_str ;
|
1107
|
|
|
|
|
|
|
}
|
1108
|
|
|
|
|
|
|
|
1109
|
|
|
|
|
|
|
|
1110
|
|
|
|
|
|
|
#----------------------------------------------------------------------
|
1111
|
|
|
|
|
|
|
sub parse_val
|
1112
|
|
|
|
|
|
|
{
|
1113
|
84
|
|
|
84
|
0
|
117
|
my ($val) = @_ ;
|
1114
|
84
|
|
|
|
|
80
|
my $ival ;
|
1115
|
|
|
|
|
|
|
|
1116
|
84
|
50
|
|
|
|
334
|
if ($val =~ /^0x([\da-z]+)/i)
|
|
|
100
|
|
|
|
|
|
1117
|
|
|
|
|
|
|
{
|
1118
|
0
|
|
|
|
|
0
|
$ival = hex($1) ;
|
1119
|
|
|
|
|
|
|
}
|
1120
|
|
|
|
|
|
|
elsif ($val =~ /([\d]+)/)
|
1121
|
|
|
|
|
|
|
{
|
1122
|
71
|
|
|
|
|
119
|
$ival = int($1) ;
|
1123
|
|
|
|
|
|
|
}
|
1124
|
|
|
|
|
|
|
|
1125
|
84
|
|
|
|
|
140
|
return $ival ;
|
1126
|
|
|
|
|
|
|
}
|
1127
|
|
|
|
|
|
|
|
1128
|
|
|
|
|
|
|
#----------------------------------------------------------------------
|
1129
|
|
|
|
|
|
|
# Convert mode string into value (eg default - logo + audio)
|
1130
|
|
|
|
|
|
|
sub parse_method
|
1131
|
|
|
|
|
|
|
{
|
1132
|
13
|
|
|
13
|
0
|
22
|
my ($var, $val) = @_ ;
|
1133
|
|
|
|
|
|
|
|
1134
|
13
|
50
|
|
|
|
234
|
print "parse_method($var, $val)\n" if $DEBUG >= 10 ;
|
1135
|
|
|
|
|
|
|
|
1136
|
13
|
|
|
|
|
27
|
my $ival = parse_val($val) ;
|
1137
|
13
|
50
|
|
|
|
30
|
if (defined($ival))
|
1138
|
|
|
|
|
|
|
{
|
1139
|
|
|
|
|
|
|
## Integer - if non-zero then ensure minimum settings are applied
|
1140
|
0
|
|
|
|
|
0
|
$val = $ival ;
|
1141
|
|
|
|
|
|
|
|
1142
|
0
|
0
|
|
|
|
0
|
if ($val)
|
1143
|
|
|
|
|
|
|
{
|
1144
|
0
|
|
|
|
|
0
|
$val |= $Linux::DVB::DVBT::Advert::Constants::CONSTANTS{'Advert'}{'detection_method_special'}{'MIN'} ;
|
1145
|
|
|
|
|
|
|
}
|
1146
|
|
|
|
|
|
|
}
|
1147
|
|
|
|
|
|
|
else
|
1148
|
|
|
|
|
|
|
{
|
1149
|
|
|
|
|
|
|
# Special string 'disable' or 'none' overrides everything
|
1150
|
13
|
100
|
|
|
|
139
|
if ($val =~ /$METHOD_DISABLE_REGEXP/)
|
1151
|
|
|
|
|
|
|
{
|
1152
|
|
|
|
|
|
|
# no detection
|
1153
|
12
|
|
|
|
|
20
|
$val = 0 ;
|
1154
|
|
|
|
|
|
|
}
|
1155
|
|
|
|
|
|
|
else
|
1156
|
|
|
|
|
|
|
{
|
1157
|
|
|
|
|
|
|
# Allow definitions of the form:
|
1158
|
|
|
|
|
|
|
# default -logo +audio = (black+logo+audio) - logo +audio = black+audio
|
1159
|
|
|
|
|
|
|
# logo + audio = logo+audio -> black+logo+audio (always add MIN)
|
1160
|
|
|
|
|
|
|
# -logo +audio = (black+logo+audio) - logo +audio = black+audio (infers default)
|
1161
|
|
|
|
|
|
|
#
|
1162
|
1
|
|
|
|
|
9
|
my $got_base=0 ;
|
1163
|
1
|
|
|
|
|
2
|
my $method=0 ;
|
1164
|
1
|
|
|
|
|
2
|
my $op = '' ;
|
1165
|
1
|
|
|
|
|
7
|
while ($val =~ /([\+\-]|\S+)/g)
|
1166
|
|
|
|
|
|
|
{
|
1167
|
1
|
|
|
|
|
3
|
my $token = $1 ;
|
1168
|
1
|
50
|
|
|
|
3
|
print " + token: \"$token\" (got base=$got_base) method=$method op=$op\n" if $DEBUG >= 10 ;
|
1169
|
1
|
50
|
|
|
|
5
|
if ($token =~ /(\+|\-)/)
|
1170
|
|
|
|
|
|
|
{
|
1171
|
0
|
0
|
|
|
|
0
|
print " + + an op\n" if $DEBUG >= 10 ;
|
1172
|
|
|
|
|
|
|
## + or - operator, see if a base value has been specified, otherwise start with default
|
1173
|
0
|
|
|
|
|
0
|
$op = $1 ;
|
1174
|
0
|
0
|
|
|
|
0
|
if (!$got_base)
|
1175
|
|
|
|
|
|
|
{
|
1176
|
0
|
|
|
|
|
0
|
$method = $Linux::DVB::DVBT::Advert::Constants::CONSTANTS{'Advert'}{'detection_method_special'}{'DEFAULT'} ;
|
1177
|
0
|
|
|
|
|
0
|
++$got_base ;
|
1178
|
0
|
0
|
|
|
|
0
|
print " + + + set base method=$method\n" if $DEBUG >= 10 ;
|
1179
|
|
|
|
|
|
|
}
|
1180
|
0
|
0
|
|
|
|
0
|
print " + + op=$op\n" if $DEBUG >= 10 ;
|
1181
|
|
|
|
|
|
|
}
|
1182
|
|
|
|
|
|
|
else
|
1183
|
|
|
|
|
|
|
{
|
1184
|
1
|
|
|
|
|
3
|
my $method_key = uc $token ;
|
1185
|
1
|
50
|
|
|
|
3
|
print " + + a key $method_key\n" if $DEBUG >= 10 ;
|
1186
|
1
|
50
|
|
|
|
13
|
if (exists($Linux::DVB::DVBT::Advert::Constants::CONSTANTS{'Advert'}{'detection_method'}{$method_key}))
|
|
|
50
|
|
|
|
|
|
1187
|
|
|
|
|
|
|
{
|
1188
|
0
|
0
|
|
|
|
0
|
print " + + + exists! (op=$op)\n" if $DEBUG >= 10 ;
|
1189
|
0
|
0
|
|
|
|
0
|
if (!$op)
|
1190
|
|
|
|
|
|
|
{
|
1191
|
|
|
|
|
|
|
# Set method to this value
|
1192
|
0
|
|
|
|
|
0
|
$method = $Linux::DVB::DVBT::Advert::Constants::CONSTANTS{'Advert'}{'detection_method'}{$method_key} ;
|
1193
|
0
|
|
|
|
|
0
|
++$got_base ;
|
1194
|
0
|
0
|
|
|
|
0
|
print " + + + set base method=$method\n" if $DEBUG >= 10 ;
|
1195
|
|
|
|
|
|
|
}
|
1196
|
|
|
|
|
|
|
else
|
1197
|
|
|
|
|
|
|
{
|
1198
|
0
|
0
|
|
|
|
0
|
if ($op eq '+')
|
1199
|
|
|
|
|
|
|
{
|
1200
|
|
|
|
|
|
|
## Add
|
1201
|
0
|
|
|
|
|
0
|
$method |= $Linux::DVB::DVBT::Advert::Constants::CONSTANTS{'Advert'}{'detection_method'}{$method_key} ;
|
1202
|
|
|
|
|
|
|
}
|
1203
|
|
|
|
|
|
|
else
|
1204
|
|
|
|
|
|
|
{
|
1205
|
|
|
|
|
|
|
## Subtract
|
1206
|
0
|
|
|
|
|
0
|
$method &= ~$Linux::DVB::DVBT::Advert::Constants::CONSTANTS{'Advert'}{'detection_method'}{$method_key} ;
|
1207
|
|
|
|
|
|
|
}
|
1208
|
0
|
|
|
|
|
0
|
$op = '' ;
|
1209
|
0
|
0
|
|
|
|
0
|
print " + + + set method=$method\n" if $DEBUG >= 10 ;
|
1210
|
|
|
|
|
|
|
}
|
1211
|
|
|
|
|
|
|
}
|
1212
|
|
|
|
|
|
|
elsif (exists($Linux::DVB::DVBT::Advert::Constants::CONSTANTS{'Advert'}{'detection_method_special'}{$method_key}))
|
1213
|
|
|
|
|
|
|
{
|
1214
|
|
|
|
|
|
|
## override with special value (e.g. 'default')
|
1215
|
1
|
|
|
|
|
3
|
$method = $Linux::DVB::DVBT::Advert::Constants::CONSTANTS{'Advert'}{'detection_method_special'}{$method_key} ;
|
1216
|
1
|
|
|
|
|
2
|
$op = '' ;
|
1217
|
1
|
50
|
|
|
|
6
|
print " + + + set method=$method\n" if $DEBUG >= 10 ;
|
1218
|
|
|
|
|
|
|
}
|
1219
|
|
|
|
|
|
|
}
|
1220
|
|
|
|
|
|
|
}
|
1221
|
|
|
|
|
|
|
|
1222
|
1
|
50
|
|
|
|
2
|
print " + method=$val\n" if $DEBUG >= 10 ;
|
1223
|
|
|
|
|
|
|
|
1224
|
1
|
50
|
|
|
|
3
|
$method = 0 if $method < 0 ;
|
1225
|
1
|
|
|
|
|
3
|
$method |= $Linux::DVB::DVBT::Advert::Constants::CONSTANTS{'Advert'}{'detection_method_special'}{'MIN'} ;
|
1226
|
|
|
|
|
|
|
|
1227
|
1
|
|
|
|
|
3
|
$val = $method ;
|
1228
|
1
|
50
|
|
|
|
4
|
print "METHOD: method=$val\n" if $DEBUG >= 10 ;
|
1229
|
|
|
|
|
|
|
}
|
1230
|
|
|
|
|
|
|
}
|
1231
|
13
|
50
|
|
|
|
29
|
print "METHOD: val=$val\n" if $DEBUG >= 10 ;
|
1232
|
|
|
|
|
|
|
|
1233
|
13
|
|
|
|
|
25
|
return $val ;
|
1234
|
|
|
|
|
|
|
}
|
1235
|
|
|
|
|
|
|
|
1236
|
|
|
|
|
|
|
|
1237
|
|
|
|
|
|
|
#----------------------------------------------------------------------
|
1238
|
|
|
|
|
|
|
sub parse_value
|
1239
|
|
|
|
|
|
|
{
|
1240
|
84
|
|
|
84
|
0
|
110
|
my ($var, $val) = @_ ;
|
1241
|
|
|
|
|
|
|
|
1242
|
84
|
100
|
|
|
|
145
|
if ($var eq $METHOD_VAR)
|
1243
|
|
|
|
|
|
|
{
|
1244
|
13
|
|
|
|
|
27
|
$val = parse_method($var, $val) ;
|
1245
|
|
|
|
|
|
|
}
|
1246
|
|
|
|
|
|
|
else
|
1247
|
|
|
|
|
|
|
{
|
1248
|
71
|
|
|
|
|
122
|
my $ival = parse_val($val) ;
|
1249
|
71
|
50
|
|
|
|
437
|
if (defined($ival))
|
1250
|
|
|
|
|
|
|
{
|
1251
|
71
|
|
|
|
|
97
|
$val = $ival ;
|
1252
|
|
|
|
|
|
|
}
|
1253
|
|
|
|
|
|
|
}
|
1254
|
84
|
|
|
|
|
443
|
return $val ;
|
1255
|
|
|
|
|
|
|
}
|
1256
|
|
|
|
|
|
|
|
1257
|
|
|
|
|
|
|
#----------------------------------------------------------------------
|
1258
|
|
|
|
|
|
|
sub parse_assignment
|
1259
|
|
|
|
|
|
|
{
|
1260
|
452
|
|
|
452
|
0
|
618
|
my ($line, $href) = @_ ;
|
1261
|
|
|
|
|
|
|
|
1262
|
452
|
100
|
|
|
|
1536
|
if ($line =~ /(\S+)\s*=\s*(\S+.*)/)
|
1263
|
|
|
|
|
|
|
{
|
1264
|
84
|
|
|
|
|
194
|
my ($var, $val) = ($1, $2) ;
|
1265
|
84
|
|
|
|
|
252
|
$val =~ s/\s+$// ;
|
1266
|
84
|
100
|
|
|
|
294
|
if ($var =~ /([\w\d]+)\.([\w\d]+)/)
|
1267
|
|
|
|
|
|
|
{
|
1268
|
|
|
|
|
|
|
# of the form:
|
1269
|
|
|
|
|
|
|
# logo.logo_threshold
|
1270
|
|
|
|
|
|
|
#
|
1271
|
|
|
|
|
|
|
# so save as:
|
1272
|
|
|
|
|
|
|
# {logo}{logo_threshold}
|
1273
|
|
|
|
|
|
|
#
|
1274
|
43
|
|
100
|
|
|
148
|
$href->{$1} ||= {} ;
|
1275
|
43
|
|
|
|
|
70
|
$href->{$1}{$2} = parse_value($var, $val) ;
|
1276
|
|
|
|
|
|
|
}
|
1277
|
|
|
|
|
|
|
else
|
1278
|
|
|
|
|
|
|
{
|
1279
|
41
|
|
|
|
|
216
|
$href->{$var} = parse_value($var, $val) ;
|
1280
|
|
|
|
|
|
|
}
|
1281
|
|
|
|
|
|
|
}
|
1282
|
|
|
|
|
|
|
}
|
1283
|
|
|
|
|
|
|
|
1284
|
|
|
|
|
|
|
#----------------------------------------------------------------------
|
1285
|
|
|
|
|
|
|
# Need to copy globals down to key (if not already set), then use defaults
|
1286
|
|
|
|
|
|
|
# if neither set
|
1287
|
|
|
|
|
|
|
#
|
1288
|
|
|
|
|
|
|
sub cascade_settings
|
1289
|
|
|
|
|
|
|
{
|
1290
|
0
|
|
|
0
|
0
|
0
|
my ($settings_href, $key, $defaults_href) = @_ ;
|
1291
|
|
|
|
|
|
|
|
1292
|
0
|
|
0
|
|
|
0
|
$settings_href ||= {} ;
|
1293
|
0
|
|
0
|
|
|
0
|
$defaults_href ||= {} ;
|
1294
|
|
|
|
|
|
|
|
1295
|
0
|
|
|
|
|
0
|
my $cascaded_href = {} ;
|
1296
|
|
|
|
|
|
|
|
1297
|
0
|
0
|
|
|
|
0
|
print Data::Dumper->Dump(["cascade_settings($key) IN:", $settings_href, "DEFAULTS:", $defaults_href]) if $DEBUG >= 10 ;
|
1298
|
|
|
|
|
|
|
|
1299
|
|
|
|
|
|
|
## start with defaults as a baseline
|
1300
|
0
|
0
|
0
|
|
|
0
|
if ($key && exists($defaults_href->{$key}))
|
1301
|
|
|
|
|
|
|
{
|
1302
|
0
|
|
|
|
|
0
|
_hash_copy_shallow($defaults_href->{$key}, $cascaded_href) ;
|
1303
|
|
|
|
|
|
|
}
|
1304
|
|
|
|
|
|
|
else
|
1305
|
|
|
|
|
|
|
{
|
1306
|
0
|
|
|
|
|
0
|
_hash_copy_shallow($defaults_href, $cascaded_href) ;
|
1307
|
|
|
|
|
|
|
}
|
1308
|
|
|
|
|
|
|
|
1309
|
|
|
|
|
|
|
## copy over any settings defined in the global namespace
|
1310
|
0
|
|
|
|
|
0
|
_hash_copy_shallow($settings_href, $cascaded_href) ;
|
1311
|
|
|
|
|
|
|
|
1312
|
|
|
|
|
|
|
## copy over any settings defined in the key's namespace
|
1313
|
0
|
0
|
0
|
|
|
0
|
if ($key && exists($settings_href->{$key}))
|
1314
|
|
|
|
|
|
|
{
|
1315
|
0
|
|
|
|
|
0
|
_hash_copy_shallow($settings_href->{$key}, $cascaded_href) ;
|
1316
|
|
|
|
|
|
|
}
|
1317
|
|
|
|
|
|
|
else
|
1318
|
|
|
|
|
|
|
{
|
1319
|
0
|
|
|
|
|
0
|
_hash_copy_shallow($settings_href, $cascaded_href) ;
|
1320
|
|
|
|
|
|
|
}
|
1321
|
0
|
0
|
|
|
|
0
|
print Data::Dumper->Dump(["cascade_settings($key) OUT:", $cascaded_href]) if $DEBUG >= 10 ;
|
1322
|
|
|
|
|
|
|
|
1323
|
0
|
|
|
|
|
0
|
return $cascaded_href ;
|
1324
|
|
|
|
|
|
|
}
|
1325
|
|
|
|
|
|
|
|
1326
|
|
|
|
|
|
|
#----------------------------------------------------------------------
|
1327
|
|
|
|
|
|
|
# Do a deep copy of one HASH heirarchy of settings onto another
|
1328
|
|
|
|
|
|
|
# List of settings starting with lowest priority
|
1329
|
|
|
|
|
|
|
#
|
1330
|
|
|
|
|
|
|
sub merge_settings
|
1331
|
|
|
|
|
|
|
{
|
1332
|
6
|
|
|
6
|
0
|
15
|
my (@settings_list) = @_ ;
|
1333
|
|
|
|
|
|
|
|
1334
|
6
|
50
|
|
|
|
21
|
print Data::Dumper->Dump(["merge_settings() IN:", \@settings_list]) if $DEBUG >= 10 ;
|
1335
|
|
|
|
|
|
|
|
1336
|
6
|
|
|
|
|
49
|
my $merged_href = {} ;
|
1337
|
6
|
|
|
|
|
15
|
foreach my $href (@settings_list)
|
1338
|
|
|
|
|
|
|
{
|
1339
|
13
|
|
|
|
|
31
|
_hash_copy_deep($href, $merged_href);
|
1340
|
|
|
|
|
|
|
}
|
1341
|
|
|
|
|
|
|
|
1342
|
6
|
50
|
|
|
|
19
|
print Data::Dumper->Dump(["merge_settings() OUT:", $merged_href]) if $DEBUG >= 10 ;
|
1343
|
|
|
|
|
|
|
|
1344
|
6
|
|
|
|
|
48
|
return $merged_href ;
|
1345
|
|
|
|
|
|
|
}
|
1346
|
|
|
|
|
|
|
|
1347
|
|
|
|
|
|
|
|
1348
|
|
|
|
|
|
|
|
1349
|
|
|
|
|
|
|
#----------------------------------------------------------------------
|
1350
|
|
|
|
|
|
|
# Do a deep copy of the HASH and sub-hashes, propagating global settings down onto
|
1351
|
|
|
|
|
|
|
# any unset channel settings
|
1352
|
|
|
|
|
|
|
#
|
1353
|
|
|
|
|
|
|
sub channel_settings
|
1354
|
|
|
|
|
|
|
{
|
1355
|
1
|
|
|
1
|
0
|
3
|
my ($advert_settings_href, $channel) = @_ ;
|
1356
|
|
|
|
|
|
|
|
1357
|
1
|
|
50
|
|
|
3
|
$channel ||= "" ;
|
1358
|
1
|
|
|
|
|
4
|
$channel =~ s/^['"](.*)['"]$/$1/ ;
|
1359
|
|
|
|
|
|
|
|
1360
|
1
|
50
|
|
|
|
4
|
print Data::Dumper->Dump(["channel_settings($channel) IN:", $advert_settings_href]) if $DEBUG >= 10 ;
|
1361
|
|
|
|
|
|
|
|
1362
|
1
|
|
|
|
|
2
|
my $cascaded_href = {} ;
|
1363
|
|
|
|
|
|
|
|
1364
|
|
|
|
|
|
|
## Get copy of globals
|
1365
|
1
|
|
|
|
|
5
|
_hash_copy_deep($advert_settings_href->{$ADVERT_GLOBAL_SECTION}, $cascaded_href);
|
1366
|
|
|
|
|
|
|
|
1367
|
|
|
|
|
|
|
## If channel specified, overwrite globals with channel-specific
|
1368
|
1
|
50
|
33
|
|
|
22
|
if ($channel && exists($advert_settings_href->{$channel}))
|
1369
|
|
|
|
|
|
|
{
|
1370
|
0
|
|
|
|
|
0
|
_hash_copy_deep($advert_settings_href->{$channel}, $cascaded_href);
|
1371
|
|
|
|
|
|
|
|
1372
|
|
|
|
|
|
|
## Insert channel name into settings
|
1373
|
0
|
|
|
|
|
0
|
$cascaded_href->{'channel'} = $channel ;
|
1374
|
|
|
|
|
|
|
}
|
1375
|
|
|
|
|
|
|
|
1376
|
1
|
50
|
|
|
|
4
|
print Data::Dumper->Dump(["channel_settings($channel) OUT:", $cascaded_href]) if $DEBUG >= 10 ;
|
1377
|
1
|
|
|
|
|
3
|
return $cascaded_href ;
|
1378
|
|
|
|
|
|
|
}
|
1379
|
|
|
|
|
|
|
|
1380
|
|
|
|
|
|
|
|
1381
|
|
|
|
|
|
|
|
1382
|
|
|
|
|
|
|
# ============================================================================================
|
1383
|
|
|
|
|
|
|
# ============================================================================================
|
1384
|
|
|
|
|
|
|
|
1385
|
|
|
|
|
|
|
|
1386
|
|
|
|
|
|
|
#---------------------------------------------------------------------------------
|
1387
|
|
|
|
|
|
|
# Copy key values from one hash into another. Follow a single depth of hierarchy for any
|
1388
|
|
|
|
|
|
|
# HASH entries
|
1389
|
|
|
|
|
|
|
sub _hash_copy_deep
|
1390
|
|
|
|
|
|
|
{
|
1391
|
14
|
|
|
14
|
|
22
|
my ($base_href, $new_href) = @_ ;
|
1392
|
|
|
|
|
|
|
|
1393
|
14
|
|
50
|
|
|
34
|
$base_href ||= {} ;
|
1394
|
14
|
50
|
|
|
|
35
|
croak "Error: cannot copy HASH because destination is not a HASH ref" if ref($new_href) ne 'HASH' ;
|
1395
|
|
|
|
|
|
|
|
1396
|
14
|
|
|
|
|
41
|
foreach my $key (keys %$base_href)
|
1397
|
|
|
|
|
|
|
{
|
1398
|
79
|
|
|
|
|
101
|
my $val = $base_href->{$key} ;
|
1399
|
79
|
100
|
|
|
|
125
|
if (ref($val) eq 'HASH')
|
1400
|
|
|
|
|
|
|
{
|
1401
|
|
|
|
|
|
|
# copy HASH entries
|
1402
|
39
|
|
100
|
|
|
126
|
$new_href->{$key} ||= {} ;
|
1403
|
39
|
|
|
|
|
425
|
$new_href->{$key} = {
|
1404
|
39
|
|
|
|
|
40
|
%{$new_href->{$key}},
|
1405
|
|
|
|
|
|
|
%$val
|
1406
|
|
|
|
|
|
|
};
|
1407
|
|
|
|
|
|
|
}
|
1408
|
|
|
|
|
|
|
else
|
1409
|
|
|
|
|
|
|
{
|
1410
|
|
|
|
|
|
|
# scalar
|
1411
|
40
|
|
|
|
|
120
|
$new_href->{$key} = $val ;
|
1412
|
|
|
|
|
|
|
}
|
1413
|
|
|
|
|
|
|
}
|
1414
|
|
|
|
|
|
|
}
|
1415
|
|
|
|
|
|
|
|
1416
|
|
|
|
|
|
|
#---------------------------------------------------------------------------------
|
1417
|
|
|
|
|
|
|
# Copy key values from one hash into another. Skips any HASH entries
|
1418
|
|
|
|
|
|
|
sub _hash_copy_shallow
|
1419
|
|
|
|
|
|
|
{
|
1420
|
0
|
|
|
0
|
|
0
|
my ($base_href, $new_href) = @_ ;
|
1421
|
|
|
|
|
|
|
|
1422
|
0
|
|
0
|
|
|
0
|
$base_href ||= {} ;
|
1423
|
|
|
|
|
|
|
|
1424
|
0
|
0
|
|
|
|
0
|
croak "Error: cannot copy HASH because destination is not a HASH ref" if ref($new_href) ne 'HASH' ;
|
1425
|
|
|
|
|
|
|
|
1426
|
0
|
|
|
|
|
0
|
foreach my $key (keys %$base_href)
|
1427
|
|
|
|
|
|
|
{
|
1428
|
0
|
|
|
|
|
0
|
my $val = $base_href->{$key} ;
|
1429
|
0
|
0
|
|
|
|
0
|
if (!ref($val))
|
1430
|
|
|
|
|
|
|
{
|
1431
|
|
|
|
|
|
|
# scalar
|
1432
|
0
|
|
|
|
|
0
|
$new_href->{$key} = $val ;
|
1433
|
|
|
|
|
|
|
}
|
1434
|
|
|
|
|
|
|
}
|
1435
|
|
|
|
|
|
|
}
|
1436
|
|
|
|
|
|
|
|
1437
|
|
|
|
|
|
|
#---------------------------------------------------------------------------------
|
1438
|
|
|
|
|
|
|
# Convert template line into field/subvar
|
1439
|
|
|
|
|
|
|
sub _field_parse
|
1440
|
|
|
|
|
|
|
{
|
1441
|
0
|
|
|
0
|
|
0
|
my ($line) = @_ ;
|
1442
|
0
|
|
|
|
|
0
|
my ($field, $subvar) = ($line, '') ;
|
1443
|
|
|
|
|
|
|
|
1444
|
0
|
0
|
|
|
|
0
|
if ($field =~ /(\w+)\.(.*)/)
|
1445
|
|
|
|
|
|
|
{
|
1446
|
0
|
|
|
|
|
0
|
($field, $subvar) = ($1, $2) ;
|
1447
|
|
|
|
|
|
|
}
|
1448
|
0
|
|
|
|
|
0
|
return ($field, $subvar) ;
|
1449
|
|
|
|
|
|
|
}
|
1450
|
|
|
|
|
|
|
|
1451
|
|
|
|
|
|
|
#---------------------------------------------------------------------------------
|
1452
|
|
|
|
|
|
|
# Lookup the comment text for this field/subvar
|
1453
|
|
|
|
|
|
|
sub _lookup_comment
|
1454
|
|
|
|
|
|
|
{
|
1455
|
0
|
|
|
0
|
|
0
|
my ($field, $subvar) = @_ ;
|
1456
|
|
|
|
|
|
|
|
1457
|
0
|
|
|
|
|
0
|
my $comment = '' ;
|
1458
|
0
|
|
|
|
|
0
|
my $name = $field ;
|
1459
|
0
|
0
|
|
|
|
0
|
$name .= ".$subvar" if $subvar ;
|
1460
|
|
|
|
|
|
|
|
1461
|
0
|
0
|
0
|
|
|
0
|
if (exists($SETTINGS_COMMENTS{$name}))
|
|
|
0
|
|
|
|
|
|
1462
|
|
|
|
|
|
|
{
|
1463
|
|
|
|
|
|
|
## use specific comment
|
1464
|
0
|
|
|
|
|
0
|
$comment = $SETTINGS_COMMENTS{$name} ;
|
1465
|
|
|
|
|
|
|
}
|
1466
|
|
|
|
|
|
|
elsif ($subvar && exists($SETTINGS_COMMENTS{$subvar}))
|
1467
|
|
|
|
|
|
|
{
|
1468
|
|
|
|
|
|
|
## no specific comment, so use global
|
1469
|
0
|
|
|
|
|
0
|
$comment = $SETTINGS_COMMENTS{$subvar} ;
|
1470
|
|
|
|
|
|
|
}
|
1471
|
0
|
|
|
|
|
0
|
return $comment ;
|
1472
|
|
|
|
|
|
|
|
1473
|
|
|
|
|
|
|
}
|
1474
|
|
|
|
|
|
|
|
1475
|
|
|
|
|
|
|
|
1476
|
|
|
|
|
|
|
# ============================================================================================
|
1477
|
|
|
|
|
|
|
# From Linux::DVB::DVBT::Config
|
1478
|
|
|
|
|
|
|
# ============================================================================================
|
1479
|
|
|
|
|
|
|
|
1480
|
|
|
|
|
|
|
#----------------------------------------------------------------------
|
1481
|
|
|
|
|
|
|
|
1482
|
|
|
|
|
|
|
=item B
|
1483
|
|
|
|
|
|
|
|
1484
|
|
|
|
|
|
|
Find directories to read from - all readable directories in search path
|
1485
|
|
|
|
|
|
|
|
1486
|
|
|
|
|
|
|
=cut
|
1487
|
|
|
|
|
|
|
|
1488
|
|
|
|
|
|
|
sub read_dir
|
1489
|
|
|
|
|
|
|
{
|
1490
|
5
|
|
|
5
|
1
|
8
|
my ($search_path, $fname) = @_ ;
|
1491
|
|
|
|
|
|
|
|
1492
|
5
|
|
|
|
|
17
|
my @dirs = _expand_search_path($search_path) ;
|
1493
|
|
|
|
|
|
|
# my $dir ;
|
1494
|
|
|
|
|
|
|
|
1495
|
5
|
|
|
|
|
11
|
my @found = () ;
|
1496
|
5
|
|
|
|
|
11
|
foreach my $d (@dirs)
|
1497
|
|
|
|
|
|
|
{
|
1498
|
6
|
|
|
|
|
10
|
my $found=1 ;
|
1499
|
6
|
100
|
|
|
|
235
|
if (! -f "$d/$fname")
|
1500
|
|
|
|
|
|
|
{
|
1501
|
|
|
|
|
|
|
## can't find file, so mark as invalid directory
|
1502
|
1
|
|
|
|
|
2
|
$found=0 ;
|
1503
|
|
|
|
|
|
|
}
|
1504
|
|
|
|
|
|
|
|
1505
|
6
|
100
|
|
|
|
17
|
if ($found)
|
1506
|
|
|
|
|
|
|
{
|
1507
|
|
|
|
|
|
|
# $dir = $d ;
|
1508
|
|
|
|
|
|
|
# last ;
|
1509
|
5
|
|
|
|
|
84
|
push @found, $d ;
|
1510
|
|
|
|
|
|
|
}
|
1511
|
|
|
|
|
|
|
}
|
1512
|
|
|
|
|
|
|
|
1513
|
5
|
100
|
|
|
|
17
|
@found = ('.') unless @found ;
|
1514
|
5
|
50
|
|
|
|
992
|
print "Searched [ @$search_path ] : read dir=@found\n" if $DEBUG ;
|
1515
|
|
|
|
|
|
|
|
1516
|
|
|
|
|
|
|
# return $dir ;
|
1517
|
5
|
|
|
|
|
24
|
return @found ;
|
1518
|
|
|
|
|
|
|
}
|
1519
|
|
|
|
|
|
|
|
1520
|
|
|
|
|
|
|
#----------------------------------------------------------------------
|
1521
|
|
|
|
|
|
|
|
1522
|
|
|
|
|
|
|
=item B
|
1523
|
|
|
|
|
|
|
|
1524
|
|
|
|
|
|
|
Find directory to write to - first writeable directory in search path
|
1525
|
|
|
|
|
|
|
|
1526
|
|
|
|
|
|
|
=cut
|
1527
|
|
|
|
|
|
|
|
1528
|
|
|
|
|
|
|
sub write_dir
|
1529
|
|
|
|
|
|
|
{
|
1530
|
0
|
|
|
0
|
1
|
0
|
my ($search_path, $fname) = @_ ;
|
1531
|
|
|
|
|
|
|
|
1532
|
0
|
|
|
|
|
0
|
my @dirs = _expand_search_path($search_path) ;
|
1533
|
0
|
|
|
|
|
0
|
my $dir ;
|
1534
|
|
|
|
|
|
|
|
1535
|
0
|
0
|
|
|
|
0
|
print STDERR "Find dir to write to from $search_path ...\n" if $DEBUG ;
|
1536
|
|
|
|
|
|
|
|
1537
|
0
|
|
|
|
|
0
|
foreach my $d (@dirs)
|
1538
|
|
|
|
|
|
|
{
|
1539
|
0
|
|
|
|
|
0
|
my $found=1 ;
|
1540
|
|
|
|
|
|
|
|
1541
|
0
|
0
|
|
|
|
0
|
print STDERR " + processing $d\n" if $DEBUG ;
|
1542
|
|
|
|
|
|
|
|
1543
|
|
|
|
|
|
|
# See if dir exists
|
1544
|
0
|
0
|
|
|
|
0
|
if (!-d $d)
|
1545
|
|
|
|
|
|
|
{
|
1546
|
|
|
|
|
|
|
# See if this user can create the dir
|
1547
|
0
|
|
|
|
|
0
|
eval {
|
1548
|
0
|
|
|
|
|
0
|
mkpath([$d], $DEBUG, 0755) ;
|
1549
|
|
|
|
|
|
|
};
|
1550
|
0
|
0
|
|
|
|
0
|
$found=0 if $@ ;
|
1551
|
|
|
|
|
|
|
|
1552
|
0
|
0
|
|
|
|
0
|
print STDERR " + $d does not exist - attempt to mkdir=$found\n" if $DEBUG ;
|
1553
|
|
|
|
|
|
|
}
|
1554
|
|
|
|
|
|
|
|
1555
|
0
|
0
|
|
|
|
0
|
if (-d $d)
|
1556
|
|
|
|
|
|
|
{
|
1557
|
0
|
0
|
|
|
|
0
|
print STDERR " + $d does exist ...\n" if $DEBUG ;
|
1558
|
|
|
|
|
|
|
|
1559
|
|
|
|
|
|
|
# See if this user can write to the dir
|
1560
|
0
|
0
|
|
|
|
0
|
if (open my $fh, ">>$d/$fname")
|
1561
|
|
|
|
|
|
|
{
|
1562
|
0
|
|
|
|
|
0
|
close $fh ;
|
1563
|
0
|
0
|
|
|
|
0
|
print STDERR " + + Write to $d/$fname succeded\n" if $DEBUG ;
|
1564
|
|
|
|
|
|
|
}
|
1565
|
|
|
|
|
|
|
else
|
1566
|
|
|
|
|
|
|
{
|
1567
|
0
|
0
|
|
|
|
0
|
print STDERR " + + Unable to write to $d/$fname - aborting this dir\n" if $DEBUG ;
|
1568
|
|
|
|
|
|
|
|
1569
|
0
|
|
|
|
|
0
|
$found = 0;
|
1570
|
|
|
|
|
|
|
}
|
1571
|
|
|
|
|
|
|
}
|
1572
|
|
|
|
|
|
|
|
1573
|
0
|
0
|
|
|
|
0
|
if ($found)
|
1574
|
|
|
|
|
|
|
{
|
1575
|
0
|
|
|
|
|
0
|
$dir = $d ;
|
1576
|
0
|
|
|
|
|
0
|
last ;
|
1577
|
|
|
|
|
|
|
}
|
1578
|
|
|
|
|
|
|
}
|
1579
|
|
|
|
|
|
|
|
1580
|
0
|
0
|
|
|
|
0
|
print STDERR "Searched $search_path : write dir=".($dir?$dir:"")."\n" if $DEBUG ;
|
|
|
0
|
|
|
|
|
|
1581
|
|
|
|
|
|
|
|
1582
|
0
|
|
|
|
|
0
|
return $dir ;
|
1583
|
|
|
|
|
|
|
}
|
1584
|
|
|
|
|
|
|
|
1585
|
|
|
|
|
|
|
|
1586
|
|
|
|
|
|
|
#----------------------------------------------------------------------
|
1587
|
|
|
|
|
|
|
# Split the search path & expand all the directories to absolute paths
|
1588
|
|
|
|
|
|
|
#
|
1589
|
|
|
|
|
|
|
sub _expand_search_path
|
1590
|
|
|
|
|
|
|
{
|
1591
|
5
|
|
|
5
|
|
9
|
my ($search_path) = @_ ;
|
1592
|
|
|
|
|
|
|
|
1593
|
5
|
|
|
|
|
13
|
my @dirs = @$search_path ;
|
1594
|
5
|
|
|
|
|
12
|
foreach my $d (@dirs)
|
1595
|
|
|
|
|
|
|
{
|
1596
|
|
|
|
|
|
|
# Replace any '~' with $HOME
|
1597
|
6
|
|
|
|
|
13
|
$d =~ s/~/\$HOME/g ;
|
1598
|
|
|
|
|
|
|
|
1599
|
|
|
|
|
|
|
# Now replace any vars with values from the environment
|
1600
|
6
|
|
|
|
|
10
|
$d =~ s/\$(\w+)/$ENV{$1}/ge ;
|
|
0
|
|
|
|
|
0
|
|
1601
|
|
|
|
|
|
|
|
1602
|
|
|
|
|
|
|
# Ensure path is clean
|
1603
|
6
|
|
|
|
|
220
|
$d = File::Spec->rel2abs($d) ;
|
1604
|
|
|
|
|
|
|
}
|
1605
|
|
|
|
|
|
|
|
1606
|
5
|
|
|
|
|
16
|
return @dirs ;
|
1607
|
|
|
|
|
|
|
}
|
1608
|
|
|
|
|
|
|
|
1609
|
|
|
|
|
|
|
|
1610
|
|
|
|
|
|
|
#----------------------------------------------------------------------
|
1611
|
|
|
|
|
|
|
#
|
1612
|
|
|
|
|
|
|
sub _channel_search
|
1613
|
|
|
|
|
|
|
{
|
1614
|
0
|
|
|
0
|
|
|
my ($channel_name, $search_href) = @_ ;
|
1615
|
|
|
|
|
|
|
|
1616
|
0
|
|
|
|
|
|
my $found_channel_name ;
|
1617
|
|
|
|
|
|
|
|
1618
|
|
|
|
|
|
|
# start by just seeing if it's the correct name...
|
1619
|
0
|
0
|
|
|
|
|
if (exists($search_href->{$channel_name}))
|
1620
|
|
|
|
|
|
|
{
|
1621
|
0
|
|
|
|
|
|
return $channel_name ;
|
1622
|
|
|
|
|
|
|
}
|
1623
|
|
|
|
|
|
|
else
|
1624
|
|
|
|
|
|
|
{
|
1625
|
|
|
|
|
|
|
## Otherwise, try finding variations on the channel name
|
1626
|
0
|
|
|
|
|
|
my %search ;
|
1627
|
|
|
|
|
|
|
|
1628
|
0
|
|
|
|
|
|
$channel_name = lc $channel_name ;
|
1629
|
|
|
|
|
|
|
|
1630
|
|
|
|
|
|
|
# lower-case, no spaces
|
1631
|
0
|
|
|
|
|
|
my $srch = $channel_name ;
|
1632
|
0
|
|
|
|
|
|
$srch =~ s/\s+//g ;
|
1633
|
0
|
|
|
|
|
|
$search{$srch}=1 ;
|
1634
|
|
|
|
|
|
|
|
1635
|
|
|
|
|
|
|
# lower-case, replaced words with numbers, no spaces
|
1636
|
0
|
|
|
|
|
|
$srch = $channel_name ;
|
1637
|
0
|
|
|
|
|
|
foreach my $num (keys %NUMERALS)
|
1638
|
|
|
|
|
|
|
{
|
1639
|
0
|
|
|
|
|
|
$srch =~ s/\b($num)\b/$NUMERALS{$num}/ge ;
|
|
0
|
|
|
|
|
|
|
1640
|
|
|
|
|
|
|
}
|
1641
|
0
|
|
|
|
|
|
$srch =~ s/\s+//g ;
|
1642
|
0
|
|
|
|
|
|
$search{$srch}=1 ;
|
1643
|
|
|
|
|
|
|
|
1644
|
|
|
|
|
|
|
# lower-case, replaced numbers with words, no spaces
|
1645
|
0
|
|
|
|
|
|
$srch = $channel_name ;
|
1646
|
0
|
|
|
|
|
|
foreach my $num (keys %NUMERALS)
|
1647
|
|
|
|
|
|
|
{
|
1648
|
0
|
0
|
|
|
|
|
print STDERR " -- $srch - replace $NUMERALS{$num} with $num..\n" if $DEBUG>3 ;
|
1649
|
0
|
|
|
|
|
|
$srch =~ s/($NUMERALS{$num})\b/$num/ge ;
|
|
0
|
|
|
|
|
|
|
1650
|
0
|
0
|
|
|
|
|
print STDERR " -- -- $srch\n" if $DEBUG>3 ;
|
1651
|
|
|
|
|
|
|
}
|
1652
|
0
|
|
|
|
|
|
$srch =~ s/\s+//g ;
|
1653
|
0
|
|
|
|
|
|
$search{$srch}=1 ;
|
1654
|
|
|
|
|
|
|
|
1655
|
0
|
0
|
|
|
|
|
print STDERR " + Searching tuning info [", keys %search, "]...\n" if $DEBUG>2 ;
|
1656
|
|
|
|
|
|
|
|
1657
|
0
|
|
|
|
|
|
foreach my $chan (keys %$search_href)
|
1658
|
|
|
|
|
|
|
{
|
1659
|
0
|
|
|
|
|
|
my $srch_chan = lc $chan ;
|
1660
|
0
|
|
|
|
|
|
$srch_chan =~ s/\s+//g ;
|
1661
|
|
|
|
|
|
|
|
1662
|
0
|
|
|
|
|
|
foreach my $search (keys %search)
|
1663
|
|
|
|
|
|
|
{
|
1664
|
0
|
0
|
|
|
|
|
print STDERR " + + checking $search against $srch_chan \n" if $DEBUG>2 ;
|
1665
|
0
|
0
|
|
|
|
|
if ($srch_chan eq $search)
|
1666
|
|
|
|
|
|
|
{
|
1667
|
0
|
|
|
|
|
|
$found_channel_name = $chan ;
|
1668
|
0
|
0
|
|
|
|
|
print STDERR " + found $channel_name\n" if $DEBUG ;
|
1669
|
0
|
|
|
|
|
|
last ;
|
1670
|
|
|
|
|
|
|
}
|
1671
|
|
|
|
|
|
|
}
|
1672
|
|
|
|
|
|
|
|
1673
|
0
|
0
|
|
|
|
|
last if $found_channel_name ;
|
1674
|
|
|
|
|
|
|
}
|
1675
|
|
|
|
|
|
|
}
|
1676
|
|
|
|
|
|
|
|
1677
|
0
|
|
|
|
|
|
return $found_channel_name ;
|
1678
|
|
|
|
|
|
|
}
|
1679
|
|
|
|
|
|
|
|
1680
|
|
|
|
|
|
|
# ============================================================================================
|
1681
|
|
|
|
|
|
|
# END OF PACKAGE
|
1682
|
|
|
|
|
|
|
|
1683
|
|
|
|
|
|
|
=back
|
1684
|
|
|
|
|
|
|
|
1685
|
|
|
|
|
|
|
=cut
|
1686
|
|
|
|
|
|
|
|
1687
|
|
|
|
|
|
|
1;
|
1688
|
|
|
|
|
|
|
|