Project

General

Profile

Virtual Channel tuning for ATSC/CableCARD tuners (HDHomeR... » vch.patch

Robert Cameron, 2018-04-28 07:07

View differences:

src/input/mpegts/dvb.h
16 16
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
17 17
 */
18 18

  
19
/* 
19
/*
20 20
 * Based on:
21 21
 *
22 22
 * ITU-T Recommendation H.222.0 / ISO standard 13818-1
......
599 599
  } layers[3];
600 600
} dvb_isdbt_config_t;
601 601

  
602
typedef struct dvb_fe_vchan {
603
	uint32_t	num;
604
	uint16_t	minor;
605
	char	   *name;
606
} dvb_fe_vchan_t;
607

  
602 608
typedef struct dvb_mux_conf
603 609
{
604 610
  dvb_fe_type_t               dmc_fe_type;
605 611
  dvb_fe_delivery_system_t    dmc_fe_delsys;
606 612
  dvb_fe_modulation_t         dmc_fe_modulation;
607 613
  uint32_t                    dmc_fe_freq;
614
  dvb_fe_vchan_t	          dmc_fe_vchan;
608 615
  dvb_fe_spectral_inversion_t dmc_fe_inversion;
609 616
  dvb_fe_rolloff_t            dmc_fe_rolloff;
610 617
  dvb_fe_pilot_t              dmc_fe_pilot;
......
620 627

  
621 628
  // For scan file configurations
622 629
  LIST_ENTRY(dvb_mux_conf)    dmc_link;
623
  
630

  
624 631
} dvb_mux_conf_t;
625 632

  
626 633
/* conversion routines */
src/input/mpegts/dvb_support.c
252 252

  
253 253
int
254 254
dvb_get_string
255
  (char *dst, size_t dstlen, const uint8_t *src, size_t srclen, 
255
  (char *dst, size_t dstlen, const uint8_t *src, size_t srclen,
256 256
   const char *dvb_charset, dvb_string_conv_t *conv)
257 257
{
258 258
  int ic = -1;
......
302 302
    ic = convert_iso_8859[src[2]];
303 303
    src+=3; srclen-=3;
304 304
    break;
305
    
305

  
306 306
  case 0x11:
307 307
    ic = convert_ucs2;
308 308
    src++; srclen--;
......
376 376

  
377 377

  
378 378
int
379
dvb_get_string_with_len(char *dst, size_t dstlen, 
379
dvb_get_string_with_len(char *dst, size_t dstlen,
380 380
			const uint8_t *buf, size_t buflen, const char *dvb_charset,
381 381
      dvb_string_conv_t *conv)
382 382
{
......
1105 1105
           dmc->u.dmc_fe_isdbt.layers[2].time_interleaving);
1106 1106
}
1107 1107

  
1108
static int
1109
dvb_mux_conf_str_vchan(dvb_mux_conf_t *dmc, char *buf, size_t bufsize)
1110
{
1111
	if (!dmc->dmc_fe_vchan.minor)
1112
		return snprintf(buf, bufsize,
1113
		  "%s channel %u",
1114
		  dvb_type2str(dmc->dmc_fe_type),
1115
		  dmc->dmc_fe_vchan.num);
1116
	else
1117
		return snprintf(buf, bufsize,
1118
		  "%s channel %u.%u",
1119
		  dvb_type2str(dmc->dmc_fe_type),
1120
		  dmc->dmc_fe_vchan.num,
1121
		  dmc->dmc_fe_vchan.minor);
1122
}
1123

  
1108 1124
int
1109 1125
dvb_mux_conf_str ( dvb_mux_conf_t *dmc, char *buf, size_t bufsize )
1110 1126
{
1127
	if (dmc->dmc_fe_vchan.num)
1128
		return dvb_mux_conf_str_vchan(dmc, buf, bufsize);
1111 1129
  switch (dmc->dmc_fe_type) {
1112 1130
  case DVB_TYPE_NONE:
1113 1131
    return
src/input/mpegts/mpegts_mux_dvb.c
532 532
  return list;
533 533
}
534 534

  
535
static const void *
536
dvb_mux_class_vchan_get(void *o)
537
{
538
	dvb_mux_t *lm = (dvb_mux_t *)o;
539
	if (!lm->lm_tuning.dmc_fe_vchan.minor)
540
		snprintf(prop_sbuf, PROP_SBUF_LEN, "%u",
541
		  lm->lm_tuning.dmc_fe_vchan.num);
542
	else
543
		snprintf(prop_sbuf, PROP_SBUF_LEN, "%u.%u",
544
		  lm->lm_tuning.dmc_fe_vchan.num,
545
		  lm->lm_tuning.dmc_fe_vchan.minor);
546
	return &prop_sbuf_ptr;
547
}
548

  
549
static int
550
dvb_mux_class_vchan_set(void *o, const void *v)
551
{
552
	dvb_mux_t *lm = (dvb_mux_t *)o;
553

  
554
	lm->lm_tuning.dmc_fe_vchan.minor = 0;
555
	sscanf(v, "%u%*[.-]%hu",
556
	  &lm->lm_tuning.dmc_fe_vchan.num,
557
	  &lm->lm_tuning.dmc_fe_vchan.minor);
558
	return 0;
559
}
560

  
535 561
dvb_mux_class_R(atsc_t, modulation, qam, qam,
536 562
                     DVB_MOD_QAM_AUTO, DVB_MOD_QAM_256, DVB_MOD_VSB_8);
537 563

  
......
557 583
      MUX_PROP_STR("modulation", N_("Modulation"), atsc_t, qam, N_("AUTO")),
558 584
      .desc     = N_("The modulation used on the mux."),
559 585
    },
586
    {
587
		.type	= PT_STR,
588
		.id	    = "vch",
589
		.name	= N_("Virtual channel"),
590
		.get	= dvb_mux_class_vchan_get,
591
		.set	= dvb_mux_class_vchan_set,
592
		.opts	= PO_ADVANCED,
593
	},
594
	{
595
		.type	= PT_U32,
596
		.id	    = "vch_num",
597
		.name	= N_("Virtual channel number"),
598
		.off	= offsetof(dvb_mux_t, lm_tuning.dmc_fe_vchan.num),
599
		.opts	= PO_RDONLY | PO_NOSAVE,
600
	},
601
	{
602
		.type	= PT_U16,
603
		.id	    = "vch_minor",
604
		.name	= N_("Virtual channel (minor)"),
605
		.off	= offsetof(dvb_mux_t, lm_tuning.dmc_fe_vchan.minor),
606
		.opts	= PO_RDONLY | PO_NOSAVE,
607
	},
608
	{
609
		.type	= PT_STR,
610
		.id	    = "vch_name",
611
		.name	= N_("Virtual channel name"),
612
		.off	= offsetof(dvb_mux_t, lm_tuning.dmc_fe_vchan.name),
613
		.opts	= PO_RDONLY | PO_NOSAVE,
614
	},
560 615
    {}
561 616
  }
562 617
};
......
610 665
      MUX_PROP_STR("fec", N_("FEC"), dvbc, fec, N_("AUTO")),
611 666
      .desc     = N_("The forward error correction used on the mux."),
612 667
    },
668
    {
669
		.type	= PT_STR,
670
		.id	    = "vch",
671
		.name	= N_("Virtual channel"),
672
		.get	= dvb_mux_class_vchan_get,
673
		.set	= dvb_mux_class_vchan_set,
674
		.opts	= PO_ADVANCED,
675
	},
676
	{
677
		.type	= PT_U32,
678
		.id	    = "vch_num",
679
		.name	= N_("Virtual channel number"),
680
		.off	= offsetof(dvb_mux_t, lm_tuning.dmc_fe_vchan.num),
681
		.opts	= PO_RDONLY | PO_NOSAVE,
682
	},
683
	{
684
		.type	= PT_U16,
685
		.id	    = "vch_minor",
686
		.name	= N_("Virtual channel (minor)"),
687
		.off	= offsetof(dvb_mux_t, lm_tuning.dmc_fe_vchan.minor),
688
		.opts	= PO_RDONLY | PO_NOSAVE,
689
	},
690
	{
691
		.type	= PT_STR,
692
		.id	    = "vch_name",
693
		.name	= N_("Virtual channel name"),
694
		.off	= offsetof(dvb_mux_t, lm_tuning.dmc_fe_vchan.name),
695
		.opts	= PO_RDONLY | PO_NOSAVE,
696
	},
613 697
    {}
614 698
  }
615 699
};
......
910 994
dvb_mux_display_name ( mpegts_mux_t *mm, char *buf, size_t len )
911 995
{
912 996
  dvb_mux_t *lm = (dvb_mux_t*)mm;
913
  dvb_network_t *ln = (dvb_network_t*)mm->mm_network;
914
  uint32_t freq = lm->lm_tuning.dmc_fe_freq, freq2;
915
  char extra[8], buf2[5], *p;
916
  if (ln->ln_type == DVB_TYPE_S) {
917
    const char *s = dvb_pol2str(lm->lm_tuning.u.dmc_fe_qpsk.polarisation);
918
    if (s) extra[0] = *s;
919
    extra[1] = '\0';
997

  
998
  if (lm->lm_tuning.dmc_fe_vchan.num) {
999
	if (!lm->lm_tuning.dmc_fe_vchan.minor)
1000
		snprintf(buf, len, "%u",
1001
		  lm->lm_tuning.dmc_fe_vchan.num);
1002
	else
1003
		snprintf(buf, len, "%u.%u",
1004
		  lm->lm_tuning.dmc_fe_vchan.num,
1005
		  lm->lm_tuning.dmc_fe_vchan.minor);
920 1006
  } else {
1007
    dvb_network_t *ln = (dvb_network_t*)mm->mm_network;
1008
    uint32_t freq = lm->lm_tuning.dmc_fe_freq, freq2;
1009
    char extra[8], buf2[5], *p;
1010
    if (ln->ln_type == DVB_TYPE_S) {
1011
      const char *s = dvb_pol2str(lm->lm_tuning.u.dmc_fe_qpsk.polarisation);
1012
      if (s) extra[0] = *s;
1013
      extra[1] = '\0';
1014
    } else {
1015
      freq /= 1000;
1016
      strcpy(extra, "MHz");
1017
    }
1018
    freq2 = freq % 1000;
921 1019
    freq /= 1000;
922
    strcpy(extra, "MHz");
923
  }
924
  freq2 = freq % 1000;
925
  freq /= 1000;
926
  snprintf(buf2, sizeof(buf2), "%03d", freq2);
927
  p = buf2 + 2;
928
  while (freq2 && (freq2 % 10) == 0) {
929
    freq2 /= 10;
930
    *(p--) = '\0';
1020
    snprintf(buf2, sizeof(buf2), "%03d", freq2);
1021
    p = buf2 + 2;
1022
    while (freq2 && (freq2 % 10) == 0) {
1023
      freq2 /= 10;
1024
      *(p--) = '\0';
1025
    }
1026
    if (freq2)
1027
      snprintf(buf, len, "%d.%s%s", freq, buf2, extra);
1028
    else
1029
      snprintf(buf, len, "%d%s", freq, extra);
931 1030
  }
932
  if (freq2)
933
    snprintf(buf, len, "%d.%s%s", freq, buf2, extra);
934
  else
935
    snprintf(buf, len, "%d%s", freq, extra);
936 1031
}
937 1032

  
938 1033
static void
src/input/mpegts/mpegts_network_dvb.c
47 47
  char ubuf[UUID_HEX_SIZE];
48 48

  
49 49
  /* remove config */
50
  hts_settings_remove("input/dvb/networks/%s", 
50
  hts_settings_remove("input/dvb/networks/%s",
51 51
                      idnode_uuid_as_str(in, ubuf));
52 52

  
53 53
  /* Parent delete */
......
792 792
}
793 793

  
794 794
static mpegts_service_t *
795
dvb_network_create_service
796
  ( mpegts_mux_t *mm, uint16_t sid, uint16_t pmt_pid )
795
dvb_network_create_service(mpegts_mux_t *mm, uint16_t sid, uint16_t pmt_pid)
797 796
{
798
  return mpegts_service_create1(NULL, mm, sid, pmt_pid, NULL);
797
	dvb_mux_t	        *lm = (dvb_mux_t *)mm;
798
	mpegts_network_t	*ln = mm->mm_network;
799
	mpegts_service_t	*s;
800

  
801
	s = mpegts_service_create1(NULL, mm, sid, pmt_pid, NULL);
802
	if (lm->lm_tuning.dmc_fe_vchan.num) {
803
		if (!s->s_dvb_provider && ln->mn_provider_network_name)
804
			s->s_dvb_provider = strdup(ln->mn_provider_network_name);
805
		if (!s->s_dvb_channel_num)
806
			s->s_dvb_channel_num = lm->lm_tuning.dmc_fe_vchan.num;
807
		if (!s->s_dvb_channel_minor && lm->lm_tuning.dmc_fe_vchan.minor)
808
			s->s_dvb_channel_minor = lm->lm_tuning.dmc_fe_vchan.minor;
809
		if (!s->s_dvb_svcname && lm->lm_tuning.dmc_fe_vchan.name)
810
			s->s_dvb_svcname = lm->lm_tuning.dmc_fe_vchan.name;
811
	}
812
	return s;
799 813
}
800 814

  
801 815
static mpegts_mux_t *
......
829 843
  if (!(ln = (dvb_network_t*)mpegts_network_create0((void*)ln,
830 844
                                     idc, uuid, NULL, conf)))
831 845
    return NULL;
832
  
846

  
833 847
  /* Callbacks */
834 848
  ln->mn_create_mux     = dvb_network_create_mux;
835 849
  ln->mn_create_service = dvb_network_create_service;
......
912 926
  for (i = 0; i < ARRAY_SIZE(dvb_network_classes); i++)
913 927
    mpegts_network_register_builder(dvb_network_classes[i],
914 928
                                    dvb_network_builder);
915
  
929

  
916 930
  /* Load settings */
917 931
  if (!(c = hts_settings_load_r(1, "input/dvb/networks")))
918 932
    return;
src/input/mpegts/tvhdhomerun/tvhdhomerun.c
323 323
  } else {
324 324
    if (strstr(hd->hd_info.deviceModel, "_atsc"))
325 325
      type = DVB_TYPE_ATSC_T;
326
    if (strstr(hd->hd_info.deviceModel, "_cablecard"))
327
      type = DVB_TYPE_ATSC_C;
326 328
  }
327 329

  
328 330
  hd->hd_override_type = strdup(dvb_type2str(type));
src/input/mpegts/tvhdhomerun/tvhdhomerun_frontend.c
254 254
      tvhdebug(LS_TVHDHOMERUN, "locked");
255 255
      hfe->hf_locked = 1;
256 256

  
257
      /* Set vchan.name from status */
258
      dvb_mux_t *lm = (dvb_mux_t *)mm;
259
      struct hdhomerun_tuner_vstatus_t tuner_vstatus;
260
      char *tuner_vstatus_str;
261
      pthread_mutex_lock(&hfe->hf_hdhomerun_device_mutex);
262
      res = hdhomerun_device_get_tuner_vstatus(hfe->hf_hdhomerun_tuner,
263
        &tuner_vstatus_str, &tuner_vstatus);
264
      pthread_mutex_unlock(&hfe->hf_hdhomerun_device_mutex);
265
      if (res < 1)
266
        tvhwarn(LS_TVHDHOMERUN, "tuner_vstatus (%d)", res);
267
      lm->lm_tuning.dmc_fe_vchan.name = strdup(tuner_vstatus.name);
268

  
257 269
      /* start input thread */
258 270
      tvh_pipe(O_NONBLOCK, &hfe->hf_input_thread_pipe);
259 271
      pthread_mutex_lock(&hfe->hf_input_thread_mutex);
......
366 378
  int res;
367 379
  char *perror;
368 380

  
369
  /* resolve the modulation type */
370
  switch (dmc->dmc_fe_type) {
371
    case DVB_TYPE_C:
372
      /* the symbol rate */
373
      symbol_rate = dmc->u.dmc_fe_qam.symbol_rate / 1000;
374
      switch(dmc->dmc_fe_modulation) {
375
        case DVB_MOD_QAM_64:
376
          snprintf(channel_buf, sizeof(channel_buf), "a8qam64-%d:%u", symbol_rate, dmc->dmc_fe_freq);
377
          break;
378
        case DVB_MOD_QAM_256:
379
          snprintf(channel_buf, sizeof(channel_buf), "a8qam256-%d:%u", symbol_rate, dmc->dmc_fe_freq);
380
          break;
381
        default:
382
          snprintf(channel_buf, sizeof(channel_buf), "auto:%u", dmc->dmc_fe_freq);
383
          break;
384
      }
385
      break;
386
    case DVB_TYPE_T:
387
      bandwidth = dmc->u.dmc_fe_ofdm.bandwidth / 1000UL;
388
      switch (dmc->dmc_fe_modulation) {
389
        case DVB_MOD_AUTO:
390
            if (dmc->u.dmc_fe_ofdm.bandwidth == DVB_BANDWIDTH_AUTO) {
391
                snprintf(channel_buf, sizeof(channel_buf), "auto:%u", dmc->dmc_fe_freq);
392
            } else {
393
                snprintf(channel_buf, sizeof(channel_buf), "auto%dt:%u", bandwidth, dmc->dmc_fe_freq);
394
            }
395
            break;
396
        case DVB_MOD_QAM_256:
397
            if (dmc->dmc_fe_delsys == DVB_SYS_DVBT2) {
398
                snprintf(channel_buf, sizeof(channel_buf), "tt%dqam256:%u", bandwidth, dmc->dmc_fe_freq);
399
            } else {
400
                snprintf(channel_buf, sizeof(channel_buf), "t%dqam256:%u", bandwidth, dmc->dmc_fe_freq);
401
            }
381
  if (dmc->dmc_fe_vchan.num) {
382
    if (!dmc->dmc_fe_vchan.minor)
383
      snprintf(channel_buf, sizeof(channel_buf), "%u", dmc->dmc_fe_vchan.num);
384
    else
385
      snprintf(channel_buf, sizeof(channel_buf), "%u.%u", dmc->dmc_fe_vchan.num, dmc->dmc_fe_vchan.minor);
386
  } else {
387
    /* resolve the modulation type */
388
    switch (dmc->dmc_fe_type) {
389
      case DVB_TYPE_C:
390
        /* the symbol rate */
391
        symbol_rate = dmc->u.dmc_fe_qam.symbol_rate / 1000;
392
        switch(dmc->dmc_fe_modulation) {
393
          case DVB_MOD_QAM_64:
394
            snprintf(channel_buf, sizeof(channel_buf), "a8qam64-%d:%u", symbol_rate, dmc->dmc_fe_freq);
402 395
            break;
403
        case DVB_MOD_QAM_64:
404
            if (dmc->dmc_fe_delsys == DVB_SYS_DVBT2) {
405
                snprintf(channel_buf, sizeof(channel_buf), "tt%dqam64:%u", bandwidth, dmc->dmc_fe_freq);
406
            } else {
407
                snprintf(channel_buf, sizeof(channel_buf), "t%dqam64:%u", bandwidth, dmc->dmc_fe_freq);
408
            }
396
          case DVB_MOD_QAM_256:
397
            snprintf(channel_buf, sizeof(channel_buf), "a8qam256-%d:%u", symbol_rate, dmc->dmc_fe_freq);
409 398
            break;
410
        default:
411
            /* probably won't work but never mind */
399
          default:
412 400
            snprintf(channel_buf, sizeof(channel_buf), "auto:%u", dmc->dmc_fe_freq);
413 401
            break;
414
      }
415
      break;
416
    default:
417
      snprintf(channel_buf, sizeof(channel_buf), "auto:%u", dmc->dmc_fe_freq);
418
      break;
402
        }
403
        break;
404
      case DVB_TYPE_T:
405
        bandwidth = dmc->u.dmc_fe_ofdm.bandwidth / 1000UL;
406
        switch (dmc->dmc_fe_modulation) {
407
          case DVB_MOD_AUTO:
408
              if (dmc->u.dmc_fe_ofdm.bandwidth == DVB_BANDWIDTH_AUTO) {
409
                  snprintf(channel_buf, sizeof(channel_buf), "auto:%u", dmc->dmc_fe_freq);
410
              } else {
411
                  snprintf(channel_buf, sizeof(channel_buf), "auto%dt:%u", bandwidth, dmc->dmc_fe_freq);
412
              }
413
              break;
414
          case DVB_MOD_QAM_256:
415
              if (dmc->dmc_fe_delsys == DVB_SYS_DVBT2) {
416
                  snprintf(channel_buf, sizeof(channel_buf), "tt%dqam256:%u", bandwidth, dmc->dmc_fe_freq);
417
              } else {
418
                  snprintf(channel_buf, sizeof(channel_buf), "t%dqam256:%u", bandwidth, dmc->dmc_fe_freq);
419
              }
420
              break;
421
          case DVB_MOD_QAM_64:
422
              if (dmc->dmc_fe_delsys == DVB_SYS_DVBT2) {
423
                  snprintf(channel_buf, sizeof(channel_buf), "tt%dqam64:%u", bandwidth, dmc->dmc_fe_freq);
424
              } else {
425
                  snprintf(channel_buf, sizeof(channel_buf), "t%dqam64:%u", bandwidth, dmc->dmc_fe_freq);
426
              }
427
              break;
428
          default:
429
              /* probably won't work but never mind */
430
              snprintf(channel_buf, sizeof(channel_buf), "auto:%u", dmc->dmc_fe_freq);
431
              break;
432
        }
433
        break;
434
      default:
435
        snprintf(channel_buf, sizeof(channel_buf), "auto:%u", dmc->dmc_fe_freq);
436
        break;
437
    }
419 438
  }
420 439

  
421 440
  tvhinfo(LS_TVHDHOMERUN, "tuning to %s", channel_buf);
......
427 446
    tvherror(LS_TVHDHOMERUN, "failed to acquire lockkey: %s", perror);
428 447
    return SM_CODE_TUNING_FAILED;
429 448
  }
430
  res = hdhomerun_device_set_tuner_channel(hfe->hf_hdhomerun_tuner, channel_buf);
449
  if (dmc->dmc_fe_vchan.num)
450
    res = hdhomerun_device_set_tuner_vchannel(hfe->hf_hdhomerun_tuner, channel_buf);
451
  else
452
    res = hdhomerun_device_set_tuner_channel(hfe->hf_hdhomerun_tuner, channel_buf);
431 453
  pthread_mutex_unlock(&hfe->hf_hdhomerun_device_mutex);
432 454
  if(res < 1) {
433 455
    tvherror(LS_TVHDHOMERUN, "failed to tune to %s", channel_buf);
......
448 470
  ( mpegts_input_t *mi, mpegts_mux_instance_t *mmi, int weight )
449 471
{
450 472
  tvhdhomerun_frontend_t *hfe = (tvhdhomerun_frontend_t*)mi;
451
  int res, r;
473
  dvb_mux_t *lm = (dvb_mux_t *)mmi->mmi_mux;
474
  int res;
452 475
  char buf1[256], buf2[256];
453 476

  
454 477
  mi->mi_display_name(mi, buf1, sizeof(buf1));
......
459 482
  res = tvhdhomerun_frontend_tune(hfe, mmi);
460 483

  
461 484
  /* reset the pfilters */
462
  pthread_mutex_lock(&hfe->hf_hdhomerun_device_mutex);
463
  r = hdhomerun_device_set_tuner_filter(hfe->hf_hdhomerun_tuner, "0x0000");
464
  pthread_mutex_unlock(&hfe->hf_hdhomerun_device_mutex);
465
  if(r < 1)
466
    tvherror(LS_TVHDHOMERUN, "failed to reset pfilter: %d", r);
485
  if (!lm->lm_tuning.dmc_fe_vchan.num) {
486
    int r;
487
    pthread_mutex_lock(&hfe->hf_hdhomerun_device_mutex);
488
    r = hdhomerun_device_set_tuner_filter(hfe->hf_hdhomerun_tuner, "0x0000");
489
    pthread_mutex_unlock(&hfe->hf_hdhomerun_device_mutex);
490
    if(r < 1)
491
      tvherror(LS_TVHDHOMERUN, "failed to reset pfilter: %d", r);
492
  }
467 493

  
468 494
  return res;
469 495
}
(1-1/2)