Project

General

Profile

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

Robert Cameron, 2018-04-29 22:28

View differences:

src/input/mpegts/dvb.h
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;
src/input/mpegts/dvb_support.c
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
	int r;
554

  
555
	r = sscanf(v, "%u%*[.-]%hu",
556
	  &lm->lm_tuning.dmc_fe_vchan.num,
557
	  &lm->lm_tuning.dmc_fe_vchan.minor);
558
	switch (r) {
559
	case 0:
560
		return 1;
561
	case 1:
562
		lm->lm_tuning.dmc_fe_vchan.minor = 0;
563
	}
564
	return 0;
565
}
566

  
535 567
dvb_mux_class_R(atsc_t, modulation, qam, qam,
536 568
                     DVB_MOD_QAM_AUTO, DVB_MOD_QAM_256, DVB_MOD_VSB_8);
537 569

  
......
557 589
      MUX_PROP_STR("modulation", N_("Modulation"), atsc_t, qam, N_("AUTO")),
558 590
      .desc     = N_("The modulation used on the mux."),
559 591
    },
592
    {
593
		.type	= PT_STR,
594
		.id	    = "vch",
595
		.name	= N_("Virtual channel"),
596
		.get	= dvb_mux_class_vchan_get,
597
		.set	= dvb_mux_class_vchan_set,
598
		.opts	= PO_ADVANCED,
599
	},
600
	{
601
		.type	= PT_U32,
602
		.id	    = "vch_num",
603
		.name	= N_("Virtual channel number"),
604
		.off	= offsetof(dvb_mux_t, lm_tuning.dmc_fe_vchan.num),
605
		.opts	= PO_RDONLY | PO_NOSAVE,
606
	},
607
	{
608
		.type	= PT_U16,
609
		.id	    = "vch_minor",
610
		.name	= N_("Virtual channel (minor)"),
611
		.off	= offsetof(dvb_mux_t, lm_tuning.dmc_fe_vchan.minor),
612
		.opts	= PO_RDONLY | PO_NOSAVE,
613
	},
614
	{
615
		.type	= PT_STR,
616
		.id	    = "vch_name",
617
		.name	= N_("Virtual channel name"),
618
		.off	= offsetof(dvb_mux_t, lm_tuning.dmc_fe_vchan.name),
619
		.opts	= PO_RDONLY | PO_NOSAVE,
620
	},
560 621
    {}
561 622
  }
562 623
};
......
610 671
      MUX_PROP_STR("fec", N_("FEC"), dvbc, fec, N_("AUTO")),
611 672
      .desc     = N_("The forward error correction used on the mux."),
612 673
    },
674
    {
675
		.type	= PT_STR,
676
		.id	    = "vch",
677
		.name	= N_("Virtual channel"),
678
		.get	= dvb_mux_class_vchan_get,
679
		.set	= dvb_mux_class_vchan_set,
680
		.opts	= PO_ADVANCED,
681
	},
682
	{
683
		.type	= PT_U32,
684
		.id	    = "vch_num",
685
		.name	= N_("Virtual channel number"),
686
		.off	= offsetof(dvb_mux_t, lm_tuning.dmc_fe_vchan.num),
687
		.opts	= PO_RDONLY | PO_NOSAVE,
688
	},
689
	{
690
		.type	= PT_U16,
691
		.id	    = "vch_minor",
692
		.name	= N_("Virtual channel (minor)"),
693
		.off	= offsetof(dvb_mux_t, lm_tuning.dmc_fe_vchan.minor),
694
		.opts	= PO_RDONLY | PO_NOSAVE,
695
	},
696
	{
697
		.type	= PT_STR,
698
		.id	    = "vch_name",
699
		.name	= N_("Virtual channel name"),
700
		.off	= offsetof(dvb_mux_t, lm_tuning.dmc_fe_vchan.name),
701
		.opts	= PO_RDONLY | PO_NOSAVE,
702
	},
613 703
    {}
614 704
  }
615 705
};
......
910 1000
dvb_mux_display_name ( mpegts_mux_t *mm, char *buf, size_t len )
911 1001
{
912 1002
  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';
1003

  
1004
  if (lm->lm_tuning.dmc_fe_vchan.num) {
1005
	if (!lm->lm_tuning.dmc_fe_vchan.minor)
1006
		snprintf(buf, len, "%u",
1007
		  lm->lm_tuning.dmc_fe_vchan.num);
1008
	else
1009
		snprintf(buf, len, "%u.%u",
1010
		  lm->lm_tuning.dmc_fe_vchan.num,
1011
		  lm->lm_tuning.dmc_fe_vchan.minor);
920 1012
  } else {
1013
    dvb_network_t *ln = (dvb_network_t*)mm->mm_network;
1014
    uint32_t freq = lm->lm_tuning.dmc_fe_freq, freq2;
1015
    char extra[8], buf2[5], *p;
1016
    if (ln->ln_type == DVB_TYPE_S) {
1017
      const char *s = dvb_pol2str(lm->lm_tuning.u.dmc_fe_qpsk.polarisation);
1018
      if (s) extra[0] = *s;
1019
      extra[1] = '\0';
1020
    } else {
1021
      freq /= 1000;
1022
      strcpy(extra, "MHz");
1023
    }
1024
    freq2 = freq % 1000;
921 1025
    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';
1026
    snprintf(buf2, sizeof(buf2), "%03d", freq2);
1027
    p = buf2 + 2;
1028
    while (freq2 && (freq2 % 10) == 0) {
1029
      freq2 /= 10;
1030
      *(p--) = '\0';
1031
    }
1032
    if (freq2)
1033
      snprintf(buf, len, "%d.%s%s", freq, buf2, extra);
1034
    else
1035
      snprintf(buf, len, "%d%s", freq, extra);
931 1036
  }
932
  if (freq2)
933
    snprintf(buf, len, "%d.%s%s", freq, buf2, extra);
934
  else
935
    snprintf(buf, len, "%d%s", freq, extra);
936 1037
}
937 1038

  
938 1039
static void
src/input/mpegts/mpegts_network_dvb.c
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 *
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
}
(2-2/2)