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