1 /*
2 * MPEGTS (DVB) based service
3 *
4 * Copyright (C) 2013 Andreas Öman
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 <assert.h>
21
22 #include "service.h"
23 #include "channels.h"
24 #include "input.h"
25 #include "settings.h"
26 #include "dvb_charset.h"
27 #include "config.h"
28 #include "epggrab.h"
29
30 /* **************************************************************************
31 * Class definition
32 * *************************************************************************/
33
34 extern const idclass_t service_class;
35
36 static const void *
mpegts_service_class_get_mux(void * ptr)37 mpegts_service_class_get_mux ( void *ptr )
38 {
39 static char buf[512], *s = buf;
40 mpegts_service_t *ms = ptr;
41 if (ms->s_dvb_mux && ms->s_dvb_mux->mm_display_name)
42 ms->s_dvb_mux->mm_display_name(ms->s_dvb_mux, buf, sizeof(buf));
43 else
44 *buf = 0;
45 return &s;
46 }
47
48 static const void *
mpegts_service_class_get_mux_uuid(void * ptr)49 mpegts_service_class_get_mux_uuid ( void *ptr )
50 {
51 mpegts_service_t *ms = ptr;
52 if (ms && ms->s_dvb_mux)
53 idnode_uuid_as_str(&ms->s_dvb_mux->mm_id, prop_sbuf);
54 else
55 prop_sbuf[0] = '\0';
56 return &prop_sbuf_ptr;
57 }
58
59 static const void *
mpegts_service_class_get_network(void * ptr)60 mpegts_service_class_get_network ( void *ptr )
61 {
62 static char buf[512], *s = buf;
63 mpegts_service_t *ms = ptr;
64 mpegts_network_t *mn = ms->s_dvb_mux ? ms->s_dvb_mux->mm_network : NULL;
65 if (mn && mn->mn_display_name)
66 mn->mn_display_name(mn, buf, sizeof(buf));
67 else
68 *buf = 0;
69 return &s;
70 }
71
72 static htsmsg_t *
mpegts_service_pref_capid_lock_list(void * o,const char * lang)73 mpegts_service_pref_capid_lock_list ( void *o, const char *lang )
74 {
75 static const struct strtab tab[] = {
76 { N_("Off"), 0 },
77 { N_("On"), 1 },
78 { N_("Only preferred CA PID"), 2 },
79 };
80 return strtab2htsmsg(tab, 1, lang);
81 }
82
83 CLASS_DOC(mpegts_service)
84
85 const idclass_t mpegts_service_class =
86 {
87 .ic_super = &service_class,
88 .ic_class = "mpegts_service",
89 .ic_caption = N_("MPEG-TS Service"),
90 .ic_doc = tvh_doc_mpegts_service_class,
91 .ic_order = "enabled,channel,svcname",
92 .ic_properties = (const property_t[]){
93 {
94 .type = PT_STR,
95 .id = "network",
96 .name = N_("Network"),
97 .desc = N_("The network the service is on."),
98 .opts = PO_RDONLY | PO_NOSAVE,
99 .get = mpegts_service_class_get_network,
100 },
101 {
102 .type = PT_STR,
103 .id = "multiplex",
104 .name = N_("Mux"),
105 .desc = N_("The mux the service is on."),
106 .opts = PO_RDONLY | PO_NOSAVE,
107 .get = mpegts_service_class_get_mux,
108 },
109 {
110 .type = PT_STR,
111 .id = "multiplex_uuid",
112 .name = N_("Mux UUID"),
113 .desc = N_("The mux's universally unique identifier."),
114 .opts = PO_RDONLY | PO_NOSAVE | PO_HIDDEN | PO_EXPERT,
115 .get = mpegts_service_class_get_mux_uuid,
116 },
117 {
118 .type = PT_U16,
119 .id = "sid",
120 .name = N_("Service ID"),
121 .desc = N_("The service ID as set by the provider."),
122 .opts = PO_RDONLY | PO_ADVANCED,
123 .off = offsetof(mpegts_service_t, s_dvb_service_id),
124 },
125 {
126 .type = PT_U16,
127 .id = "lcn",
128 .name = N_("Local channel number"),
129 .desc = N_("The service's channel number as set by the provider."),
130 .opts = PO_RDONLY | PO_ADVANCED,
131 .off = offsetof(mpegts_service_t, s_dvb_channel_num),
132 },
133 {
134 .type = PT_U16,
135 .id = "lcn_minor",
136 .name = N_("Local channel minor"),
137 .desc = N_("The service's channel minor as set by the provider."),
138 .opts = PO_RDONLY | PO_EXPERT,
139 .off = offsetof(mpegts_service_t, s_dvb_channel_minor),
140 },
141 {
142 .type = PT_U16,
143 .id = "lcn2",
144 .name = N_("OpenTV channel number"),
145 .desc = N_("The OpenTV channel number as set by the provider."),
146 .opts = PO_RDONLY | PO_EXPERT,
147 .off = offsetof(mpegts_service_t, s_dvb_opentv_chnum),
148 },
149 {
150 .type = PT_U16,
151 .id = "srcid",
152 .name = N_("ATSC source ID"),
153 .desc = N_("The ATSC source ID as set by the provider."),
154 .opts = PO_RDONLY | PO_EXPERT,
155 .off = offsetof(mpegts_service_t, s_atsc_source_id),
156 },
157 {
158 .type = PT_STR,
159 .id = "svcname",
160 .name = N_("Service name"),
161 .desc = N_("The service name as set by the provider."),
162 .opts = PO_RDONLY,
163 .off = offsetof(mpegts_service_t, s_dvb_svcname),
164 },
165 {
166 .type = PT_STR,
167 .id = "provider",
168 .name = N_("Provider"),
169 .desc = N_("The provider's name."),
170 .opts = PO_RDONLY | PO_HIDDEN,
171 .off = offsetof(mpegts_service_t, s_dvb_provider),
172 },
173 {
174 .type = PT_STR,
175 .id = "cridauth",
176 .name = N_("CRID authority"),
177 .desc = N_("Content reference identifier authority."),
178 .opts = PO_RDONLY | PO_HIDDEN | PO_EXPERT,
179 .off = offsetof(mpegts_service_t, s_dvb_cridauth),
180 },
181 {
182 .type = PT_U16,
183 .id = "dvb_servicetype",
184 .name = N_("Service type"),
185 .desc = N_("The service type flag as defined by the DVB "
186 "specifications (e.g. 0x02 = radio, 0x11 = MPEG2 "
187 "HD TV, 0x19 = H.264 HD TV)"),
188 .opts = PO_RDONLY | PO_HIDDEN | PO_EXPERT,
189 .off = offsetof(mpegts_service_t, s_dvb_servicetype),
190 },
191 {
192 .type = PT_BOOL,
193 .id = "dvb_ignore_eit",
194 .name = N_("Ignore EPG (EIT)"),
195 .desc = N_("Enable or disable ignoring of Event Information "
196 "Table (EIT) data on this mux."),
197 .off = offsetof(mpegts_service_t, s_dvb_ignore_eit),
198 .opts = PO_EXPERT,
199 },
200 {
201 .type = PT_STR,
202 .id = "charset",
203 .name = N_("Character set"),
204 .desc = N_("The character encoding for this service (e.g. UTF-8)."),
205 .off = offsetof(mpegts_service_t, s_dvb_charset),
206 .list = dvb_charset_enum,
207 .opts = PO_EXPERT | PO_DOC_NLIST,
208 },
209 {
210 .type = PT_U16,
211 .id = "prefcapid",
212 .name = N_("Preferred CA PID"),
213 .desc = N_("The Preferred Conditional Access Packet "
214 "Identifier. Used for decrypting scrambled streams."),
215 .off = offsetof(mpegts_service_t, s_dvb_prefcapid),
216 .opts = PO_EXPERT,
217 },
218 {
219 .type = PT_INT,
220 .id = "prefcapid_lock",
221 .name = N_("Lock preferred CA PID"),
222 .desc = N_("The locking mechanism selection for The Preferred "
223 "Conditional Access Packet Identifier. See Help "
224 "for more information."),
225 .off = offsetof(mpegts_service_t, s_dvb_prefcapid_lock),
226 .opts = PO_EXPERT | PO_DOC_NLIST,
227 .list = mpegts_service_pref_capid_lock_list,
228 },
229 {
230 .type = PT_U16,
231 .id = "force_caid",
232 .name = N_("Force CA ID (e.g. 0x2600)"),
233 .desc = N_("Force usage of entered CA ID on this service."),
234 .off = offsetof(mpegts_service_t, s_dvb_forcecaid),
235 .opts = PO_EXPERT | PO_HEXA,
236 },
237 {
238 .type = PT_INT,
239 .id = "pts_shift",
240 .name = N_("Shift PTS (ms)"),
241 .desc = N_("Add this value to PTS for the teletext subtitles. The time value is in milliseconds and may be negative."),
242 .off = offsetof(mpegts_service_t, s_pts_shift),
243 .opts = PO_EXPERT,
244 },
245 {
246 .type = PT_TIME,
247 .id = "created",
248 .name = N_("Created"),
249 .desc = N_("When the service was first identified and recorded."),
250 .off = offsetof(mpegts_service_t, s_dvb_created),
251 .opts = PO_ADVANCED | PO_RDONLY,
252 },
253 {
254 .type = PT_TIME,
255 .id = "last_seen",
256 .name = N_("Last seen"),
257 .desc = N_("When the service was last seen during a mux scan."),
258 .off = offsetof(mpegts_service_t, s_dvb_last_seen),
259 .opts = PO_ADVANCED | PO_RDONLY,
260 },
261 {},
262 }
263 };
264
265 /* **************************************************************************
266 * Class methods
267 * *************************************************************************/
268
269 /*
270 * Check the service is enabled
271 */
272 static int
mpegts_service_is_enabled(service_t * t,int flags)273 mpegts_service_is_enabled(service_t *t, int flags)
274 {
275 mpegts_service_t *s = (mpegts_service_t*)t;
276 mpegts_mux_t *mm = s->s_dvb_mux;
277 return mm->mm_is_enabled(mm) ? s->s_enabled : 0;
278 }
279
280 /*
281 * Save
282 */
283 static htsmsg_t *
mpegts_service_config_save(service_t * t,char * filename,size_t fsize)284 mpegts_service_config_save ( service_t *t, char *filename, size_t fsize )
285 {
286 mpegts_service_t *s = (mpegts_service_t*)t;
287 idnode_changed(&s->s_dvb_mux->mm_id);
288 return NULL;
289 }
290
291 /*
292 * Service instance list
293 */
294 static int
mpegts_service_enlist_raw(service_t * t,tvh_input_t * ti,struct service_instance_list * sil,int flags,int weight)295 mpegts_service_enlist_raw
296 ( service_t *t, tvh_input_t *ti, struct service_instance_list *sil,
297 int flags, int weight )
298 {
299 int p, w, r, added = 0, errcnt = 0;
300 mpegts_service_t *s = (mpegts_service_t*)t;
301 mpegts_input_t *mi;
302 mpegts_mux_t *m = s->s_dvb_mux;
303 mpegts_mux_instance_t *mmi;
304
305 assert(s->s_source_type == S_MPEG_TS);
306
307 /* Create instances */
308 m->mm_create_instances(m);
309
310 /* Enlist available */
311 LIST_FOREACH(mmi, &m->mm_instances, mmi_mux_link) {
312 if (mmi->mmi_tune_failed)
313 continue;
314
315 mi = mmi->mmi_input;
316
317 if (ti && (tvh_input_t *)mi != ti)
318 continue;
319
320 r = mi->mi_is_enabled(mi, mmi->mmi_mux, flags, weight);
321 if (r == MI_IS_ENABLED_NEVER) {
322 tvhtrace(LS_MPEGTS, "enlist: input %p not enabled for mux %p service %s weight %d flags %x",
323 mi, mmi->mmi_mux, s->s_nicename, weight, flags);
324 continue;
325 }
326 if (r == MI_IS_ENABLED_RETRY) {
327 /* temporary error - retry later */
328 tvhtrace(LS_MPEGTS, "enlist: input %p postponed for mux %p service %s weight %d flags %x",
329 mi, mmi->mmi_mux, s->s_nicename, weight, flags);
330 errcnt++;
331 continue;
332 }
333
334 /* Set weight to -1 (forced) for already active mux */
335 if (mmi->mmi_mux->mm_active == mmi) {
336 w = -1;
337 p = -1;
338 } else {
339 w = mi->mi_get_weight(mi, mmi->mmi_mux, flags, weight);
340 p = mi->mi_get_priority(mi, mmi->mmi_mux, flags);
341 if (w > 0 && mi->mi_free_weight &&
342 weight >= mi->mi_free_weight && w < mi->mi_free_weight)
343 w = 0;
344 }
345
346 service_instance_add(sil, t, mi->mi_instance, mi->mi_name, p, w);
347 added++;
348 }
349
350 return added ? 0 : (errcnt ? SM_CODE_NO_FREE_ADAPTER : 0);
351 }
352
353 /*
354 * Service instance list
355 */
356 static int
mpegts_service_enlist(service_t * t,tvh_input_t * ti,struct service_instance_list * sil,int flags,int weight)357 mpegts_service_enlist
358 ( service_t *t, tvh_input_t *ti, struct service_instance_list *sil,
359 int flags, int weight )
360 {
361 /* invalid PMT */
362 if (t->s_pmt_pid != SERVICE_PMT_AUTO &&
363 (t->s_pmt_pid <= 0 || t->s_pmt_pid >= 8191))
364 return SM_CODE_INVALID_SERVICE;
365
366 return mpegts_service_enlist_raw(t, ti, sil, flags, weight);
367 }
368
369 /*
370 * Start service
371 */
372 static int
mpegts_service_start(service_t * t,int instance,int weight,int flags)373 mpegts_service_start(service_t *t, int instance, int weight, int flags)
374 {
375 int r;
376 mpegts_service_t *s = (mpegts_service_t*)t;
377 mpegts_mux_t *m = s->s_dvb_mux;
378 mpegts_mux_instance_t *mmi;
379
380 /* Validate */
381 assert(s->s_status == SERVICE_IDLE);
382 assert(s->s_source_type == S_MPEG_TS);
383 lock_assert(&global_lock);
384
385 /* Find */
386 LIST_FOREACH(mmi, &m->mm_instances, mmi_mux_link)
387 if (mmi->mmi_input->mi_instance == instance)
388 break;
389 assert(mmi != NULL);
390 if (mmi == NULL)
391 return SM_CODE_UNDEFINED_ERROR;
392
393 /* Start Mux */
394 mmi->mmi_start_weight = weight;
395 r = mpegts_mux_instance_start(&mmi, t, weight);
396
397 /* Start */
398 if (!r) {
399
400 /* Open service */
401 s->s_dvb_subscription_flags = flags;
402 s->s_dvb_subscription_weight = weight;
403 mmi->mmi_input->mi_open_service(mmi->mmi_input, s, flags, 1, weight);
404 }
405
406 return r;
407 }
408
409 /*
410 * Stop service
411 */
412 static void
mpegts_service_stop(service_t * t)413 mpegts_service_stop(service_t *t)
414 {
415 mpegts_service_t *s = (mpegts_service_t*)t;
416 mpegts_input_t *i = s->s_dvb_active_input;
417
418 /* Validate */
419 assert(s->s_source_type == S_MPEG_TS);
420 lock_assert(&global_lock);
421
422 /* Stop */
423 if (i)
424 i->mi_close_service(i, s);
425
426 /* Save some memory */
427 sbuf_free(&s->s_tsbuf);
428 }
429
430 /*
431 * Refresh
432 */
433 static void
mpegts_service_refresh(service_t * t)434 mpegts_service_refresh(service_t *t)
435 {
436 mpegts_service_t *s = (mpegts_service_t*)t;
437 mpegts_input_t *i = s->s_dvb_active_input;
438
439 /* Validate */
440 assert(s->s_source_type == S_MPEG_TS);
441 assert(i != NULL);
442 lock_assert(&global_lock);
443
444 /* Re-open */
445 i->mi_open_service(i, s, s->s_dvb_subscription_flags, 0, s->s_dvb_subscription_weight);
446 }
447
448 /*
449 * Source info
450 */
451 static void
mpegts_service_setsourceinfo(service_t * t,source_info_t * si)452 mpegts_service_setsourceinfo(service_t *t, source_info_t *si)
453 {
454 char buf[256];
455 mpegts_service_t *s = (mpegts_service_t*)t;
456 mpegts_mux_t *m = s->s_dvb_mux;
457
458 /* Validate */
459 assert(s->s_source_type == S_MPEG_TS);
460 lock_assert(&global_lock);
461
462 /* Update */
463 memset(si, 0, sizeof(struct source_info));
464 si->si_type = S_MPEG_TS;
465
466 uuid_duplicate(&si->si_network_uuid, &m->mm_network->mn_id.in_uuid);
467 uuid_duplicate(&si->si_mux_uuid, &m->mm_id.in_uuid);
468
469 if(m->mm_network->mn_network_name != NULL)
470 si->si_network = strdup(m->mm_network->mn_network_name);
471 mpegts_network_get_type_str(m->mm_network, buf, sizeof(buf));
472 si->si_network_type = strdup(buf);
473
474 m->mm_display_name(m, buf, sizeof(buf));
475 si->si_mux = strdup(buf);
476
477 if(s->s_dvb_active_input) {
478 mpegts_input_t *mi = s->s_dvb_active_input;
479 uuid_duplicate(&si->si_adapter_uuid, &mi->ti_id.in_uuid);
480 mi->mi_display_name(mi, buf, sizeof(buf));
481 si->si_adapter = strdup(buf);
482 }
483
484 if(s->s_dvb_provider != NULL)
485 si->si_provider = strdup(s->s_dvb_provider);
486
487 if(s->s_dvb_svcname != NULL)
488 si->si_service = strdup(s->s_dvb_svcname);
489
490 #if ENABLE_MPEGTS_DVB
491 if(m->mm_network != NULL && m->mm_network->mn_satpos != INT_MAX) {
492 dvb_sat_position_to_str(m->mm_network->mn_satpos, buf, sizeof(buf));
493 si->si_satpos = strdup(buf);
494 }
495 #endif
496 }
497
498 /*
499 * Grace period
500 */
501 static int
mpegts_service_grace_period(service_t * t)502 mpegts_service_grace_period(service_t *t)
503 {
504 int r = 0;
505 mpegts_service_t *ms = (mpegts_service_t*)t;
506 mpegts_mux_t *mm = ms->s_dvb_mux;
507 mpegts_input_t *mi = ms->s_dvb_active_input;
508 assert(mi != NULL);
509
510 if (mi && mi->mi_get_grace)
511 r = mi->mi_get_grace(mi, mm);
512
513 return r ?: 10;
514 }
515
516 /*
517 * Channel number
518 */
519 int64_t
mpegts_service_channel_number(service_t * s)520 mpegts_service_channel_number ( service_t *s )
521 {
522 mpegts_service_t *ms = (mpegts_service_t*)s;
523 int64_t r = 0;
524
525 if (!ms->s_dvb_mux->mm_network->mn_ignore_chnum) {
526 r = ms->s_dvb_channel_num * CHANNEL_SPLIT + ms->s_dvb_channel_minor;
527 if (r <= 0)
528 r = ms->s_dvb_opentv_chnum * CHANNEL_SPLIT;
529 }
530 if (r <= 0 && ms->s_dvb_mux->mm_network->mn_sid_chnum)
531 r = ms->s_dvb_service_id * CHANNEL_SPLIT;
532 return r;
533 }
534
535 static const char *
mpegts_service_channel_name(service_t * s)536 mpegts_service_channel_name ( service_t *s )
537 {
538 return ((mpegts_service_t*)s)->s_dvb_svcname;
539 }
540
541 static const char *
mpegts_service_provider_name(service_t * s)542 mpegts_service_provider_name ( service_t *s )
543 {
544 return ((mpegts_service_t*)s)->s_dvb_provider;
545 }
546
547 #if ENABLE_MPEGTS_DVB
548 static int
mpegts_picon_mux_isvalid(dvb_mux_t * mux,int orbital_position)549 mpegts_picon_mux_isvalid(dvb_mux_t *mux, int orbital_position)
550 {
551 switch (mux->mm_onid) {
552 case 0:
553 case 0x1111:
554 return 0;
555 case 1:
556 return orbital_position == 192;
557 case 0x00B1:
558 return mux->mm_tsid != 0x00B0;
559 case 0x0002:
560 return abs(orbital_position-282) < 6;
561 default:
562 return mux->mm_tsid < 0xFF00;
563 }
564 }
565 #endif
566
567 static const char *
mpegts_service_channel_icon(service_t * s)568 mpegts_service_channel_icon ( service_t *s )
569 {
570 /* DVB? */
571 #if ENABLE_MPEGTS_DVB
572 mpegts_service_t *ms = (mpegts_service_t*)s;
573 extern const idclass_t dvb_mux_class;
574 if (ms->s_dvb_mux &&
575 idnode_is_instance(&ms->s_dvb_mux->mm_id, &dvb_mux_class)) {
576 int32_t hash = 0;
577 dvb_mux_t *mmd = (dvb_mux_t*)ms->s_dvb_mux;
578 int pos;
579
580 switch (mmd->lm_tuning.dmc_fe_type) {
581 case DVB_TYPE_S:
582 if ((pos = dvb_network_get_orbital_pos(mmd->mm_network)) == INT_MAX)
583 return NULL;
584 if (pos < -1800 || pos > 1800)
585 return NULL;
586 hash = (pos >= 0 ? pos : 3600 + pos) << 16;
587 if (!mpegts_picon_mux_isvalid(mmd, pos))
588 hash |= ((mmd->lm_tuning.dmc_fe_freq / 1000) & 0x7fff) |
589 (mmd->lm_tuning.u.dmc_fe_qpsk.orbital_pos == DVB_POLARISATION_HORIZONTAL ? 0x8000 : 0);
590 break;
591 case DVB_TYPE_C:
592 case DVB_TYPE_ATSC_C:
593 hash = 0xFFFF0000;
594 break;
595 case DVB_TYPE_T:
596 hash = 0xEEEE0000;
597 break;
598 case DVB_TYPE_ATSC_T:
599 hash = 0xDDDD0000;
600 break;
601 default:
602 return NULL;
603 }
604
605 snprintf(prop_sbuf, PROP_SBUF_LEN,
606 "picon://1_0_%X_%X_%X_%X_%X_0_0_0.png",
607 config.picon_scheme == PICON_ISVCTYPE ? 1 : ms->s_dvb_servicetype,
608 ms->s_dvb_service_id,
609 ms->s_dvb_mux->mm_tsid,
610 ms->s_dvb_mux->mm_onid,
611 hash);
612 return prop_sbuf;
613 }
614 #endif
615
616 return NULL;
617 }
618
619 #if ENABLE_MPEGTS_DVB
620 static int
mpegts_service_match_network(mpegts_network_t * mn,uint32_t hash,const idclass_t * idc)621 mpegts_service_match_network(mpegts_network_t *mn, uint32_t hash, const idclass_t *idc)
622 {
623 int pos, pos2;
624
625 if (idc != &dvb_mux_dvbs_class) return 1;
626 pos = hash >> 16;
627 if (pos > 3600 || pos < 0) return 0;
628 pos = pos <= 1800 ? pos : pos - 3600;
629 if ((pos2 = dvb_network_get_orbital_pos(mn)) == INT_MAX) return 0;
630 return deltaI32(pos, pos2) <= 20;
631 }
632 #endif
633
634 #if ENABLE_MPEGTS_DVB
635 static int
mpegts_service_match_mux(dvb_mux_t * mm,uint32_t hash,const idclass_t * idc)636 mpegts_service_match_mux(dvb_mux_t *mm, uint32_t hash, const idclass_t *idc)
637 {
638 extern const idclass_t dvb_mux_dvbs_class;
639 dvb_mux_t *mmd;
640 int freq, pol;
641
642 if ((hash & 0xffff) == 0) return 1;
643 if (idc != &dvb_mux_dvbs_class) return 0;
644 freq = (hash & 0x7fff) * 1000;
645 pol = (hash & 0x8000) ? DVB_POLARISATION_HORIZONTAL : DVB_POLARISATION_VERTICAL;
646 mmd = mm;
647 return mmd->lm_tuning.u.dmc_fe_qpsk.orbital_pos == pol &&
648 deltaU32(mmd->lm_tuning.dmc_fe_freq, freq) < 2000;
649 }
650 #endif
651
652 service_t *
mpegts_service_find_e2(uint32_t stype,uint32_t sid,uint32_t tsid,uint32_t onid,uint32_t hash)653 mpegts_service_find_e2(uint32_t stype, uint32_t sid, uint32_t tsid,
654 uint32_t onid, uint32_t hash)
655 {
656 #if ENABLE_MPEGTS_DVB
657 mpegts_network_t *mn;
658 mpegts_mux_t *mm;
659 mpegts_service_t *s;
660 const idclass_t *idc;
661
662 lock_assert(&global_lock);
663
664 switch (hash & 0xFFFF0000) {
665 case 0xFFFF0000: idc = &dvb_mux_dvbc_class; break;
666 case 0xEEEE0000: idc = &dvb_mux_dvbt_class; break;
667 case 0xDDDD0000: idc = &dvb_mux_dvbt_class; break;
668 default: idc = &dvb_mux_dvbs_class; break;
669 }
670 LIST_FOREACH(mn, &mpegts_network_all, mn_global_link) {
671 if (!idnode_is_instance(&mn->mn_id, &dvb_network_class)) continue;
672 if (dvb_network_mux_class(mn) != idc) continue;
673 if (!mpegts_service_match_network(mn, hash, idc)) continue;
674 LIST_FOREACH(mm, &mn->mn_muxes, mm_network_link) {
675 if (!idnode_is_instance(&mm->mm_id, idc)) continue;
676 if (mm->mm_tsid != tsid || mm->mm_onid != onid) continue;
677 if (!mpegts_service_match_mux((dvb_mux_t *)mm, hash, idc)) continue;
678 LIST_FOREACH(s, &mm->mm_services, s_dvb_mux_link)
679 if (s->s_dvb_service_id == sid)
680 return (service_t *)s;
681 }
682 }
683 #endif
684 return NULL;
685 }
686
687 static void
mpegts_service_mapped(service_t * t)688 mpegts_service_mapped ( service_t *t )
689 {
690 epggrab_ota_queue_mux(((mpegts_service_t *)t)->s_dvb_mux);
691 }
692
693 void
mpegts_service_unref(service_t * t)694 mpegts_service_unref ( service_t *t )
695 {
696 mpegts_service_t *ms = (mpegts_service_t*)t;
697
698 free(ms->s_dvb_svcname);
699 free(ms->s_dvb_provider);
700 free(ms->s_dvb_cridauth);
701 free(ms->s_dvb_charset);
702 }
703
704 void
mpegts_service_delete(service_t * t,int delconf)705 mpegts_service_delete ( service_t *t, int delconf )
706 {
707 mpegts_service_t *ms = (mpegts_service_t*)t, *mms;
708 mpegts_mux_t *mm = t->s_type == STYPE_STD ? ms->s_dvb_mux : NULL;
709
710 if (mm)
711 idnode_changed(&mm->mm_id);
712
713 /* Free memory */
714 if (t->s_type == STYPE_STD)
715 LIST_REMOVE(ms, s_dvb_mux_link);
716 sbuf_free(&ms->s_tsbuf);
717
718 /* Remove master/slave linking */
719 while (ms->s_masters.is_count > 0) {
720 mms = (mpegts_service_t *)ms->s_masters.is_array[0];
721 mms->s_unlink(mms, ms);
722 }
723 idnode_set_clear(&ms->s_masters);
724
725 /* Remove PID lists */
726 mpegts_pid_destroy(&ms->s_pids);
727 mpegts_pid_destroy(&ms->s_slaves_pids);
728
729 // Note: the ultimate deletion and removal from the idnode list
730 // is done in service_destroy
731 }
732
733 static int
mpegts_service_satip_source(service_t * t)734 mpegts_service_satip_source ( service_t *t )
735 {
736 mpegts_service_t *ms = (mpegts_service_t*)t;
737 mpegts_network_t *mn = ms->s_dvb_mux ? ms->s_dvb_mux->mm_network : NULL;
738 return mn ? mn->mn_satip_source : -1;
739 }
740
741 static void
mpegts_service_memoryinfo(service_t * t,int64_t * size)742 mpegts_service_memoryinfo ( service_t *t, int64_t *size )
743 {
744 mpegts_service_t *ms = (mpegts_service_t*)t;
745 *size += sizeof(*ms);
746 *size += tvh_strlen(ms->s_nicename);
747 *size += tvh_strlen(ms->s_dvb_svcname);
748 *size += tvh_strlen(ms->s_dvb_provider);
749 *size += tvh_strlen(ms->s_dvb_cridauth);
750 *size += tvh_strlen(ms->s_dvb_charset);
751 }
752
753 static int
mpegts_service_unseen(service_t * t,const char * type,time_t before)754 mpegts_service_unseen( service_t *t, const char *type, time_t before )
755 {
756 mpegts_service_t *ms = (mpegts_service_t*)t;
757 int pat = type && strcasecmp(type, "pat") == 0;
758 if (pat && ms->s_auto != SERVICE_AUTO_PAT_MISSING) return 0;
759 return ms->s_dvb_last_seen < before;
760 }
761
762 /* **************************************************************************
763 * Creation/Location
764 * *************************************************************************/
765
766 /*
767 * Create service
768 */
769 mpegts_service_t *
mpegts_service_create0(mpegts_service_t * s,const idclass_t * class,const char * uuid,mpegts_mux_t * mm,uint16_t sid,uint16_t pmt_pid,htsmsg_t * conf)770 mpegts_service_create0
771 ( mpegts_service_t *s, const idclass_t *class, const char *uuid,
772 mpegts_mux_t *mm, uint16_t sid, uint16_t pmt_pid, htsmsg_t *conf )
773 {
774 int r;
775 char buf[256];
776 time_t dispatch_clock = gclk();
777
778 /* defaults for older version */
779 s->s_dvb_created = dispatch_clock;
780
781 if (service_create0((service_t*)s, STYPE_STD, class, uuid,
782 S_MPEG_TS, conf) == NULL)
783 return NULL;
784
785 /* Create */
786 sbuf_init(&s->s_tsbuf);
787 if (!conf) {
788 if (sid) s->s_dvb_service_id = sid;
789 if (pmt_pid) s->s_pmt_pid = pmt_pid;
790 } else {
791 if (s->s_dvb_last_seen > gclk()) /* sanity check */
792 s->s_dvb_last_seen = gclk();
793 }
794 s->s_dvb_mux = mm;
795 if ((r = dvb_servicetype_lookup(s->s_dvb_servicetype)) != -1)
796 s->s_servicetype = r;
797 LIST_INSERT_HEAD(&mm->mm_services, s, s_dvb_mux_link);
798
799 s->s_delete = mpegts_service_delete;
800 s->s_unref = mpegts_service_unref;
801 s->s_is_enabled = mpegts_service_is_enabled;
802 s->s_config_save = mpegts_service_config_save;
803 s->s_enlist = mpegts_service_enlist;
804 s->s_start_feed = mpegts_service_start;
805 s->s_stop_feed = mpegts_service_stop;
806 s->s_refresh_feed = mpegts_service_refresh;
807 s->s_setsourceinfo = mpegts_service_setsourceinfo;
808 s->s_grace_period = mpegts_service_grace_period;
809 s->s_channel_number = mpegts_service_channel_number;
810 s->s_channel_name = mpegts_service_channel_name;
811 s->s_provider_name = mpegts_service_provider_name;
812 s->s_channel_icon = mpegts_service_channel_icon;
813 s->s_mapped = mpegts_service_mapped;
814 s->s_satip_source = mpegts_service_satip_source;
815 s->s_memoryinfo = mpegts_service_memoryinfo;
816 s->s_unseen = mpegts_service_unseen;
817
818 pthread_mutex_lock(&s->s_stream_mutex);
819 service_make_nicename((service_t*)s);
820 pthread_mutex_unlock(&s->s_stream_mutex);
821
822 mpegts_mux_nice_name(mm, buf, sizeof(buf));
823 tvhdebug(LS_MPEGTS, "%s - add service %04X %s", buf, s->s_dvb_service_id, s->s_dvb_svcname);
824
825 /* Notification */
826 idnode_notify_changed(&mm->mm_id);
827 idnode_notify_changed(&mm->mm_network->mn_id);
828
829 /* Save the create time */
830 if (s->s_dvb_created == dispatch_clock)
831 service_request_save((service_t *)s, 0);
832
833 return s;
834 }
835
836 /*
837 * Find service
838 */
839 mpegts_service_t *
mpegts_service_find(mpegts_mux_t * mm,uint16_t sid,uint16_t pmt_pid,int create,int * save)840 mpegts_service_find
841 ( mpegts_mux_t *mm, uint16_t sid, uint16_t pmt_pid,
842 int create, int *save )
843 {
844 mpegts_service_t *s;
845
846 /* Validate */
847 lock_assert(&global_lock);
848
849 if (mm->mm_sid_filter > 0 && sid != mm->mm_sid_filter)
850 return NULL;
851
852 /* Find existing service */
853 LIST_FOREACH(s, &mm->mm_services, s_dvb_mux_link) {
854 if (s->s_dvb_service_id == sid) {
855 if (pmt_pid && pmt_pid != s->s_pmt_pid) {
856 s->s_pmt_pid = pmt_pid;
857 if (save) *save = 1;
858 }
859 if (create) {
860 if ((save && *save) || s->s_dvb_last_seen + 3600 < gclk()) {
861 s->s_dvb_last_seen = gclk();
862 if (save) *save = 1;
863 }
864 }
865 return s;
866 }
867 }
868
869 /* Create */
870 if (create) {
871 s = mm->mm_network->mn_create_service(mm, sid, pmt_pid);
872 s->s_dvb_created = s->s_dvb_last_seen = gclk();
873 if (save) *save = 1;
874 }
875
876 return s;
877 }
878
879 /*
880 * Find PID
881 */
882 mpegts_service_t *
mpegts_service_find_by_pid(mpegts_mux_t * mm,int pid)883 mpegts_service_find_by_pid ( mpegts_mux_t *mm, int pid )
884 {
885 mpegts_service_t *s;
886
887 lock_assert(&global_lock);
888
889 /* Find existing service */
890 LIST_FOREACH(s, &mm->mm_services, s_dvb_mux_link) {
891 pthread_mutex_lock(&s->s_stream_mutex);
892 if (pid == s->s_pmt_pid || pid == s->s_pcr_pid)
893 goto ok;
894 if (service_stream_find((service_t *)s, pid))
895 goto ok;
896 pthread_mutex_unlock(&s->s_stream_mutex);
897 }
898 return NULL;
899 ok:
900 pthread_mutex_unlock(&s->s_stream_mutex);
901 return s;
902 }
903
904 /*
905 * Raw MPEGTS Service
906 */
907
908 const idclass_t mpegts_service_raw_class =
909 {
910 .ic_super = &service_raw_class,
911 .ic_class = "mpegts_raw_service",
912 .ic_caption = N_("MPEG-TS raw service"),
913 .ic_properties = NULL
914 };
915
916 static void
mpegts_service_raw_setsourceinfo(service_t * t,source_info_t * si)917 mpegts_service_raw_setsourceinfo(service_t *t, source_info_t *si)
918 {
919 mpegts_service_setsourceinfo(t, si);
920
921 free(si->si_service);
922 si->si_service = strdup("Raw PID Subscription");
923 }
924
925 static int
mpegts_service_raw_update_pids(mpegts_service_t * t,mpegts_apids_t * pids)926 mpegts_service_raw_update_pids(mpegts_service_t *t, mpegts_apids_t *pids)
927 {
928 mpegts_input_t *mi = t->s_dvb_active_input;
929 mpegts_mux_t *mm = t->s_dvb_mux;
930 mpegts_apids_t *p, *x;
931 mpegts_apids_t add, del;
932 mpegts_apid_t *pi;
933 int i;
934
935 lock_assert(&global_lock);
936 if (pids) {
937 p = calloc(1, sizeof(*p));
938 mpegts_pid_init(p);
939 mpegts_pid_copy(p, pids);
940 } else
941 p = NULL;
942 if (mi && mm) {
943 pthread_mutex_lock(&mi->mi_output_lock);
944 pthread_mutex_lock(&t->s_stream_mutex);
945 x = t->s_pids;
946 t->s_pids = p;
947 if (!pids->all && x && x->all) {
948 mpegts_input_close_pid(mi, mm, MPEGTS_FULLMUX_PID, MPS_RAW, MPS_WEIGHT_RAW, t);
949 mpegts_input_close_pids(mi, mm, t, 1);
950 for (i = 0; i < x->count; i++) {
951 pi = &x->pids[i];
952 mpegts_input_open_pid(mi, mm, pi->pid, MPS_RAW, pi->weight, t, 0);
953 }
954 } else {
955 if (pids->all) {
956 mpegts_input_close_pids(mi, mm, t, 1);
957 mpegts_input_open_pid(mi, mm, MPEGTS_FULLMUX_PID, MPS_RAW, MPS_WEIGHT_RAW, t, 0);
958 } else {
959 mpegts_pid_compare(p, x, &add, &del);
960 for (i = 0; i < del.count; i++) {
961 pi = &del.pids[i];
962 mpegts_input_close_pid(mi, mm, pi->pid, MPS_RAW, pi->weight, t);
963 }
964 for (i = 0; i < add.count; i++) {
965 pi = &add.pids[i];
966 mpegts_input_open_pid(mi, mm, pi->pid, MPS_RAW, pi->weight, t, 0);
967 }
968 mpegts_pid_done(&add);
969 mpegts_pid_done(&del);
970 }
971 }
972 pthread_mutex_unlock(&t->s_stream_mutex);
973 pthread_mutex_unlock(&mi->mi_output_lock);
974 mpegts_mux_update_pids(mm);
975 } else {
976 pthread_mutex_lock(&t->s_stream_mutex);
977 x = t->s_pids;
978 t->s_pids = p;
979 pthread_mutex_unlock(&t->s_stream_mutex);
980 }
981 if (x) {
982 mpegts_pid_done(x);
983 free(x);
984 }
985 return 0;
986 }
987
988 void
mpegts_service_update_slave_pids(mpegts_service_t * s,int del)989 mpegts_service_update_slave_pids ( mpegts_service_t *s, int del )
990 {
991 mpegts_service_t *s2;
992 mpegts_apids_t *pids;
993 elementary_stream_t *st;
994 int i;
995
996 lock_assert(&s->s_stream_mutex);
997
998 if (s->s_pmt_pid == SERVICE_PMT_AUTO)
999 return;
1000
1001 pids = mpegts_pid_alloc();
1002
1003 mpegts_pid_add(pids, s->s_pmt_pid, MPS_WEIGHT_PMT);
1004 mpegts_pid_add(pids, s->s_pcr_pid, MPS_WEIGHT_PCR);
1005
1006 /* Ensure that filtered PIDs are not send in ts_recv_raw */
1007 TAILQ_FOREACH(st, &s->s_filt_components, es_filt_link)
1008 if ((s->s_scrambled_pass || st->es_type != SCT_CA) &&
1009 st->es_pid >= 0 && st->es_pid < 8192)
1010 mpegts_pid_add(pids, st->es_pid, mpegts_mps_weight(st));
1011
1012 for (i = 0; i < s->s_masters.is_count; i++) {
1013 s2 = (mpegts_service_t *)s->s_masters.is_array[i];
1014 pthread_mutex_lock(&s2->s_stream_mutex);
1015 if (!del)
1016 mpegts_pid_add_group(s2->s_slaves_pids, pids);
1017 else
1018 mpegts_pid_del_group(s2->s_slaves_pids, pids);
1019 pthread_mutex_unlock(&s2->s_stream_mutex);
1020 }
1021
1022 mpegts_pid_destroy(&pids);
1023 }
1024
1025 static int
mpegts_service_link(mpegts_service_t * master,mpegts_service_t * slave)1026 mpegts_service_link ( mpegts_service_t *master, mpegts_service_t *slave )
1027 {
1028 pthread_mutex_lock(&slave->s_stream_mutex);
1029 pthread_mutex_lock(&master->s_stream_mutex);
1030 assert(!idnode_set_exists(&slave->s_masters, &master->s_id));
1031 assert(LIST_SAFE_ENTRY(slave, s_slaves_link));
1032 idnode_set_alloc(&slave->s_masters, 16);
1033 idnode_set_add(&slave->s_masters, &master->s_id, NULL, NULL);
1034 LIST_INSERT_HEAD(&master->s_slaves, slave, s_slaves_link);
1035 pthread_mutex_unlock(&master->s_stream_mutex);
1036 mpegts_service_update_slave_pids(slave, 0);
1037 pthread_mutex_unlock(&slave->s_stream_mutex);
1038 return 0;
1039 }
1040
1041 static int
mpegts_service_unlink(mpegts_service_t * master,mpegts_service_t * slave)1042 mpegts_service_unlink ( mpegts_service_t *master, mpegts_service_t *slave )
1043 {
1044 pthread_mutex_lock(&slave->s_stream_mutex);
1045 mpegts_service_update_slave_pids(slave, 1);
1046 pthread_mutex_lock(&master->s_stream_mutex);
1047 idnode_set_remove(&slave->s_masters, &master->s_id);
1048 if (slave->s_masters.is_count == 0)
1049 idnode_set_clear(&slave->s_masters);
1050 LIST_SAFE_REMOVE(slave, s_slaves_link);
1051 pthread_mutex_unlock(&master->s_stream_mutex);
1052 pthread_mutex_unlock(&slave->s_stream_mutex);
1053 return 0;
1054 }
1055
1056 mpegts_service_t *
mpegts_service_create_raw(mpegts_mux_t * mm)1057 mpegts_service_create_raw ( mpegts_mux_t *mm )
1058 {
1059 mpegts_service_t *s = calloc(1, sizeof(*s));
1060 char buf[256];
1061
1062 mpegts_mux_nice_name(mm, buf, sizeof(buf));
1063
1064 if (service_create0((service_t*)s, STYPE_RAW,
1065 &mpegts_service_raw_class, NULL,
1066 S_MPEG_TS, NULL) == NULL) {
1067 free(s);
1068 return NULL;
1069 }
1070
1071 sbuf_init(&s->s_tsbuf);
1072
1073 s->s_dvb_mux = mm;
1074
1075 s->s_delete = mpegts_service_delete;
1076 s->s_is_enabled = mpegts_service_is_enabled;
1077 s->s_config_save = mpegts_service_config_save;
1078 s->s_enlist = mpegts_service_enlist_raw;
1079 s->s_start_feed = mpegts_service_start;
1080 s->s_stop_feed = mpegts_service_stop;
1081 s->s_refresh_feed = mpegts_service_refresh;
1082 s->s_setsourceinfo = mpegts_service_raw_setsourceinfo;
1083 s->s_grace_period = mpegts_service_grace_period;
1084 s->s_channel_number = mpegts_service_channel_number;
1085 s->s_channel_name = mpegts_service_channel_name;
1086 s->s_provider_name = mpegts_service_provider_name;
1087 s->s_channel_icon = mpegts_service_channel_icon;
1088 s->s_mapped = mpegts_service_mapped;
1089 s->s_update_pids = mpegts_service_raw_update_pids;
1090 s->s_link = mpegts_service_link;
1091 s->s_unlink = mpegts_service_unlink;
1092 s->s_satip_source = mpegts_service_satip_source;
1093 s->s_memoryinfo = mpegts_service_memoryinfo;
1094
1095 pthread_mutex_lock(&s->s_stream_mutex);
1096 free(s->s_nicename);
1097 s->s_nicename = strdup(buf);
1098 pthread_mutex_unlock(&s->s_stream_mutex);
1099
1100 tvhdebug(LS_MPEGTS, "%s - add raw service", buf);
1101
1102 return s;
1103 }
1104
1105 /******************************************************************************
1106 * Editor Configuration
1107 *
1108 * vim:sts=2:ts=2:sw=2:et
1109 *****************************************************************************/
1110