bouquet: freesat support
This commit is contained in:
parent
8812f5c51c
commit
ab51ae2f80
9 changed files with 459 additions and 55 deletions
|
@ -112,12 +112,17 @@ void
|
|||
bouquet_destroy_by_service(service_t *t)
|
||||
{
|
||||
bouquet_t *bq;
|
||||
service_lcn_t *sl;
|
||||
|
||||
lock_assert(&global_lock);
|
||||
|
||||
RB_FOREACH(bq, &bouquets, bq_link)
|
||||
if (idnode_set_exists(bq->bq_services, &t->s_id))
|
||||
idnode_set_remove(bq->bq_services, &t->s_id);
|
||||
while ((sl = LIST_FIRST(&t->s_lcns)) != NULL) {
|
||||
LIST_REMOVE(sl, sl_link);
|
||||
free(sl);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -150,8 +155,14 @@ bouquet_find_by_source(const char *name, const char *src, int create)
|
|||
|
||||
bqs.bq_src = (char *)src;
|
||||
bq = RB_FIND(&bouquets, &bqs, bq_link, _bq_cmp);
|
||||
if (bq)
|
||||
if (bq) {
|
||||
if (name && *name && strcmp(name, bq->bq_name)) {
|
||||
tvhwarn("bouquet", "bouquet name '%s' changed to '%s'", bq->bq_name ?: "", name);
|
||||
free(bq->bq_name);
|
||||
bq->bq_name = strdup(name);
|
||||
}
|
||||
return bq;
|
||||
}
|
||||
if (create && name)
|
||||
return bouquet_create(NULL, NULL, name, src);
|
||||
return NULL;
|
||||
|
@ -227,13 +238,30 @@ bouquet_map_channel(bouquet_t *bq, service_t *t)
|
|||
*
|
||||
*/
|
||||
void
|
||||
bouquet_add_service(bouquet_t *bq, service_t *s)
|
||||
bouquet_add_service(bouquet_t *bq, service_t *s, uint32_t lcn)
|
||||
{
|
||||
service_lcn_t *tl;
|
||||
|
||||
lock_assert(&global_lock);
|
||||
|
||||
if (!idnode_set_exists(bq->bq_services, &s->s_id)) {
|
||||
tvhtrace("bouquet", "add service %s to %s", s->s_nicename, bq->bq_name ?: "<unknown>");
|
||||
idnode_set_add(bq->bq_services, &s->s_id, NULL);
|
||||
|
||||
LIST_FOREACH(tl, &s->s_lcns, sl_link)
|
||||
if (tl->sl_bouquet == bq) {
|
||||
tl->sl_lcn = lcn;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!tl) {
|
||||
tl = calloc(1, sizeof(*tl));
|
||||
tl->sl_bouquet = bq;
|
||||
tl->sl_lcn = lcn;
|
||||
LIST_INSERT_HEAD(&s->s_lcns, tl, sl_link);
|
||||
}
|
||||
tl->sl_seen = 1;
|
||||
|
||||
bq->bq_saveflag = 1;
|
||||
if (bq->bq_enabled && bq->bq_maptoch)
|
||||
bouquet_map_channel(bq, s);
|
||||
|
@ -281,11 +309,17 @@ void
|
|||
bouquet_completed(bouquet_t *bq)
|
||||
{
|
||||
idnode_set_t *remove;
|
||||
service_t *s;
|
||||
service_lcn_t *lcn, *lcn_next;
|
||||
size_t z;
|
||||
|
||||
if (!bq)
|
||||
return;
|
||||
|
||||
tvhtrace("bouquet", "completed: active=%zi old=%zi",
|
||||
bq->bq_active_services->is_count, bq->bq_services->is_count);
|
||||
|
||||
/* Add/Remove services */
|
||||
remove = idnode_set_create();
|
||||
for (z = 0; z < bq->bq_services->is_count; z++)
|
||||
if (!idnode_set_exists(bq->bq_active_services, bq->bq_services->is_array[z]))
|
||||
|
@ -294,8 +328,27 @@ bouquet_completed(bouquet_t *bq)
|
|||
bouquet_remove_service(bq, (service_t *)remove->is_array[z]);
|
||||
idnode_set_free(remove);
|
||||
|
||||
/* Remove no longer used LCNs */
|
||||
for (z = 0; z < bq->bq_services->is_count; z++) {
|
||||
s = (service_t *)bq->bq_services->is_array[z];
|
||||
for (lcn = LIST_FIRST(&s->s_lcns); lcn; lcn = lcn_next) {
|
||||
lcn_next = LIST_NEXT(lcn, sl_link);
|
||||
if (lcn->sl_bouquet != bq) continue;
|
||||
if (!lcn->sl_seen) {
|
||||
LIST_REMOVE(lcn, sl_link);
|
||||
free(lcn);
|
||||
} else {
|
||||
lcn->sl_seen = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
idnode_set_free(bq->bq_active_services);
|
||||
bq->bq_active_services = idnode_set_create();
|
||||
|
||||
if (bq->bq_saveflag)
|
||||
bouquet_save(bq, 1);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -335,6 +388,20 @@ bouquet_notify_channels(bouquet_t *bq)
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
uint64_t
|
||||
bouquet_get_channel_number(bouquet_t *bq, service_t *t)
|
||||
{
|
||||
service_lcn_t *tl;
|
||||
|
||||
LIST_FOREACH(tl, &t->s_lcns, sl_link)
|
||||
if (tl->sl_bouquet == bq)
|
||||
return (int64_t)tl->sl_lcn * CHANNEL_SPLIT;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
@ -524,15 +591,19 @@ bouquet_class_chtag_ref_set ( void *obj, const void *p )
|
|||
static const void *
|
||||
bouquet_class_services_get ( void *obj )
|
||||
{
|
||||
htsmsg_t *l = htsmsg_create_list();
|
||||
htsmsg_t *m = htsmsg_create_map();
|
||||
bouquet_t *bq = obj;
|
||||
service_t *t;
|
||||
size_t z;
|
||||
|
||||
/* Add all */
|
||||
for (z = 0; z < bq->bq_services->is_count; z++)
|
||||
htsmsg_add_str(l, NULL, idnode_uuid_as_str(bq->bq_services->is_array[z]));
|
||||
for (z = 0; z < bq->bq_services->is_count; z++) {
|
||||
t = (service_t *)bq->bq_services->is_array[z];
|
||||
htsmsg_add_u32(m, idnode_uuid_as_str(&t->s_id),
|
||||
bouquet_get_channel_number(bq, t));
|
||||
}
|
||||
|
||||
return l;
|
||||
return m;
|
||||
}
|
||||
|
||||
static char *
|
||||
|
@ -696,7 +767,7 @@ bouquet_service_resolve(void)
|
|||
bouquet_t *bq;
|
||||
htsmsg_field_t *f;
|
||||
service_t *s;
|
||||
const char *str;
|
||||
uint32_t lcn;
|
||||
int saveflag;
|
||||
|
||||
lock_assert(&global_lock);
|
||||
|
@ -706,11 +777,10 @@ bouquet_service_resolve(void)
|
|||
continue;
|
||||
saveflag = bq->bq_saveflag;
|
||||
HTSMSG_FOREACH(f, bq->bq_services_waiting) {
|
||||
if ((str = htsmsg_field_get_str(f))) {
|
||||
s = service_find_by_identifier(str);
|
||||
if (s)
|
||||
bouquet_add_service(bq, s);
|
||||
}
|
||||
if (htsmsg_field_get_u32(f, &lcn)) continue;
|
||||
s = service_find_by_identifier(f->hmf_name);
|
||||
if (s)
|
||||
bouquet_add_service(bq, s, lcn);
|
||||
}
|
||||
htsmsg_destroy(bq->bq_services_waiting);
|
||||
bq->bq_services_waiting = NULL;
|
||||
|
|
|
@ -76,9 +76,11 @@ bouquet_t * bouquet_find_by_source(const char *name, const char *src, int create
|
|||
|
||||
void bouquet_map_to_channels(bouquet_t *bq);
|
||||
void bouquet_notify_channels(bouquet_t *bq);
|
||||
void bouquet_add_service(bouquet_t *bq, service_t *s);
|
||||
void bouquet_add_service(bouquet_t *bq, service_t *s, uint32_t lcn);
|
||||
void bouquet_completed(bouquet_t *bq);
|
||||
|
||||
uint64_t bouquet_get_channel_number(bouquet_t *bq, service_t *t);
|
||||
|
||||
void bouquet_save(bouquet_t *bq, int notify);
|
||||
|
||||
/**
|
||||
|
|
|
@ -569,9 +569,13 @@ channel_get_number ( channel_t *ch )
|
|||
if (ch->ch_number) {
|
||||
n = ch->ch_number;
|
||||
} else {
|
||||
LIST_FOREACH(csm, &ch->ch_services, csm_chn_link)
|
||||
LIST_FOREACH(csm, &ch->ch_services, csm_chn_link) {
|
||||
if (ch->ch_bouquet &&
|
||||
(n = bouquet_get_channel_number(ch->ch_bouquet, csm->csm_svc)))
|
||||
break;
|
||||
if ((n = service_get_channel_number(csm->csm_svc)))
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (n) {
|
||||
if (ch->ch_bouquet)
|
||||
|
@ -661,6 +665,7 @@ channel_get_icon ( channel_t *ch )
|
|||
ch->ch_icon = strdup(icn);
|
||||
channel_save(ch);
|
||||
idnode_notify_simple(&ch->ch_id);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -111,7 +111,6 @@ typedef struct mpegts_table_state
|
|||
int version;
|
||||
int complete;
|
||||
uint32_t sections[8];
|
||||
void *bouquet;
|
||||
RB_ENTRY(mpegts_table_state) link;
|
||||
} mpegts_table_state_t;
|
||||
|
||||
|
@ -172,6 +171,7 @@ struct mpegts_table
|
|||
char *mt_name;
|
||||
|
||||
void *mt_opaque;
|
||||
void *mt_bat;
|
||||
mpegts_table_callback_t mt_callback;
|
||||
|
||||
RB_HEAD(,mpegts_table_state) mt_state;
|
||||
|
|
|
@ -131,6 +131,9 @@ struct mpegts_mux;
|
|||
#define DVB_DESC_AAC 0x7C
|
||||
#define DVB_DESC_LOCAL_CHAN 0x83
|
||||
|
||||
#define DVB_DESC_FREESAT_LCN 0xD3
|
||||
#define DVB_DESC_FREESAT_REGIONS 0xD4
|
||||
|
||||
/* Service type lookup */
|
||||
|
||||
int dvb_servicetype_lookup ( int t );
|
||||
|
@ -202,7 +205,9 @@ int dvb_table_begin
|
|||
int tableid, uint64_t extraid, int minlen,
|
||||
struct mpegts_table_state **st, int *sect, int *last, int *ver);
|
||||
void dvb_table_reset
|
||||
(struct mpegts_table *mt );
|
||||
(struct mpegts_table *mt);
|
||||
void dvb_bat_destroy
|
||||
(struct mpegts_table *mt);
|
||||
|
||||
int dvb_pat_callback
|
||||
(struct mpegts_table *mt, const uint8_t *ptr, int len, int tableid);
|
||||
|
|
|
@ -33,6 +33,45 @@
|
|||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
typedef struct dvb_freesat_svc {
|
||||
TAILQ_ENTRY(dvb_freesat_svc) link;
|
||||
TAILQ_ENTRY(dvb_freesat_svc) region_link;
|
||||
uint16_t sid;
|
||||
uint16_t regionid;
|
||||
uint16_t lcn;
|
||||
mpegts_service_t *svc;
|
||||
} dvb_freesat_svc_t;
|
||||
|
||||
typedef struct dvb_freesat_region {
|
||||
LIST_ENTRY(dvb_freesat_region) link;
|
||||
TAILQ_HEAD(,dvb_freesat_svc) services;
|
||||
uint16_t regionid;
|
||||
char name[32];
|
||||
bouquet_t *bouquet;
|
||||
} dvb_freesat_region_t;
|
||||
|
||||
typedef struct dvb_bat_svc {
|
||||
TAILQ_ENTRY(dvb_bat_svc) link;
|
||||
mpegts_service_t *svc;
|
||||
dvb_freesat_svc_t *fallback;
|
||||
} dvb_bat_svc_t;
|
||||
|
||||
typedef struct dvb_bat_id {
|
||||
LIST_ENTRY(dvb_bat_id) link;
|
||||
uint32_t complete:1;
|
||||
uint32_t freesat:1;
|
||||
uint16_t nbid;
|
||||
char name[32];
|
||||
TAILQ_HEAD(,dvb_bat_svc) services;
|
||||
} dvb_bat_id_t;
|
||||
|
||||
typedef struct dvb_bat {
|
||||
int complete;
|
||||
LIST_HEAD(,dvb_bat_id) bats;
|
||||
LIST_HEAD(,dvb_freesat_region) fregions;
|
||||
TAILQ_HEAD(,dvb_freesat_svc) fservices;
|
||||
} dvb_bat_t;
|
||||
|
||||
SKEL_DECLARE(mpegts_table_state_skel, struct mpegts_table_state);
|
||||
|
||||
static int
|
||||
|
@ -323,10 +362,11 @@ dvb_desc_service
|
|||
|
||||
static int
|
||||
dvb_desc_service_list
|
||||
( const char *dstr, const uint8_t *ptr, int len, mpegts_mux_t *mm, bouquet_t *bq )
|
||||
( const char *dstr, const uint8_t *ptr, int len, mpegts_mux_t *mm, dvb_bat_id_t *bi )
|
||||
{
|
||||
uint16_t stype, sid;
|
||||
int i;
|
||||
dvb_bat_svc_t *bs;
|
||||
mpegts_service_t *s;
|
||||
for (i = 0; i < len; i += 3) {
|
||||
sid = (ptr[i] << 8) | ptr[i+1];
|
||||
|
@ -335,8 +375,11 @@ dvb_desc_service_list
|
|||
if (mm) {
|
||||
int save = 0;
|
||||
s = mpegts_service_find(mm, sid, 0, 1, &save);
|
||||
if (bq)
|
||||
bouquet_add_service(bq, (service_t *)s);
|
||||
if (bi) {
|
||||
bs = calloc(1, sizeof(*bs));
|
||||
bs->svc = s;
|
||||
TAILQ_INSERT_TAIL(&bi->services, bs, link);
|
||||
}
|
||||
if (save)
|
||||
s->s_config_save((service_t*)s);
|
||||
}
|
||||
|
@ -371,7 +414,150 @@ dvb_desc_local_channel
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* UK FreeSat
|
||||
*/
|
||||
|
||||
static void
|
||||
dvb_freesat_local_channels
|
||||
( dvb_bat_t *b, const char *dstr, const uint8_t *ptr, int len, uint16_t nbid )
|
||||
{
|
||||
uint16_t sid, unk, lcn, regionid;
|
||||
dvb_freesat_svc_t *fs;
|
||||
int len2;
|
||||
|
||||
while (len > 4) {
|
||||
sid = (ptr[0] << 8) | ptr[1];
|
||||
unk = (ptr[2] << 8) | ptr[3];
|
||||
len2 = ptr[4];
|
||||
ptr += 5;
|
||||
len -= 5;
|
||||
if (len2 > len)
|
||||
break;
|
||||
tvhtrace(dstr, " sid %04X (%d) uknown %04X (%d)\n", sid, sid, unk, unk);
|
||||
while (len2 > 3) {
|
||||
lcn = ((ptr[0] & 0x0f) << 8) | ptr[1];
|
||||
regionid = (ptr[2] << 8) | ptr[3];
|
||||
tvhtrace(dstr, " lcn %d region %d\n", lcn, regionid);
|
||||
|
||||
TAILQ_FOREACH(fs, &b->fservices, link)
|
||||
if (fs->sid == sid && fs->regionid == regionid)
|
||||
break;
|
||||
if (!fs) {
|
||||
fs = calloc(1, sizeof(*fs));
|
||||
fs->sid = sid;
|
||||
fs->regionid = regionid;
|
||||
fs->lcn = lcn;
|
||||
TAILQ_INSERT_TAIL(&b->fservices, fs, link);
|
||||
}
|
||||
ptr += 4;
|
||||
len -= 4;
|
||||
len2 -= 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
dvb_freesat_regions
|
||||
( dvb_bat_t *b, const char *dstr, const uint8_t *ptr, int len, uint16_t nbid )
|
||||
{
|
||||
uint16_t id;
|
||||
char name[32];
|
||||
dvb_freesat_region_t *fr;
|
||||
int r;
|
||||
|
||||
while (len > 5) {
|
||||
id = (ptr[0] << 8) | ptr[1];
|
||||
/* language: ptr[2-4]: 'eng' */
|
||||
if ((r = dvb_get_string_with_len(name, sizeof(name), ptr + 5, len - 5, NULL, NULL)) < 0)
|
||||
break;
|
||||
tvhtrace(dstr, " region %u - '%s'\n", id, name);
|
||||
|
||||
LIST_FOREACH(fr, &b->fregions, link)
|
||||
if (fr->regionid == id)
|
||||
break;
|
||||
if (!fr) {
|
||||
fr = calloc(1, sizeof(*fr));
|
||||
fr->regionid = id;
|
||||
strncpy(fr->name, name, sizeof(fr->name)-1);
|
||||
fr->name[sizeof(fr->name)-1] = '\0';
|
||||
TAILQ_INIT(&fr->services);
|
||||
LIST_INSERT_HEAD(&b->fregions, fr, link);
|
||||
}
|
||||
|
||||
ptr += 5 + r;
|
||||
len -= 5 + r;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
dvb_freesat_add_service
|
||||
( dvb_bat_id_t *bi, dvb_freesat_region_t *fr, mpegts_service_t *s, uint32_t lcn )
|
||||
{
|
||||
char name[64], src[64];
|
||||
if (!fr->bouquet) {
|
||||
snprintf(name, sizeof(name), "%s: %s", bi->name, fr->name);
|
||||
snprintf(src, sizeof(src), "dvb-freesat://28.2E,%04X,%u", bi->nbid, fr->regionid);
|
||||
fr->bouquet = bouquet_find_by_source(name, src, 1);
|
||||
}
|
||||
bouquet_add_service(fr->bouquet, (service_t *)s, lcn);
|
||||
}
|
||||
|
||||
static void
|
||||
dvb_freesat_completed
|
||||
( dvb_bat_t *b, dvb_bat_id_t *bi, const char *dstr, int nbid )
|
||||
{
|
||||
dvb_bat_svc_t *bs;
|
||||
dvb_freesat_svc_t *fs;
|
||||
dvb_freesat_region_t *fr;
|
||||
uint16_t sid;
|
||||
|
||||
/* Find all "fallback" services and region specific */
|
||||
TAILQ_FOREACH(bs, &bi->services, link) {
|
||||
sid = bs->svc->s_dvb_service_id;
|
||||
TAILQ_FOREACH(fs, &b->fservices, link)
|
||||
if (fs->sid == sid) {
|
||||
fs->svc = bs->svc;
|
||||
if ((fs->regionid == 0 && !bs->fallback) || fs->regionid == 65535) {
|
||||
bs->fallback = fs;
|
||||
continue;
|
||||
}
|
||||
LIST_FOREACH(fr, &b->fregions, link)
|
||||
if (fr->regionid == fs->regionid)
|
||||
break;
|
||||
if (!fr)
|
||||
tvhtrace(dstr, "cannot find freesat region id %u", fs->regionid);
|
||||
else
|
||||
TAILQ_INSERT_TAIL(&fr->services, fs, region_link);
|
||||
}
|
||||
}
|
||||
|
||||
/* create bouquets, one per region */
|
||||
LIST_FOREACH(fr, &b->fregions, link) {
|
||||
if (TAILQ_EMPTY(&fr->services)) continue;
|
||||
TAILQ_FOREACH(fs, &fr->services, region_link)
|
||||
dvb_freesat_add_service(bi, fr, fs->svc, fs->lcn);
|
||||
TAILQ_FOREACH(bs, &bi->services, link)
|
||||
if ((fs = bs->fallback) != NULL)
|
||||
dvb_freesat_add_service(bi, fr, bs->svc, fs->lcn);
|
||||
else
|
||||
dvb_freesat_add_service(bi, fr, bs->svc, 0);
|
||||
}
|
||||
|
||||
/* Remove all services associated to region, notify the completed status */
|
||||
LIST_FOREACH(fr, &b->fregions, link) {
|
||||
while ((fs = TAILQ_FIRST(&fr->services)) != NULL)
|
||||
TAILQ_REMOVE(&fr->services, fs, region_link);
|
||||
if (fr->bouquet) {
|
||||
bouquet_completed(fr->bouquet);
|
||||
fr->bouquet = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Clear all "fallback/default" services */
|
||||
TAILQ_FOREACH(bs, &bi->services, link)
|
||||
bs->fallback = NULL;
|
||||
}
|
||||
|
||||
/* **************************************************************************
|
||||
* Tables
|
||||
|
@ -711,12 +897,105 @@ dvb_pmt_callback
|
|||
/*
|
||||
* NIT/BAT processing (because its near identical)
|
||||
*/
|
||||
|
||||
static void
|
||||
dvb_bat_destroy_lists( mpegts_table_t *mt )
|
||||
{
|
||||
dvb_bat_t *b = mt->mt_bat;
|
||||
dvb_bat_id_t *bi;
|
||||
dvb_bat_svc_t *bs;
|
||||
dvb_freesat_region_t *fr;
|
||||
dvb_freesat_svc_t *fs;
|
||||
|
||||
while ((bi = LIST_FIRST(&b->bats)) != NULL) {
|
||||
while ((bs = TAILQ_FIRST(&bi->services)) != NULL) {
|
||||
TAILQ_REMOVE(&bi->services, bs, link);
|
||||
free(bs);
|
||||
}
|
||||
LIST_REMOVE(bi, link);
|
||||
free(bi);
|
||||
}
|
||||
while ((fr = LIST_FIRST(&b->fregions)) != NULL) {
|
||||
LIST_REMOVE(fr, link);
|
||||
free(fr);
|
||||
}
|
||||
while ((fs = TAILQ_FIRST(&b->fservices)) != NULL) {
|
||||
TAILQ_REMOVE(&b->fservices, fs, link);
|
||||
free(fs);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
dvb_bat_destroy( mpegts_table_t *mt )
|
||||
{
|
||||
dvb_bat_destroy_lists(mt);
|
||||
free(mt->mt_bat);
|
||||
mt->mt_bat = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
dvb_bat_completed
|
||||
( dvb_bat_t *b, const char *dstr, int tableid, int nbid, mpegts_mux_t *mux )
|
||||
{
|
||||
dvb_bat_id_t *bi;
|
||||
dvb_bat_svc_t *bs;
|
||||
char src[64];
|
||||
bouquet_t *bq;
|
||||
|
||||
b->complete = 1;
|
||||
|
||||
LIST_FOREACH(bi, &b->bats, link) {
|
||||
|
||||
if (bi->nbid != nbid) {
|
||||
if (!bi->complete)
|
||||
b->complete = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (bi->freesat) {
|
||||
dvb_freesat_completed(b, bi, dstr, nbid);
|
||||
goto complete;
|
||||
}
|
||||
|
||||
bq = NULL;
|
||||
|
||||
#if ENABLE_MPEGTS_DVB
|
||||
if (tableid == 0x4A /* BAT */) {
|
||||
if (idnode_is_instance(&mux->mm_id, &dvb_mux_dvbs_class)) {
|
||||
dvb_mux_conf_t *mc = &((dvb_mux_t *)mux)->lm_tuning;
|
||||
if (mc->u.dmc_fe_qpsk.orbital_dir) {
|
||||
char buf[16];
|
||||
dvb_sat_position_to_str(dvb_sat_position(mc), buf, sizeof(buf));
|
||||
snprintf(src, sizeof(src), "dvb-bouquet://dvbs,%s,%04X", buf, bi->nbid);
|
||||
}
|
||||
} else if (idnode_is_instance(&mux->mm_id, &dvb_mux_dvbt_class)) {
|
||||
snprintf(src, sizeof(src), "dvb-bouquet://dvbt,%04X", bi->nbid);
|
||||
} else if (idnode_is_instance(&mux->mm_id, &dvb_mux_dvbc_class)) {
|
||||
snprintf(src, sizeof(src), "dvb-bouquet://dvbc,%04X", bi->nbid);
|
||||
}
|
||||
if (src[0])
|
||||
bq = bouquet_find_by_source(bi->name, src, !TAILQ_EMPTY(&bi->services));
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!bq) continue;
|
||||
|
||||
TAILQ_FOREACH(bs, &bi->services, link)
|
||||
bouquet_add_service(bq, (service_t *)bs->svc, 0);
|
||||
|
||||
bouquet_completed(bq);
|
||||
|
||||
complete:
|
||||
bi->complete = 1;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
dvb_nit_callback
|
||||
(mpegts_table_t *mt, const uint8_t *ptr, int len, int tableid)
|
||||
{
|
||||
int save = 0;
|
||||
int r, sect, last, ver;
|
||||
int r, sect, last, ver, fsat = 0;
|
||||
uint8_t dtag;
|
||||
int llen, dllen, dlen;
|
||||
const uint8_t *lptr, *dlptr, *dptr;
|
||||
|
@ -726,26 +1005,33 @@ dvb_nit_callback
|
|||
char name[256], dauth[256];
|
||||
mpegts_table_state_t *st = NULL;
|
||||
bouquet_t *bq = NULL;
|
||||
dvb_bat_t *b = NULL;
|
||||
dvb_bat_id_t *bi = NULL;
|
||||
const char *charset;
|
||||
|
||||
/* Net/Bat ID */
|
||||
nbid = (ptr[0] << 8) | ptr[1];
|
||||
|
||||
/* Begin */
|
||||
if (tableid != 0x40 && tableid != 0x41 && tableid != 0x4A && tableid != 0xBC)
|
||||
if (tableid != 0x40 && tableid != 0x41 && tableid != 0x4A &&
|
||||
tableid != DVB_FASTSCAN_NIT_BASE)
|
||||
return -1;
|
||||
|
||||
r = dvb_table_begin(mt, ptr, len, tableid, nbid, 7, &st, §, &last, &ver);
|
||||
if (r == 0) {
|
||||
if (tableid != 0xBC /* fastscan */) {
|
||||
RB_FOREACH(st, &mt->mt_state, link)
|
||||
if (st->bouquet)
|
||||
bouquet_completed((bouquet_t *)st->bouquet);
|
||||
if (tableid == 0x4A) {
|
||||
if ((b = mt->mt_bat) != NULL) {
|
||||
if (!b->complete)
|
||||
dvb_bat_completed(b, mt->mt_name, tableid, nbid, mm);
|
||||
if (b->complete)
|
||||
dvb_bat_destroy_lists(mt);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (r != 1) return r;
|
||||
|
||||
/* NIT */
|
||||
if (tableid != 0x4A && tableid != 0xBC /* fastscan */) {
|
||||
if (tableid != 0x4A && tableid != DVB_FASTSCAN_NIT_BASE) {
|
||||
|
||||
/* Specific NID */
|
||||
if (mn->mn_nid) {
|
||||
|
@ -759,6 +1045,24 @@ dvb_nit_callback
|
|||
}
|
||||
}
|
||||
|
||||
/* BAT ID lookup */
|
||||
if (tableid == 0x4A) {
|
||||
if ((b = mt->mt_bat) == NULL) {
|
||||
b = calloc(1, sizeof(*b));
|
||||
TAILQ_INIT(&b->fservices);
|
||||
mt->mt_bat = b;
|
||||
}
|
||||
LIST_FOREACH(bi, &b->bats, link)
|
||||
if (bi->nbid == nbid)
|
||||
break;
|
||||
if (!bi) {
|
||||
bi = calloc(1, sizeof(*bi));
|
||||
bi->nbid = nbid;
|
||||
TAILQ_INIT(&bi->services);
|
||||
LIST_INSERT_HEAD(&b->bats, bi, link);
|
||||
}
|
||||
}
|
||||
|
||||
/* Network Descriptors */
|
||||
*name = 0;
|
||||
charset = dvb_charset_find(mn, NULL, NULL);
|
||||
|
@ -774,17 +1078,29 @@ dvb_nit_callback
|
|||
case DVB_DESC_MULTI_NETWORK_NAME:
|
||||
// TODO: implement this?
|
||||
break;
|
||||
case DVB_DESC_PRIVATE_DATA:
|
||||
if (tableid == 0x4A && dlen == 4 && !memcmp(dptr, "FSAT", 4))
|
||||
fsat = 1;
|
||||
break;
|
||||
case DVB_DESC_FREESAT_REGIONS:
|
||||
if (fsat)
|
||||
dvb_freesat_regions(b, mt->mt_name, dptr, dlen, nbid);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Fastscan */
|
||||
if (tableid == 0xBC) {
|
||||
if (tableid == DVB_FASTSCAN_NIT_BASE) {
|
||||
tvhdebug(mt->mt_name, "fastscan %04X (%d) [%s]", nbid, nbid, name);
|
||||
bq = mt->mt_opaque;
|
||||
|
||||
/* BAT */
|
||||
} else if (tableid == 0x4A) {
|
||||
tvhdebug(mt->mt_name, "bouquet %04X (%d) [%s]", nbid, nbid, name);
|
||||
if (bi && *name) {
|
||||
strncpy(bi->name, name, sizeof(bi->name)-1);
|
||||
bi->name[sizeof(bi->name)-1] = '\0';
|
||||
}
|
||||
|
||||
/* NIT */
|
||||
} else {
|
||||
|
@ -805,30 +1121,6 @@ dvb_nit_callback
|
|||
break;
|
||||
charset = dvb_charset_find(mn, mux, NULL);
|
||||
|
||||
#if ENABLE_MPEGTS_DVB
|
||||
dauth[0] = 0;
|
||||
if (!bq && *name && tableid == 0x4A /* BAT */) {
|
||||
if (idnode_is_instance(&mm->mm_id, &dvb_mux_dvbs_class)) {
|
||||
dvb_mux_conf_t *mc = &((dvb_mux_t *)mm)->lm_tuning;
|
||||
if (mc->u.dmc_fe_qpsk.orbital_dir) {
|
||||
char buf[16];
|
||||
dvb_sat_position_to_str(dvb_sat_position(mc), buf, sizeof(buf));
|
||||
snprintf(dauth, sizeof(dauth), "dvb-bouquet://dvbs,%s/%s", buf, name);
|
||||
}
|
||||
} else if (idnode_is_instance(&mux->mm_id, &dvb_mux_dvbt_class)) {
|
||||
snprintf(dauth, sizeof(dauth), "dvb-bouquet://dvbt/%s", name);
|
||||
} else if (idnode_is_instance(&mux->mm_id, &dvb_mux_dvbc_class)) {
|
||||
snprintf(dauth, sizeof(dauth), "dvb-bouquet://dvbc/%s", name);
|
||||
}
|
||||
}
|
||||
if (dauth[0]) {
|
||||
bouquet_t *bq2 = bouquet_find_by_source(name, dauth, 1);
|
||||
if (bq2 != bq && bq && bq->bq_saveflag)
|
||||
bouquet_save(bq, 1);
|
||||
bq = bq2;
|
||||
st->bouquet = bq;
|
||||
}
|
||||
#endif
|
||||
|
||||
tvhdebug(mt->mt_name, " onid %04X (%d) tsid %04X (%d) mux %p bq %p", onid, onid, tsid, tsid, mux, bq);
|
||||
|
||||
|
@ -887,9 +1179,19 @@ dvb_nit_callback
|
|||
return -1;
|
||||
break;
|
||||
case DVB_DESC_SERVICE_LIST:
|
||||
if (dvb_desc_service_list(mt->mt_name, dptr, dlen, mux, bq))
|
||||
if (dvb_desc_service_list(mt->mt_name, dptr, dlen, mux, bi))
|
||||
return -1;
|
||||
break;
|
||||
case DVB_DESC_PRIVATE_DATA:
|
||||
if (dlen == 4 && !memcmp(dptr, "FSAT", 4))
|
||||
fsat = 1;
|
||||
break;
|
||||
case DVB_DESC_FREESAT_LCN:
|
||||
if (tableid == 0x4A && fsat) {
|
||||
dvb_freesat_local_channels(b, mt->mt_name, dptr, dlen, nbid);
|
||||
bi->freesat = 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1163,7 +1465,7 @@ dvb_fs_sdt_callback
|
|||
mpegts_mux_t *mm = mt->mt_mux, *mux;
|
||||
mpegts_network_t *mn = mm->mm_network;
|
||||
mpegts_table_state_t *st = NULL;
|
||||
bouquet_t *bq = mt->mt_opaque;
|
||||
bouquet_t *bq = mt->mt_bat;
|
||||
|
||||
/* Fastscan ID */
|
||||
nbid = (ptr[0] << 8) | ptr[1];
|
||||
|
@ -1203,7 +1505,7 @@ dvb_fs_sdt_callback
|
|||
s = mpegts_service_find(mm, service_id, 0, 1, &save);
|
||||
charset = dvb_charset_find(mn, mm, s);
|
||||
if (bq && s)
|
||||
bouquet_add_service(bq, (service_t *)s);
|
||||
bouquet_add_service(bq, (service_t *)s, 0);
|
||||
|
||||
/* Descriptor loop */
|
||||
DVB_DESC_EACH(lptr, llen, dtag, dlen, dptr) {
|
||||
|
|
|
@ -142,6 +142,8 @@ mpegts_table_release_ ( mpegts_table_t *mt )
|
|||
tvhtrace("mpegts", "table: mux %p free %s %02X/%02X (%d) pid %04X (%d)",
|
||||
mt->mt_mux, mt->mt_name, mt->mt_table, mt->mt_mask, mt->mt_table,
|
||||
mt->mt_pid, mt->mt_pid);
|
||||
if (mt->mt_bat)
|
||||
dvb_bat_destroy(mt);
|
||||
if (mt->mt_destroy)
|
||||
mt->mt_destroy(mt);
|
||||
free(mt->mt_name);
|
||||
|
|
|
@ -107,7 +107,9 @@ prop_write_values
|
|||
|
||||
/* List */
|
||||
if (p->islist)
|
||||
new = htsmsg_field_get_list(f);
|
||||
new = (f->hmf_type == HMF_MAP) ?
|
||||
htsmsg_field_get_map(f) :
|
||||
htsmsg_field_get_list(f);
|
||||
|
||||
/* Singular */
|
||||
else {
|
||||
|
|
|
@ -180,6 +180,17 @@ void service_instance_destroy
|
|||
|
||||
void service_instance_list_clear(service_instance_list_t *sil);
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
typedef struct service_lcn {
|
||||
LIST_ENTRY(service_lcn) sl_link;
|
||||
void *sl_bouquet;
|
||||
uint32_t sl_lcn;
|
||||
uint8_t sl_seen;
|
||||
} service_lcn_t;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
@ -443,6 +454,11 @@ typedef struct service {
|
|||
|
||||
int64_t s_current_pts;
|
||||
|
||||
/*
|
||||
* Local channel numbers per bouquet
|
||||
*/
|
||||
LIST_HEAD(,service_lcn) s_lcns;
|
||||
|
||||
} service_t;
|
||||
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue