Project

General

Profile

Bug #5486 » mpegts_network_dvb.c

Patched file - Anonymous, 2019-01-17 13:29

 
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
 *****************************************************************************/
(2-2/5)