1
|
/*
|
2
|
* Tvheadend - Linux DVB Network
|
3
|
*
|
4
|
* Copyright (C) 2013 Adam Sutton
|
5
|
*
|
6
|
* This program is free software: you can redistribute it and/or modify
|
7
|
* it under the terms of the GNU General Public License as published by
|
8
|
* the Free Software Foundation, either version 3 of the License, or
|
9
|
* (at your option) any later version.
|
10
|
*
|
11
|
* This program is distributed in the hope that it will be useful,
|
12
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
13
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
14
|
* GNU General Public License for more details.
|
15
|
*
|
16
|
* You should have received a copy of the GNU General Public License
|
17
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
18
|
*/
|
19
|
|
20
|
#include "tvheadend.h"
|
21
|
#include "input.h"
|
22
|
#include "queue.h"
|
23
|
#include "settings.h"
|
24
|
#include "mpegts_dvb.h"
|
25
|
#include "linuxdvb/linuxdvb_private.h"
|
26
|
#include "dvb_charset.h"
|
27
|
#include "config.h"
|
28
|
#include "scanfile.h"
|
29
|
|
30
|
#include <sys/types.h>
|
31
|
#include <sys/ioctl.h>
|
32
|
#include <unistd.h>
|
33
|
#include <stdlib.h>
|
34
|
#include <dirent.h>
|
35
|
#include <fcntl.h>
|
36
|
|
37
|
/* ****************************************************************************
|
38
|
* Class definition
|
39
|
* ***************************************************************************/
|
40
|
|
41
|
extern const idclass_t mpegts_network_class;
|
42
|
|
43
|
static void
|
44
|
dvb_network_class_delete ( idnode_t *in )
|
45
|
{
|
46
|
mpegts_network_t *mn = (mpegts_network_t*)in;
|
47
|
char ubuf[UUID_HEX_SIZE];
|
48
|
|
49
|
/* remove config */
|
50
|
hts_settings_remove("input/dvb/networks/%s",
|
51
|
idnode_uuid_as_str(in, ubuf));
|
52
|
|
53
|
/* Parent delete */
|
54
|
mpegts_network_delete(mn, 1);
|
55
|
}
|
56
|
|
57
|
static const void *
|
58
|
dvb_network_class_scanfile_get ( void *o )
|
59
|
{
|
60
|
prop_ptr = NULL;
|
61
|
return &prop_ptr;
|
62
|
}
|
63
|
|
64
|
void
|
65
|
dvb_network_scanfile_set ( dvb_network_t *ln, const char *id )
|
66
|
{
|
67
|
dvb_mux_conf_t *dmc;
|
68
|
scanfile_network_t *sfn;
|
69
|
dvb_mux_t *mm;
|
70
|
|
71
|
/* Find */
|
72
|
if (!id)
|
73
|
return;
|
74
|
if (!(sfn = scanfile_find(id)))
|
75
|
return;
|
76
|
|
77
|
/* Set satellite position */
|
78
|
if (sfn->sfn_satpos != INT_MAX && ln->mn_satpos == INT_MAX)
|
79
|
ln->mn_satpos = sfn->sfn_satpos;
|
80
|
|
81
|
/* Create */
|
82
|
LIST_FOREACH(dmc, &sfn->sfn_muxes, dmc_link) {
|
83
|
if (!(mm = dvb_network_find_mux(ln, dmc, MPEGTS_ONID_NONE, MPEGTS_TSID_NONE, 0, 0))) {
|
84
|
mm = dvb_mux_create0(ln, MPEGTS_ONID_NONE, MPEGTS_TSID_NONE,
|
85
|
dmc, NULL, NULL);
|
86
|
if (mm) {
|
87
|
mpegts_mux_post_create((mpegts_mux_t *)mm);
|
88
|
idnode_changed(&mm->mm_id);
|
89
|
}
|
90
|
if (tvhtrace_enabled()) {
|
91
|
char buf[128];
|
92
|
dvb_mux_conf_str(dmc, buf, sizeof(buf));
|
93
|
tvhtrace(LS_SCANFILE, "mux %p %s added to network %s", mm, buf, ln->mn_network_name);
|
94
|
}
|
95
|
} else {
|
96
|
if (tvhtrace_enabled()) {
|
97
|
char buf[128];
|
98
|
dvb_mux_conf_str(dmc, buf, sizeof(buf));
|
99
|
tvhtrace(LS_SCANFILE, "mux %p skipped %s in network %s", mm, buf, ln->mn_network_name);
|
100
|
dvb_mux_conf_str(&((dvb_mux_t *)mm)->lm_tuning, buf, sizeof(buf));
|
101
|
tvhtrace(LS_SCANFILE, "mux %p exists %s in network %s", mm, buf, ln->mn_network_name);
|
102
|
}
|
103
|
}
|
104
|
}
|
105
|
scanfile_clean(sfn);
|
106
|
return;
|
107
|
}
|
108
|
|
109
|
static int
|
110
|
dvb_network_class_scanfile_set ( void *o, const void *s )
|
111
|
{
|
112
|
dvb_network_scanfile_set(o, s);
|
113
|
return 0;
|
114
|
}
|
115
|
|
116
|
static htsmsg_t *
|
117
|
dvb_network_class_scanfile_list0
|
118
|
( const idclass_t *clazz, dvb_network_t *ln, const char *lang )
|
119
|
{
|
120
|
const char *type;
|
121
|
|
122
|
if (clazz == NULL)
|
123
|
return NULL;
|
124
|
htsmsg_t *e, *m = htsmsg_create_map();
|
125
|
htsmsg_add_str(m, "type", "api");
|
126
|
htsmsg_add_str(m, "uri", "dvb/scanfile/list");
|
127
|
htsmsg_add_str(m, "stype", "none");
|
128
|
e = htsmsg_create_map();
|
129
|
if (clazz == &dvb_network_dvbt_class)
|
130
|
type = "dvbt";
|
131
|
else if (clazz == &dvb_network_dvbc_class)
|
132
|
type = "dvbc";
|
133
|
else if (clazz == &dvb_network_dvbs_class)
|
134
|
type = "dvbs";
|
135
|
else if (clazz == &dvb_network_atsc_t_class)
|
136
|
type = "atsc-t";
|
137
|
else if (clazz == &dvb_network_atsc_c_class)
|
138
|
type = "atsc-c";
|
139
|
else if (clazz == &dvb_network_isdb_t_class)
|
140
|
type = "isdb-t";
|
141
|
else if (clazz == &dvb_network_isdb_c_class)
|
142
|
type = "isdb-c";
|
143
|
else if (clazz == &dvb_network_isdb_s_class)
|
144
|
type = "isdb-s";
|
145
|
else if (clazz == &dvb_network_dtmb_class)
|
146
|
type = "dtmb";
|
147
|
else if (clazz == &dvb_network_dab_class)
|
148
|
type = "dab";
|
149
|
else
|
150
|
type = "unk";
|
151
|
htsmsg_add_str(e, "type", type);
|
152
|
if (ln && ln->mn_satpos != INT_MAX)
|
153
|
htsmsg_add_s32(e, "satpos", ln->mn_satpos);
|
154
|
htsmsg_add_msg(m, "params", e);
|
155
|
return m;
|
156
|
}
|
157
|
|
158
|
htsmsg_t *
|
159
|
dvb_network_class_scanfile_list ( void *o, const char *lang )
|
160
|
{
|
161
|
if (o == NULL)
|
162
|
return NULL;
|
163
|
return dvb_network_class_scanfile_list0(((mpegts_network_t *)o)->mn_id.in_class, o, lang);
|
164
|
}
|
165
|
|
166
|
#define SCANFILE_LIST(name) \
|
167
|
static htsmsg_t * \
|
168
|
dvb_network_class_scanfile_list_##name ( void *o, const char *lang ) \
|
169
|
{ \
|
170
|
return dvb_network_class_scanfile_list0(&dvb_network_##name##_class, o, lang); \
|
171
|
}
|
172
|
|
173
|
SCANFILE_LIST(dvbt);
|
174
|
SCANFILE_LIST(dvbc);
|
175
|
SCANFILE_LIST(dvbs);
|
176
|
SCANFILE_LIST(atsc_t);
|
177
|
SCANFILE_LIST(atsc_c);
|
178
|
SCANFILE_LIST(isdb_t);
|
179
|
SCANFILE_LIST(isdb_c);
|
180
|
SCANFILE_LIST(isdb_s);
|
181
|
SCANFILE_LIST(dtmb);
|
182
|
SCANFILE_LIST(dab);
|
183
|
|
184
|
static const void *
|
185
|
dvb_network_class_orbital_pos_get ( void *o )
|
186
|
{
|
187
|
dvb_network_t *ln = o;
|
188
|
prop_sbuf[0] = '\0';
|
189
|
if (ln->mn_satpos != INT_MAX)
|
190
|
dvb_sat_position_to_str(ln->mn_satpos, prop_sbuf, PROP_SBUF_LEN);
|
191
|
return &prop_sbuf_ptr;
|
192
|
}
|
193
|
|
194
|
static int
|
195
|
dvb_network_class_orbital_pos_set ( void *o, const void *s )
|
196
|
{
|
197
|
dvb_network_t *ln = o;
|
198
|
int satpos;
|
199
|
|
200
|
/* Find */
|
201
|
if (!s)
|
202
|
return 0;
|
203
|
|
204
|
satpos = dvb_sat_position_from_str(s);
|
205
|
if (satpos != ln->mn_satpos) {
|
206
|
ln->mn_satpos = satpos;
|
207
|
return 1;
|
208
|
}
|
209
|
|
210
|
return 0;
|
211
|
}
|
212
|
|
213
|
static htsmsg_t *
|
214
|
dvb_network_class_orbital_pos_list ( void *o, const char *lang )
|
215
|
{
|
216
|
htsmsg_t *e, *m = htsmsg_create_map();
|
217
|
htsmsg_add_str(m, "type", "api");
|
218
|
htsmsg_add_str(m, "uri", "dvb/orbitalpos/list");
|
219
|
htsmsg_add_str(m, "stype", "none");
|
220
|
e = htsmsg_create_map();
|
221
|
htsmsg_add_msg(m, "params", e);
|
222
|
return m;
|
223
|
}
|
224
|
|
225
|
PROP_DOC(predefinedmuxlist)
|
226
|
|
227
|
const idclass_t dvb_network_class =
|
228
|
{
|
229
|
.ic_super = &mpegts_network_class,
|
230
|
.ic_class = "dvb_network",
|
231
|
.ic_caption = N_("LinuxDVB network"),
|
232
|
.ic_delete = dvb_network_class_delete,
|
233
|
.ic_properties = (const property_t[]){
|
234
|
{}
|
235
|
}
|
236
|
};
|
237
|
|
238
|
const idclass_t dvb_network_dvbt_class =
|
239
|
{
|
240
|
.ic_super = &dvb_network_class,
|
241
|
.ic_class = "dvb_network_dvbt",
|
242
|
.ic_caption = N_("DVB-T Network"),
|
243
|
.ic_properties = (const property_t[]) {
|
244
|
{
|
245
|
.type = PT_STR,
|
246
|
.id = "scanfile",
|
247
|
.name = N_("Pre-defined muxes"),
|
248
|
.desc = N_("Use a pre-defined list of DVB-T muxes. "
|
249
|
"Note: these lists can sometimes be outdated and "
|
250
|
"may cause scanning to take longer than usual."),
|
251
|
.doc = prop_doc_predefinedmuxlist,
|
252
|
.set = dvb_network_class_scanfile_set,
|
253
|
.get = dvb_network_class_scanfile_get,
|
254
|
.list = dvb_network_class_scanfile_list_dvbt,
|
255
|
.opts = PO_NOSAVE,
|
256
|
},
|
257
|
{}
|
258
|
}
|
259
|
};
|
260
|
|
261
|
const idclass_t dvb_network_dvbc_class =
|
262
|
{
|
263
|
.ic_super = &dvb_network_class,
|
264
|
.ic_class = "dvb_network_dvbc",
|
265
|
.ic_caption = N_("DVB-C Network"),
|
266
|
.ic_properties = (const property_t[]) {
|
267
|
{
|
268
|
.type = PT_STR,
|
269
|
.id = "scanfile",
|
270
|
.name = N_("Pre-defined muxes"),
|
271
|
.desc = N_("Use a pre-defined list of DVB-C muxes. "
|
272
|
"Note: these lists can sometimes be outdated and "
|
273
|
"may cause scanning to take longer than usual."),
|
274
|
.doc = prop_doc_predefinedmuxlist,
|
275
|
.set = dvb_network_class_scanfile_set,
|
276
|
.get = dvb_network_class_scanfile_get,
|
277
|
.list = dvb_network_class_scanfile_list_dvbc,
|
278
|
.opts = PO_NOSAVE,
|
279
|
},
|
280
|
{}
|
281
|
}
|
282
|
};
|
283
|
|
284
|
const idclass_t dvb_network_dvbs_class =
|
285
|
{
|
286
|
.ic_super = &dvb_network_class,
|
287
|
.ic_class = "dvb_network_dvbs",
|
288
|
.ic_caption = N_("DVB-S Network"),
|
289
|
.ic_properties = (const property_t[]) {
|
290
|
{
|
291
|
.type = PT_STR,
|
292
|
.id = "scanfile",
|
293
|
.name = N_("Pre-defined muxes"),
|
294
|
.desc = N_("Use a pre-defined list of DVB-S/S2 muxes. "
|
295
|
"Note: these lists can sometimes be outdated and "
|
296
|
"may cause scanning to take longer than usual."),
|
297
|
.doc = prop_doc_predefinedmuxlist,
|
298
|
.set = dvb_network_class_scanfile_set,
|
299
|
.get = dvb_network_class_scanfile_get,
|
300
|
.list = dvb_network_class_scanfile_list_dvbs,
|
301
|
.opts = PO_NOSAVE,
|
302
|
},
|
303
|
{
|
304
|
.type = PT_STR,
|
305
|
.id = "orbital_pos",
|
306
|
.name = N_("Orbital position"),
|
307
|
.desc = N_("The orbital position of the satellite "
|
308
|
"your dish is pointing at."),
|
309
|
.set = dvb_network_class_orbital_pos_set,
|
310
|
.get = dvb_network_class_orbital_pos_get,
|
311
|
.list = dvb_network_class_orbital_pos_list,
|
312
|
},
|
313
|
{}
|
314
|
}
|
315
|
};
|
316
|
|
317
|
const idclass_t dvb_network_atsc_t_class =
|
318
|
{
|
319
|
.ic_super = &dvb_network_class,
|
320
|
.ic_class = "dvb_network_atsc_t",
|
321
|
.ic_caption = N_("ATSC-T Network"),
|
322
|
.ic_properties = (const property_t[]) {
|
323
|
{
|
324
|
.type = PT_STR,
|
325
|
.id = "scanfile",
|
326
|
.name = N_("Pre-defined muxes"),
|
327
|
.desc = N_("Use a pre-defined list of ATSC-T muxes. "
|
328
|
"Note: these lists can sometimes be outdated and "
|
329
|
"may cause scanning to take longer than usual."),
|
330
|
.doc = prop_doc_predefinedmuxlist,
|
331
|
.set = dvb_network_class_scanfile_set,
|
332
|
.get = dvb_network_class_scanfile_get,
|
333
|
.list = dvb_network_class_scanfile_list_atsc_t,
|
334
|
.opts = PO_NOSAVE,
|
335
|
},
|
336
|
{}
|
337
|
}
|
338
|
};
|
339
|
|
340
|
const idclass_t dvb_network_atsc_c_class =
|
341
|
{
|
342
|
.ic_super = &dvb_network_class,
|
343
|
.ic_class = "dvb_network_atsc_c",
|
344
|
.ic_caption = N_("ATSC-C Network"),
|
345
|
.ic_properties = (const property_t[]) {
|
346
|
{
|
347
|
.type = PT_STR,
|
348
|
.id = "scanfile",
|
349
|
.name = N_("Pre-defined muxes"),
|
350
|
.desc = N_("Use a pre-defined list of ATSC-C muxes. "
|
351
|
"Note: these lists can sometimes be outdated and "
|
352
|
"may cause scanning to take longer than usual."),
|
353
|
.doc = prop_doc_predefinedmuxlist,
|
354
|
.set = dvb_network_class_scanfile_set,
|
355
|
.get = dvb_network_class_scanfile_get,
|
356
|
.list = dvb_network_class_scanfile_list_atsc_c,
|
357
|
.opts = PO_NOSAVE,
|
358
|
},
|
359
|
{}
|
360
|
}
|
361
|
};
|
362
|
|
363
|
const idclass_t dvb_network_cablecard_class =
|
364
|
{
|
365
|
.ic_super = &dvb_network_class,
|
366
|
.ic_class = "dvb_network_cablecard",
|
367
|
.ic_caption = N_("CableCARD Network"),
|
368
|
.ic_properties = (const property_t[]){
|
369
|
{}
|
370
|
}
|
371
|
};
|
372
|
|
373
|
const idclass_t dvb_network_isdb_t_class =
|
374
|
{
|
375
|
.ic_super = &dvb_network_class,
|
376
|
.ic_class = "dvb_network_isdb_t",
|
377
|
.ic_caption = N_("ISDB-T Network"),
|
378
|
.ic_properties = (const property_t[]) {
|
379
|
{
|
380
|
.type = PT_STR,
|
381
|
.id = "scanfile",
|
382
|
.name = N_("Pre-defined muxes"),
|
383
|
.desc = N_("Use a pre-defined list of ISDB-T muxes. "
|
384
|
"Note: these lists can sometimes be outdated and "
|
385
|
"may cause scanning to take longer than usual."),
|
386
|
.doc = prop_doc_predefinedmuxlist,
|
387
|
.set = dvb_network_class_scanfile_set,
|
388
|
.get = dvb_network_class_scanfile_get,
|
389
|
.list = dvb_network_class_scanfile_list_isdb_t,
|
390
|
.opts = PO_NOSAVE,
|
391
|
},
|
392
|
{}
|
393
|
}
|
394
|
};
|
395
|
|
396
|
const idclass_t dvb_network_isdb_c_class =
|
397
|
{
|
398
|
.ic_super = &dvb_network_class,
|
399
|
.ic_class = "dvb_network_isdb_c",
|
400
|
.ic_caption = N_("ISDB-C Network"),
|
401
|
.ic_properties = (const property_t[]) {
|
402
|
{
|
403
|
.type = PT_STR,
|
404
|
.id = "scanfile",
|
405
|
.name = N_("Pre-defined muxes"),
|
406
|
.desc = N_("Use a pre-defined list of ISDB-C muxes. "
|
407
|
"Note: these lists can sometimes be outdated and "
|
408
|
"may cause scanning to take longer than usual."),
|
409
|
.doc = prop_doc_predefinedmuxlist,
|
410
|
.set = dvb_network_class_scanfile_set,
|
411
|
.get = dvb_network_class_scanfile_get,
|
412
|
.list = dvb_network_class_scanfile_list_isdb_c,
|
413
|
.opts = PO_NOSAVE,
|
414
|
},
|
415
|
{}
|
416
|
}
|
417
|
};
|
418
|
|
419
|
const idclass_t dvb_network_isdb_s_class =
|
420
|
{
|
421
|
.ic_super = &dvb_network_class,
|
422
|
.ic_class = "dvb_network_isdb_s",
|
423
|
.ic_caption = N_("ISDB-S Network"),
|
424
|
.ic_properties = (const property_t[]) {
|
425
|
{
|
426
|
.type = PT_STR,
|
427
|
.id = "scanfile",
|
428
|
.name = N_("Pre-defined muxes"),
|
429
|
.desc = N_("Use a pre-defined list of ISDB-S muxes. "
|
430
|
"Note: these lists can sometimes be outdated and "
|
431
|
"may cause scanning to take longer than usual."),
|
432
|
.doc = prop_doc_predefinedmuxlist,
|
433
|
.set = dvb_network_class_scanfile_set,
|
434
|
.get = dvb_network_class_scanfile_get,
|
435
|
.list = dvb_network_class_scanfile_list_isdb_s,
|
436
|
.opts = PO_NOSAVE,
|
437
|
},
|
438
|
{}
|
439
|
}
|
440
|
};
|
441
|
|
442
|
const idclass_t dvb_network_dtmb_class =
|
443
|
{
|
444
|
.ic_super = &dvb_network_class,
|
445
|
.ic_class = "dvb_network_dtmb",
|
446
|
.ic_caption = N_("DTMB Network"),
|
447
|
.ic_properties = (const property_t[]) {
|
448
|
{
|
449
|
.type = PT_STR,
|
450
|
.id = "scanfile",
|
451
|
.name = N_("Pre-defined muxes"),
|
452
|
.desc = N_("Use a pre-defined list of DTMB muxes. "
|
453
|
"Note: these lists can sometimes be outdated and "
|
454
|
"may cause scanning to take longer than usual."),
|
455
|
.doc = prop_doc_predefinedmuxlist,
|
456
|
.set = dvb_network_class_scanfile_set,
|
457
|
.get = dvb_network_class_scanfile_get,
|
458
|
.list = dvb_network_class_scanfile_list_dtmb,
|
459
|
.opts = PO_NOSAVE,
|
460
|
},
|
461
|
{}
|
462
|
}
|
463
|
};
|
464
|
|
465
|
const idclass_t dvb_network_dab_class =
|
466
|
{
|
467
|
.ic_super = &dvb_network_class,
|
468
|
.ic_class = "dvb_network_dab",
|
469
|
.ic_caption = N_("DAB Network"),
|
470
|
.ic_properties = (const property_t[]) {
|
471
|
{
|
472
|
.type = PT_STR,
|
473
|
.id = "scanfile",
|
474
|
.name = N_("Pre-defined muxes"),
|
475
|
.desc = N_("Use a pre-defined list of DAB muxes. "
|
476
|
"Note: these lists can sometimes be outdated and "
|
477
|
"may cause scanning to take longer than usual."),
|
478
|
.doc = prop_doc_predefinedmuxlist,
|
479
|
.set = dvb_network_class_scanfile_set,
|
480
|
.get = dvb_network_class_scanfile_get,
|
481
|
.list = dvb_network_class_scanfile_list_dab,
|
482
|
.opts = PO_NOSAVE,
|
483
|
},
|
484
|
{}
|
485
|
}
|
486
|
};
|
487
|
|
488
|
/* ****************************************************************************
|
489
|
* Class methods
|
490
|
* ***************************************************************************/
|
491
|
|
492
|
static int
|
493
|
dvb_network_check_bandwidth( int bw1, int bw2 )
|
494
|
{
|
495
|
if (bw1 == DVB_BANDWIDTH_NONE || bw1 == DVB_BANDWIDTH_AUTO ||
|
496
|
bw2 == DVB_BANDWIDTH_NONE || bw2 == DVB_BANDWIDTH_AUTO)
|
497
|
return 0;
|
498
|
return bw1 != bw2;
|
499
|
}
|
500
|
|
501
|
static int
|
502
|
dvb_network_check_symbol_rate( dvb_mux_t *lm, dvb_mux_conf_t *dmc, int deltar )
|
503
|
{
|
504
|
switch (dmc->dmc_fe_type) {
|
505
|
case DVB_TYPE_T:
|
506
|
case DVB_TYPE_DTMB:
|
507
|
return dvb_network_check_bandwidth(lm->lm_tuning.u.dmc_fe_ofdm.bandwidth,
|
508
|
dmc->u.dmc_fe_ofdm.bandwidth);
|
509
|
case DVB_TYPE_C:
|
510
|
case DVB_TYPE_ATSC_C:
|
511
|
return deltaU32(lm->lm_tuning.u.dmc_fe_qam.symbol_rate,
|
512
|
dmc->u.dmc_fe_qam.symbol_rate) > deltar;
|
513
|
case DVB_TYPE_S:
|
514
|
return deltaU32(lm->lm_tuning.u.dmc_fe_qpsk.symbol_rate,
|
515
|
dmc->u.dmc_fe_qpsk.symbol_rate) > deltar;
|
516
|
case DVB_TYPE_ATSC_T:
|
517
|
return 0;
|
518
|
default:
|
519
|
return 0;
|
520
|
}
|
521
|
}
|
522
|
|
523
|
static int
|
524
|
dvb_network_check_orbital_pos ( int satpos1, int satpos2 )
|
525
|
{
|
526
|
if (satpos1 != INT_MAX && satpos2 != INT_MAX) {
|
527
|
/* 1W and 0.8W */
|
528
|
if (abs(satpos1 - satpos2) > 2)
|
529
|
return 1;
|
530
|
}
|
531
|
return 0;
|
532
|
}
|
533
|
|
534
|
dvb_mux_t *
|
535
|
dvb_network_find_mux
|
536
|
( dvb_network_t *ln, dvb_mux_conf_t *dmc, uint16_t onid, uint16_t tsid, int check, int approx_match )
|
537
|
{
|
538
|
int deltaf, deltar;
|
539
|
mpegts_mux_t *mm, *mm_alt = NULL;
|
540
|
|
541
|
LIST_FOREACH(mm, &ln->mn_muxes, mm_network_link) {
|
542
|
|
543
|
if (check && mm->mm_enabled != MM_ENABLE) continue;
|
544
|
|
545
|
deltaf = 2000; // 2K/MHz
|
546
|
deltar = 1000;
|
547
|
dvb_mux_t *lm = (dvb_mux_t*)mm;
|
548
|
|
549
|
/* Same FE type - this REALLY should match! */
|
550
|
if (lm->lm_tuning.dmc_fe_type != dmc->dmc_fe_type) continue;
|
551
|
|
552
|
/* Also, the system type should match (DVB-S/DVB-S2) */
|
553
|
if (!approx_match && (lm->lm_tuning.dmc_fe_delsys != dmc->dmc_fe_delsys)) continue;
|
554
|
|
555
|
/* if ONID/TSID are a perfect match (and this is DVB-S, allow greater deltaf) */
|
556
|
if (lm->lm_tuning.dmc_fe_type == DVB_TYPE_S) {
|
557
|
deltar = 7000;
|
558
|
if (onid != MPEGTS_ONID_NONE && tsid != MPEGTS_TSID_NONE) {
|
559
|
deltaf = 16000; // This is slightly crazy, but I have seen 10MHz changes in freq
|
560
|
// and remember the ONID and TSID must agree
|
561
|
} else {
|
562
|
/* the freq. changes for lower symbol rates might be smaller */
|
563
|
deltaf = 4000;
|
564
|
if (dmc->u.dmc_fe_qpsk.symbol_rate < 5000000)
|
565
|
deltaf = 1900;
|
566
|
if (dmc->u.dmc_fe_qpsk.symbol_rate < 10000000)
|
567
|
deltaf = 2900;
|
568
|
}
|
569
|
}
|
570
|
|
571
|
/* Reject if not same frequency (some tolerance due to changes and diff in NIT) */
|
572
|
if (deltaU32(lm->lm_tuning.dmc_fe_freq, dmc->dmc_fe_freq) > deltaf) continue;
|
573
|
|
574
|
/* Reject if not same symbol rate (some tolerance due to changes and diff in NIT) */
|
575
|
if (dvb_network_check_symbol_rate(lm, dmc, deltar)) continue;
|
576
|
|
577
|
/* Reject if not same polarisation */
|
578
|
if (lm->lm_tuning.u.dmc_fe_qpsk.polarisation != dmc->u.dmc_fe_qpsk.polarisation) continue;
|
579
|
|
580
|
/* DVB-S extra checks */
|
581
|
if (!approx_match && (lm->lm_tuning.dmc_fe_type == DVB_TYPE_S)) {
|
582
|
|
583
|
/* Same modulation */
|
584
|
if (!dvb_modulation_is_none_or_auto(lm->lm_tuning.dmc_fe_modulation) &&
|
585
|
!dvb_modulation_is_none_or_auto(dmc->dmc_fe_modulation) &&
|
586
|
lm->lm_tuning.dmc_fe_modulation != dmc->dmc_fe_modulation) continue;
|
587
|
|
588
|
/* Same FEC */
|
589
|
if (lm->lm_tuning.u.dmc_fe_qpsk.fec_inner != dmc->u.dmc_fe_qpsk.fec_inner) continue;
|
590
|
|
591
|
/* Same orbital position */
|
592
|
if (dvb_network_check_orbital_pos(lm->lm_tuning.u.dmc_fe_qpsk.orbital_pos,
|
593
|
dmc->u.dmc_fe_qpsk.orbital_pos)) continue;
|
594
|
}
|
595
|
|
596
|
/* Same PLP/ISI */
|
597
|
if (lm->lm_tuning.dmc_fe_stream_id != dmc->dmc_fe_stream_id) continue;
|
598
|
|
599
|
mm_alt = mm;
|
600
|
|
601
|
/* Reject if not same ID */
|
602
|
if (onid != MPEGTS_ONID_NONE && mm->mm_onid != MPEGTS_ONID_NONE && mm->mm_onid != onid) continue;
|
603
|
if (tsid != MPEGTS_TSID_NONE && mm->mm_tsid != MPEGTS_TSID_NONE && mm->mm_tsid != tsid) continue;
|
604
|
|
605
|
break;
|
606
|
}
|
607
|
if (!mm && onid != MPEGTS_ONID_NONE && tsid != MPEGTS_TSID_NONE) {
|
608
|
/* use the mux with closest parameters */
|
609
|
/* unfortunately, the onid and tsid might DIFFER */
|
610
|
/* in the NIT table information and real mux feed */
|
611
|
mm = mm_alt;
|
612
|
}
|
613
|
return (dvb_mux_t *)mm;
|
614
|
}
|
615
|
|
616
|
static htsmsg_t *
|
617
|
dvb_network_config_save ( mpegts_network_t *mn, char *filename, size_t fsize )
|
618
|
{
|
619
|
htsmsg_t *c = htsmsg_create_map();
|
620
|
char ubuf[UUID_HEX_SIZE];
|
621
|
idnode_save(&mn->mn_id, c);
|
622
|
htsmsg_add_str(c, "class", mn->mn_id.in_class->ic_class);
|
623
|
if (filename)
|
624
|
snprintf(filename, fsize, "input/dvb/networks/%s/config",
|
625
|
idnode_uuid_as_str(&mn->mn_id, ubuf));
|
626
|
return c;
|
627
|
}
|
628
|
|
629
|
const idclass_t *
|
630
|
dvb_network_mux_class
|
631
|
( mpegts_network_t *mn )
|
632
|
{
|
633
|
if (idnode_is_instance(&mn->mn_id, &dvb_network_dvbt_class))
|
634
|
return &dvb_mux_dvbt_class;
|
635
|
if (idnode_is_instance(&mn->mn_id, &dvb_network_dvbc_class))
|
636
|
return &dvb_mux_dvbc_class;
|
637
|
if (idnode_is_instance(&mn->mn_id, &dvb_network_dvbs_class))
|
638
|
return &dvb_mux_dvbs_class;
|
639
|
if (idnode_is_instance(&mn->mn_id, &dvb_network_atsc_t_class))
|
640
|
return &dvb_mux_atsc_t_class;
|
641
|
if (idnode_is_instance(&mn->mn_id, &dvb_network_atsc_c_class))
|
642
|
return &dvb_mux_atsc_c_class;
|
643
|
if (idnode_is_instance(&mn->mn_id, &dvb_network_isdb_t_class))
|
644
|
return &dvb_mux_isdb_t_class;
|
645
|
if (idnode_is_instance(&mn->mn_id, &dvb_network_cablecard_class))
|
646
|
return &dvb_mux_cablecard_class;
|
647
|
if (idnode_is_instance(&mn->mn_id, &dvb_network_isdb_c_class))
|
648
|
return &dvb_mux_isdb_c_class;
|
649
|
if (idnode_is_instance(&mn->mn_id, &dvb_network_isdb_s_class))
|
650
|
return &dvb_mux_isdb_s_class;
|
651
|
if (idnode_is_instance(&mn->mn_id, &dvb_network_dtmb_class))
|
652
|
return &dvb_mux_dtmb_class;
|
653
|
if (idnode_is_instance(&mn->mn_id, &dvb_network_dab_class))
|
654
|
return &dvb_mux_dab_class;
|
655
|
return NULL;
|
656
|
}
|
657
|
|
658
|
#define CBIT_ORBITAL_POS (1<<0)
|
659
|
#define CBIT_POLARISATION (1<<1)
|
660
|
#define CBIT_FREQ (1<<2)
|
661
|
#define CBIT_RATE (1<<3)
|
662
|
#define CBIT_RATE_HP (1<<4)
|
663
|
#define CBIT_RATE_LP (1<<5)
|
664
|
#define CBIT_MODULATION (1<<6)
|
665
|
#define CBIT_INVERSION (1<<7)
|
666
|
#define CBIT_ROLLOFF (1<<8)
|
667
|
#define CBIT_PILOT (1<<9)
|
668
|
#define CBIT_STREAM_ID (1<<10)
|
669
|
#define CBIT_BANDWIDTH (1<<11)
|
670
|
#define CBIT_TRANS_MODE (1<<12)
|
671
|
#define CBIT_GUARD (1<<13)
|
672
|
#define CBIT_HIERARCHY (1<<14)
|
673
|
#define CBIT_PLS_MODE (1<<15)
|
674
|
#define CBIT_PLS_CODE (1<<16)
|
675
|
#define CBIT_FEC_INNER (1<<17)
|
676
|
|
677
|
static mpegts_mux_t *
|
678
|
dvb_network_create_mux
|
679
|
( mpegts_network_t *mn, void *origin, uint16_t onid, uint16_t tsid,
|
680
|
void *p, int force )
|
681
|
{
|
682
|
int save = 0, satpos;
|
683
|
dvb_mux_t *mm;
|
684
|
dvb_network_t *ln;
|
685
|
dvb_mux_conf_t *dmc = p;
|
686
|
const idclass_t *cls = dvb_network_mux_class(mn);
|
687
|
|
688
|
tvhinfo(LS_MPEGTS, "dvb create mux: onid %d tsid %d force %d", onid, tsid, force);
|
689
|
|
690
|
/* when forced - try to look also to another DVB-S networks */
|
691
|
if (force && cls == &dvb_mux_dvbs_class && dmc->dmc_fe_type == DVB_TYPE_S &&
|
692
|
dmc->u.dmc_fe_qpsk.orbital_pos != INT_MAX) {
|
693
|
satpos = dvb_network_get_orbital_pos(mn);
|
694
|
if (dvb_network_check_orbital_pos(satpos, dmc->u.dmc_fe_qpsk.orbital_pos)) {
|
695
|
LIST_FOREACH(mn, &mpegts_network_all, mn_global_link) {
|
696
|
if (!idnode_is_instance(&mn->mn_id, &dvb_network_dvbs_class)) continue;
|
697
|
satpos = dvb_network_get_orbital_pos(mn);
|
698
|
if (satpos == INT_MAX) continue;
|
699
|
if (!dvb_network_check_orbital_pos(satpos, dmc->u.dmc_fe_qpsk.orbital_pos))
|
700
|
break;
|
701
|
}
|
702
|
if (mn == NULL)
|
703
|
return NULL;
|
704
|
}
|
705
|
}
|
706
|
|
707
|
ln = (dvb_network_t*)mn;
|
708
|
mm = dvb_network_find_mux(ln, dmc, onid, tsid, 0, 0);
|
709
|
tvhdebug(LS_MPEGTS, "dvb create mux: mm %p discovery %d", mm, ln->mn_autodiscovery);
|
710
|
if (!mm && (ln->mn_autodiscovery != MN_DISCOVERY_DISABLE || force)) {
|
711
|
cls = dvb_network_mux_class((mpegts_network_t *)ln);
|
712
|
save |= dvb_fe_type_by_network_class(cls) == dmc->dmc_fe_type;
|
713
|
tvhdebug(LS_MPEGTS, "dvb create mux: network fe type %d dmc fe type %d", dvb_fe_type_by_network_class(cls), dmc->dmc_fe_type);
|
714
|
if (save && dmc->dmc_fe_type == DVB_TYPE_S) {
|
715
|
satpos = dvb_network_get_orbital_pos(mn);
|
716
|
/* do not allow to mix satellite positions */
|
717
|
if (dvb_network_check_orbital_pos(satpos, dmc->u.dmc_fe_qpsk.orbital_pos))
|
718
|
save = 0;
|
719
|
}
|
720
|
if (save) {
|
721
|
mm = dvb_mux_create0(ln, onid, tsid, dmc, NULL, NULL);
|
722
|
mpegts_mux_post_create((mpegts_mux_t *)mm);
|
723
|
if (tvhtrace_enabled()) {
|
724
|
char buf[128];
|
725
|
dvb_mux_conf_str(&((dvb_mux_t *)mm)->lm_tuning, buf, sizeof(buf));
|
726
|
tvhtrace(LS_MPEGTS, "mux %p %s onid %i tsid %i added to network %s (autodiscovery)",
|
727
|
mm, buf, onid, tsid, mm->mm_network->mn_network_name);
|
728
|
}
|
729
|
}
|
730
|
} else if (mm) {
|
731
|
char buf[128];
|
732
|
dvb_mux_conf_t tuning_new, tuning_old;
|
733
|
dvb_mux_t *lm = (dvb_mux_t*)mm;
|
734
|
int change = (ln->mn_autodiscovery == MN_DISCOVERY_CHANGE) || force;
|
735
|
/* the nit tables may be inconsistent (like rolloff ping-pong) */
|
736
|
/* accept information only from one origin mux */
|
737
|
if (mm->mm_dmc_origin_expire > mclk() && mm->mm_dmc_origin && mm->mm_dmc_origin != origin)
|
738
|
goto noop;
|
739
|
#define COMPARE(x, cbit) ({ \
|
740
|
int xr = dmc->x != lm->lm_tuning.x; \
|
741
|
if (xr) { \
|
742
|
tvhtrace(LS_MPEGTS, "create mux dmc->" #x " (%li) != lm->lm_tuning." #x \
|
743
|
" (%li)", (long)dmc->x, (long)tuning_new.x); \
|
744
|
tuning_new.x = dmc->x; \
|
745
|
} xr ? cbit : 0; })
|
746
|
#define COMPAREN(x, cbit) ({ \
|
747
|
int xr = dmc->x != 0 && dmc->x != 1 && dmc->x != tuning_new.x; \
|
748
|
if (xr) { \
|
749
|
tvhtrace(LS_MPEGTS, "create mux dmc->" #x " (%li) != lm->lm_tuning." #x \
|
750
|
" (%li)", (long)dmc->x, (long)tuning_new.x); \
|
751
|
tuning_new.x = dmc->x; \
|
752
|
} xr ? cbit : 0; })
|
753
|
#define COMPAREN0(x, cbit) ({ \
|
754
|
int xr = dmc->x != 1 && dmc->x != tuning_new.x; \
|
755
|
if (xr) { \
|
756
|
tvhtrace(LS_MPEGTS, "create mux dmc->" #x " (%li) != lm->lm_tuning." #x \
|
757
|
" (%li)", (long)dmc->x, (long)tuning_new.x); \
|
758
|
tuning_new.x = dmc->x; \
|
759
|
} xr ? cbit : 0; })
|
760
|
tuning_new = tuning_old = lm->lm_tuning;
|
761
|
/* Always save the orbital position */
|
762
|
if (dmc->dmc_fe_type == DVB_TYPE_S) {
|
763
|
if (dmc->u.dmc_fe_qpsk.orbital_pos == INT_MAX ||
|
764
|
dvb_network_check_orbital_pos(tuning_new.u.dmc_fe_qpsk.orbital_pos,
|
765
|
dmc->u.dmc_fe_qpsk.orbital_pos)) {
|
766
|
save |= COMPARE(u.dmc_fe_qpsk.orbital_pos, CBIT_ORBITAL_POS);
|
767
|
tuning_new.u.dmc_fe_qpsk.orbital_pos = dmc->u.dmc_fe_qpsk.orbital_pos;
|
768
|
}
|
769
|
}
|
770
|
/* Do not change anything else without autodiscovery flag */
|
771
|
if (!ln->mn_autodiscovery)
|
772
|
goto save;
|
773
|
/* Handle big diffs that have been allowed through for DVB-S */
|
774
|
if (deltaU32(dmc->dmc_fe_freq, tuning_new.dmc_fe_freq) > 4000) {
|
775
|
tuning_new.dmc_fe_freq = dmc->dmc_fe_freq;
|
776
|
save |= CBIT_FREQ;
|
777
|
}
|
778
|
save |= COMPAREN(dmc_fe_modulation, CBIT_MODULATION);
|
779
|
save |= COMPAREN(dmc_fe_inversion, CBIT_INVERSION);
|
780
|
save |= COMPAREN(dmc_fe_rolloff, CBIT_ROLLOFF);
|
781
|
save |= COMPAREN(dmc_fe_pilot, CBIT_PILOT);
|
782
|
switch (dmc->dmc_fe_type) {
|
783
|
case DVB_TYPE_T:
|
784
|
case DVB_TYPE_DTMB:
|
785
|
save |= COMPARE(dmc_fe_stream_id, CBIT_STREAM_ID);
|
786
|
save |= COMPAREN(u.dmc_fe_ofdm.bandwidth, CBIT_BANDWIDTH);
|
787
|
save |= COMPAREN(u.dmc_fe_ofdm.hierarchy_information, CBIT_HIERARCHY);
|
788
|
save |= COMPAREN(u.dmc_fe_ofdm.code_rate_HP, CBIT_RATE_HP);
|
789
|
save |= COMPAREN0(u.dmc_fe_ofdm.code_rate_LP, CBIT_RATE_LP);
|
790
|
save |= COMPAREN(u.dmc_fe_ofdm.transmission_mode, CBIT_TRANS_MODE);
|
791
|
save |= COMPAREN(u.dmc_fe_ofdm.guard_interval, CBIT_GUARD);
|
792
|
break;
|
793
|
case DVB_TYPE_S:
|
794
|
save |= COMPARE(u.dmc_fe_qpsk.polarisation, CBIT_POLARISATION);
|
795
|
save |= COMPARE(u.dmc_fe_qpsk.symbol_rate, CBIT_RATE);
|
796
|
save |= COMPARE(dmc_fe_stream_id, CBIT_STREAM_ID);
|
797
|
save |= COMPAREN(dmc_fe_pls_mode, CBIT_PLS_MODE);
|
798
|
save |= COMPAREN(dmc_fe_pls_code, CBIT_PLS_CODE);
|
799
|
save |= COMPAREN(u.dmc_fe_qpsk.fec_inner, CBIT_FEC_INNER);
|
800
|
break;
|
801
|
case DVB_TYPE_C:
|
802
|
case DVB_TYPE_ATSC_C:
|
803
|
save |= COMPARE(u.dmc_fe_qam.symbol_rate, CBIT_RATE);
|
804
|
save |= COMPAREN(u.dmc_fe_qam.fec_inner, CBIT_FEC_INNER);
|
805
|
break;
|
806
|
case DVB_TYPE_ATSC_T:
|
807
|
break;
|
808
|
default:
|
809
|
abort();
|
810
|
}
|
811
|
#undef COMPARE
|
812
|
#undef COMPAREN
|
813
|
/* ignore rolloff only changes (don't save) */
|
814
|
save &= ~CBIT_ROLLOFF;
|
815
|
if (save) {
|
816
|
char muxname[128];
|
817
|
mpegts_mux_nice_name((mpegts_mux_t *)mm, muxname, sizeof(muxname));
|
818
|
dvb_mux_conf_str(&tuning_old, buf, sizeof(buf));
|
819
|
tvhlog(change ? LOG_WARNING : LOG_NOTICE, LS_MPEGTS,
|
820
|
"mux %s%s %s (%08x)", muxname,
|
821
|
change ? " changed from" : " old params", buf, save);
|
822
|
dvb_mux_conf_str(&tuning_new, buf, sizeof(buf));
|
823
|
tvhlog(change ? LOG_WARNING : LOG_NOTICE, LS_MPEGTS,
|
824
|
"mux %s%s %s (%08x)", muxname,
|
825
|
change ? " changed to " : " new params", buf, save);
|
826
|
if (!change) save = 0;
|
827
|
}
|
828
|
if (save) lm->lm_tuning = tuning_new;
|
829
|
}
|
830
|
save:
|
831
|
if (mm && save) {
|
832
|
mm->mm_dmc_origin = origin;
|
833
|
mm->mm_dmc_origin_expire = mclk() + sec2mono(3600 * 24); /* one day */
|
834
|
idnode_changed(&mm->mm_id);
|
835
|
}
|
836
|
noop:
|
837
|
return (mpegts_mux_t *)mm;
|
838
|
}
|
839
|
|
840
|
static mpegts_service_t *
|
841
|
dvb_network_create_service
|
842
|
( mpegts_mux_t *mm, uint16_t sid, uint16_t pmt_pid )
|
843
|
{
|
844
|
dvb_mux_t *lm = (dvb_mux_t *)mm;
|
845
|
mpegts_service_t *s;
|
846
|
|
847
|
s = mpegts_service_create1(NULL, mm, sid, pmt_pid, NULL);
|
848
|
|
849
|
/* Set service values from mux if CableCARD */
|
850
|
if (lm->lm_tuning.dmc_fe_type == DVB_TYPE_CABLECARD) {
|
851
|
mpegts_network_t *ln = mm->mm_network;
|
852
|
if (!s->s_dvb_provider && lm->mm_provider_network_name)
|
853
|
s->s_dvb_provider = strdup(lm->mm_provider_network_name);
|
854
|
if (!s->s_dvb_provider && ln->mn_provider_network_name)
|
855
|
s->s_dvb_provider = strdup(ln->mn_provider_network_name);
|
856
|
if (!s->s_dvb_channel_num)
|
857
|
s->s_dvb_channel_num = lm->lm_tuning.u.dmc_fe_cablecard.vchannel;
|
858
|
if (!s->s_dvb_svcname && lm->lm_tuning.u.dmc_fe_cablecard.name)
|
859
|
s->s_dvb_svcname = strdup(lm->lm_tuning.u.dmc_fe_cablecard.name);
|
860
|
}
|
861
|
|
862
|
return s;
|
863
|
}
|
864
|
|
865
|
static mpegts_mux_t *
|
866
|
dvb_network_mux_create2
|
867
|
( mpegts_network_t *mn, htsmsg_t *conf )
|
868
|
{
|
869
|
dvb_network_t *ln = (dvb_network_t*)mn;
|
870
|
dvb_mux_t *mm;
|
871
|
mm = dvb_mux_create0(ln, MPEGTS_ONID_NONE, MPEGTS_TSID_NONE,
|
872
|
NULL, NULL, conf);
|
873
|
return mpegts_mux_post_create((mpegts_mux_t *)mm);
|
874
|
}
|
875
|
|
876
|
/* ****************************************************************************
|
877
|
* Creation/Config
|
878
|
* ***************************************************************************/
|
879
|
|
880
|
dvb_network_t *
|
881
|
dvb_network_create0
|
882
|
( const char *uuid, const idclass_t *idc, htsmsg_t *conf )
|
883
|
{
|
884
|
dvb_network_t *ln;
|
885
|
dvb_mux_t *lm;
|
886
|
htsmsg_t *c, *e;
|
887
|
htsmsg_field_t *f;
|
888
|
const char *s;
|
889
|
|
890
|
ln = calloc(1, sizeof(dvb_network_t));
|
891
|
ln->ln_type = dvb_fe_type_by_network_class(idc);
|
892
|
assert(ln->ln_type != DVB_TYPE_NONE);
|
893
|
|
894
|
/* Create */
|
895
|
if (!(ln = (dvb_network_t*)mpegts_network_create0((void*)ln,
|
896
|
idc, uuid, NULL, conf)))
|
897
|
return NULL;
|
898
|
|
899
|
/* Callbacks */
|
900
|
ln->mn_create_mux = dvb_network_create_mux;
|
901
|
ln->mn_create_service = dvb_network_create_service;
|
902
|
ln->mn_config_save = dvb_network_config_save;
|
903
|
ln->mn_mux_class = dvb_network_mux_class;
|
904
|
ln->mn_mux_create2 = dvb_network_mux_create2;
|
905
|
|
906
|
/* No config */
|
907
|
if (!conf)
|
908
|
return ln;
|
909
|
|
910
|
/* Set predefined muxes */
|
911
|
/* Because PO_NOSAVE in idnode_load() this value is not set on load */
|
912
|
if ((s = htsmsg_get_str(conf, "scanfile")) != NULL)
|
913
|
dvb_network_class_scanfile_set(ln, s);
|
914
|
|
915
|
/* Load muxes */
|
916
|
if ((c = hts_settings_load_r(1, "input/dvb/networks/%s/muxes", uuid))) {
|
917
|
HTSMSG_FOREACH(f, c) {
|
918
|
if (!(e = htsmsg_get_map_by_field(f))) continue;
|
919
|
if (!(e = htsmsg_get_map(e, "config"))) continue;
|
920
|
lm = dvb_mux_create1(ln, htsmsg_field_name(f), e);
|
921
|
mpegts_mux_post_create((mpegts_mux_t *)lm);
|
922
|
}
|
923
|
htsmsg_destroy(c);
|
924
|
}
|
925
|
|
926
|
return ln;
|
927
|
}
|
928
|
|
929
|
static mpegts_network_t *
|
930
|
dvb_network_builder
|
931
|
( const idclass_t *idc, htsmsg_t *conf )
|
932
|
{
|
933
|
return (mpegts_network_t*)dvb_network_create0(NULL, idc, conf);
|
934
|
}
|
935
|
|
936
|
static const idclass_t * dvb_network_classes[] = {
|
937
|
&dvb_network_dvbt_class,
|
938
|
&dvb_network_dvbc_class,
|
939
|
&dvb_network_dvbs_class,
|
940
|
&dvb_network_atsc_t_class,
|
941
|
&dvb_network_atsc_c_class,
|
942
|
&dvb_network_cablecard_class,
|
943
|
&dvb_network_isdb_t_class,
|
944
|
&dvb_network_isdb_c_class,
|
945
|
&dvb_network_isdb_s_class,
|
946
|
#if 0 /* TODO: write DAB stream parser */
|
947
|
&dvb_network_dab_class,
|
948
|
#endif
|
949
|
};
|
950
|
|
951
|
static const idclass_t * dvb_mux_classes[] = {
|
952
|
&dvb_mux_dvbt_class,
|
953
|
&dvb_mux_dvbc_class,
|
954
|
&dvb_mux_dvbs_class,
|
955
|
&dvb_mux_atsc_t_class,
|
956
|
&dvb_mux_atsc_c_class,
|
957
|
&dvb_mux_cablecard_class,
|
958
|
&dvb_mux_isdb_t_class,
|
959
|
&dvb_mux_isdb_c_class,
|
960
|
&dvb_mux_isdb_s_class,
|
961
|
#if 0 /* TODO: write DAB stream parser */
|
962
|
&dvb_mux_dab_class,
|
963
|
#endif
|
964
|
};
|
965
|
|
966
|
void dvb_network_init ( void )
|
967
|
{
|
968
|
htsmsg_t *c, *e;
|
969
|
htsmsg_field_t *f;
|
970
|
const char *s;
|
971
|
int i;
|
972
|
|
973
|
/* Load list of mux charset global overrides */
|
974
|
dvb_charset_init();
|
975
|
|
976
|
/* Register mux classes */
|
977
|
for (i = 0; i < ARRAY_SIZE(dvb_mux_classes); i++)
|
978
|
idclass_register(dvb_mux_classes[i]);
|
979
|
|
980
|
/* Register class builders */
|
981
|
for (i = 0; i < ARRAY_SIZE(dvb_network_classes); i++)
|
982
|
mpegts_network_register_builder(dvb_network_classes[i],
|
983
|
dvb_network_builder);
|
984
|
|
985
|
/* Load settings */
|
986
|
if (!(c = hts_settings_load_r(1, "input/dvb/networks")))
|
987
|
return;
|
988
|
|
989
|
HTSMSG_FOREACH(f, c) {
|
990
|
if (!(e = htsmsg_get_map_by_field(f))) continue;
|
991
|
if (!(e = htsmsg_get_map(e, "config"))) continue;
|
992
|
if (!(s = htsmsg_get_str(e, "class"))) continue;
|
993
|
for (i = 0; i < ARRAY_SIZE(dvb_network_classes); i++) {
|
994
|
if (strcmp(s, "dvb_network_atsc") == 0)
|
995
|
s = "dvb_network_atsc_t";
|
996
|
if(!strcmp(dvb_network_classes[i]->ic_class, s)) {
|
997
|
dvb_network_create0(htsmsg_field_name(f), dvb_network_classes[i], e);
|
998
|
break;
|
999
|
}
|
1000
|
}
|
1001
|
}
|
1002
|
htsmsg_destroy(c);
|
1003
|
}
|
1004
|
|
1005
|
void dvb_network_done ( void )
|
1006
|
{
|
1007
|
int i;
|
1008
|
|
1009
|
tvh_mutex_lock(&global_lock);
|
1010
|
/* Unregister class builders */
|
1011
|
for (i = 0; i < ARRAY_SIZE(dvb_network_classes); i++) {
|
1012
|
mpegts_network_unregister_builder(dvb_network_classes[i]);
|
1013
|
mpegts_network_class_delete(dvb_network_classes[i], 0);
|
1014
|
}
|
1015
|
tvh_mutex_unlock(&global_lock);
|
1016
|
|
1017
|
dvb_charset_done();
|
1018
|
scanfile_done();
|
1019
|
}
|
1020
|
|
1021
|
/* ****************************************************************************
|
1022
|
* Search
|
1023
|
* ***************************************************************************/
|
1024
|
|
1025
|
const idclass_t *dvb_network_class_by_fe_type(dvb_fe_type_t type)
|
1026
|
{
|
1027
|
if (type == DVB_TYPE_T)
|
1028
|
return &dvb_network_dvbt_class;
|
1029
|
else if (type == DVB_TYPE_C)
|
1030
|
return &dvb_network_dvbc_class;
|
1031
|
else if (type == DVB_TYPE_S)
|
1032
|
return &dvb_network_dvbs_class;
|
1033
|
else if (type == DVB_TYPE_ATSC_T)
|
1034
|
return &dvb_network_atsc_t_class;
|
1035
|
else if (type == DVB_TYPE_ATSC_C)
|
1036
|
return &dvb_network_atsc_c_class;
|
1037
|
else if (type == DVB_TYPE_CABLECARD)
|
1038
|
return &dvb_network_cablecard_class;
|
1039
|
else if (type == DVB_TYPE_ISDB_T)
|
1040
|
return &dvb_network_isdb_t_class;
|
1041
|
else if (type == DVB_TYPE_ISDB_C)
|
1042
|
return &dvb_network_isdb_c_class;
|
1043
|
else if (type == DVB_TYPE_ISDB_S)
|
1044
|
return &dvb_network_isdb_s_class;
|
1045
|
else if (type == DVB_TYPE_DTMB)
|
1046
|
return &dvb_network_dtmb_class;
|
1047
|
else if (type == DVB_TYPE_DAB)
|
1048
|
return &dvb_network_dab_class;
|
1049
|
|
1050
|
return NULL;
|
1051
|
}
|
1052
|
|
1053
|
dvb_fe_type_t dvb_fe_type_by_network_class(const idclass_t *idc)
|
1054
|
{
|
1055
|
if (idc == &dvb_network_dvbt_class)
|
1056
|
return DVB_TYPE_T;
|
1057
|
else if (idc == &dvb_network_dvbc_class)
|
1058
|
return DVB_TYPE_C;
|
1059
|
else if (idc == &dvb_network_dvbs_class)
|
1060
|
return DVB_TYPE_S;
|
1061
|
else if (idc == &dvb_network_atsc_t_class)
|
1062
|
return DVB_TYPE_ATSC_T;
|
1063
|
else if (idc == &dvb_network_atsc_c_class)
|
1064
|
return DVB_TYPE_ATSC_C;
|
1065
|
else if (idc == &dvb_network_cablecard_class)
|
1066
|
return DVB_TYPE_CABLECARD;
|
1067
|
else if (idc == &dvb_network_isdb_t_class)
|
1068
|
return DVB_TYPE_ISDB_T;
|
1069
|
else if (idc == &dvb_network_isdb_c_class)
|
1070
|
return DVB_TYPE_ISDB_C;
|
1071
|
else if (idc == &dvb_network_isdb_s_class)
|
1072
|
return DVB_TYPE_ISDB_S;
|
1073
|
else if (idc == &dvb_network_dtmb_class)
|
1074
|
return DVB_TYPE_DTMB;
|
1075
|
else if (idc == &dvb_network_dab_class)
|
1076
|
return DVB_TYPE_DAB;
|
1077
|
|
1078
|
return DVB_TYPE_NONE;
|
1079
|
}
|
1080
|
|
1081
|
idnode_set_t *dvb_network_list_by_fe_type(dvb_fe_type_t type)
|
1082
|
{
|
1083
|
const idclass_t *idc = dvb_network_class_by_fe_type(type);
|
1084
|
|
1085
|
if (!idc)
|
1086
|
return NULL;
|
1087
|
|
1088
|
return idnode_find_all(idc, NULL);
|
1089
|
}
|
1090
|
|
1091
|
int dvb_network_get_orbital_pos(mpegts_network_t *mn)
|
1092
|
{
|
1093
|
dvb_network_t *ln = (dvb_network_t *)mn;
|
1094
|
mpegts_mux_t *mm;
|
1095
|
dvb_mux_t *lm = NULL;
|
1096
|
|
1097
|
if (!ln)
|
1098
|
return INT_MAX;
|
1099
|
if (tvhtrace_enabled()) {
|
1100
|
if (!idnode_is_instance(&mn->mn_id, &dvb_network_dvbs_class)) {
|
1101
|
tvhinfo(LS_MPEGTS, "wrong dvb_network_get_orbital_pos() call");
|
1102
|
return INT_MAX;
|
1103
|
}
|
1104
|
}
|
1105
|
if (ln->mn_satpos != INT_MAX)
|
1106
|
return ln->mn_satpos;
|
1107
|
LIST_FOREACH(mm, &ln->mn_muxes, mm_network_link) {
|
1108
|
lm = (dvb_mux_t *)mm;
|
1109
|
if (lm->lm_tuning.u.dmc_fe_qpsk.orbital_pos != INT_MAX)
|
1110
|
break;
|
1111
|
}
|
1112
|
if (mm)
|
1113
|
return lm->lm_tuning.u.dmc_fe_qpsk.orbital_pos;
|
1114
|
return INT_MAX;
|
1115
|
}
|
1116
|
|
1117
|
/******************************************************************************
|
1118
|
* Editor Configuration
|
1119
|
*
|
1120
|
* vim:sts=2:ts=2:sw=2:et
|
1121
|
*****************************************************************************/
|