From: Jaroslav Kysela Date: Thu, 15 Oct 2015 20:17:49 +0000 (+0200) Subject: IPTV: Autonetwork - add linking to bouquets X-Git-Tag: v4.2.1~1899 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=52a1e2ee9533e533efa2551e62aa445822888efb;p=thirdparty%2Ftvheadend.git IPTV: Autonetwork - add linking to bouquets --- diff --git a/src/bouquet.c b/src/bouquet.c index 2f6f186ac..c12fa210b 100644 --- a/src/bouquet.c +++ b/src/bouquet.c @@ -500,6 +500,25 @@ bouquet_get_tag_number(bouquet_t *bq, service_t *t) return 0; } +/** + * + */ +void +bouquet_delete(bouquet_t *bq) +{ + if (bq == NULL) return; + bq->bq_enabled = 0; + bouquet_map_to_channels(bq); + if (!bq->bq_shield) { + hts_settings_remove("bouquet/%s", idnode_uuid_as_sstr(&bq->bq_id)); + bouquet_destroy(bq); + } else { + idnode_set_free(bq->bq_services); + bq->bq_services = idnode_set_create(1); + bouquet_save(bq, 1); + } +} + /** * */ @@ -530,18 +549,7 @@ bouquet_class_save(idnode_t *self) static void bouquet_class_delete(idnode_t *self) { - bouquet_t *bq = (bouquet_t *)self; - - bq->bq_enabled = 0; - bouquet_map_to_channels(bq); - if (!bq->bq_shield) { - hts_settings_remove("bouquet/%s", idnode_uuid_as_sstr(&bq->bq_id)); - bouquet_destroy(bq); - } else { - idnode_set_free(bq->bq_services); - bq->bq_services = idnode_set_create(1); - bouquet_save(bq, 1); - } + bouquet_delete((bouquet_t *)self); } static const char * diff --git a/src/bouquet.h b/src/bouquet.h index 351f9a23e..4df82e76c 100644 --- a/src/bouquet.h +++ b/src/bouquet.h @@ -70,6 +70,8 @@ htsmsg_t * bouquet_class_get_list(void *o, const char *lang); bouquet_t * bouquet_create(const char *uuid, htsmsg_t *conf, const char *name, const char *src); +void bouquet_delete(bouquet_t *bq); + void bouquet_destroy_by_service(service_t *t); void bouquet_destroy_by_channel_tag(channel_tag_t *ct); diff --git a/src/input/mpegts/iptv/iptv.c b/src/input/mpegts/iptv/iptv.c index bf823f2a2..12d421fad 100644 --- a/src/input/mpegts/iptv/iptv.c +++ b/src/input/mpegts/iptv/iptv.c @@ -23,6 +23,7 @@ #include "settings.h" #include "htsstr.h" #include "channels.h" +#include "bouquet.h" #include #include @@ -81,6 +82,43 @@ iptv_handler_find ( const char *scheme ) return RB_FIND(&iptv_handlers, &ih, link, ih_cmp); } +/* ************************************************************************** + * IPTV bouquet + * *************************************************************************/ + +static bouquet_t * +iptv_bouquet_get (iptv_network_t *in, int create) +{ + char buf[128]; + snprintf(buf, sizeof(buf), "iptv-network://%s", idnode_uuid_as_sstr(&in->mn_id)); + return bouquet_find_by_source(in->in_url, buf, create); +} + +static void +iptv_bouquet_update(void *aux) +{ + iptv_network_t *in = aux; + mpegts_mux_t *mm; + mpegts_service_t *ms; + bouquet_t *bq = in->in_bouquet ? iptv_bouquet_get(in, 1) : NULL; + uint32_t seen = 0; + if (bq == NULL) + return; + LIST_FOREACH(mm, &in->mn_muxes, mm_network_link) + LIST_FOREACH(ms, &mm->mm_services, s_dvb_mux_link) { + bouquet_add_service(bq, (service_t *)ms, ((iptv_mux_t *)mm)->mm_iptv_chnum, 0); + seen++; + } + bouquet_completed(bq, seen); +} + +void +iptv_bouquet_trigger(iptv_network_t *in, int timeout) +{ + gtimer_arm(&in->in_bouquet_timer, iptv_bouquet_update, in, timeout); +} + + /* ************************************************************************** * IPTV input * *************************************************************************/ @@ -90,6 +128,7 @@ iptv_input_class_get_title ( idnode_t *self, const char *lang ) { return tvh_gettext_lang(lang, N_("IPTV")); } + extern const idclass_t mpegts_input_class; const idclass_t iptv_input_class = { .ic_super = &mpegts_input_class, @@ -485,13 +524,17 @@ iptv_network_delete ( mpegts_network_t *mn, int delconf ) char *icon_url = in->in_icon_url; char *icon_url_sane = in->in_icon_url_sane; + gtimer_disarm(&in->in_bouquet_timer); + if (in->mn_id.in_class == &iptv_auto_network_class) iptv_auto_network_done(in); /* Remove config */ - if (delconf) + if (delconf) { hts_settings_remove("input/iptv/networks/%s", idnode_uuid_as_sstr(&in->mn_id)); + bouquet_delete(iptv_bouquet_get(in, 0)); + } /* delete */ free(in->in_remove_args); @@ -594,6 +637,22 @@ iptv_auto_network_class_notify_url( void *in, const char *lang ) iptv_auto_network_trigger(in); } +static void +iptv_auto_network_class_notify_bouquet( void *in, const char *lang ) +{ + iptv_network_t *mn = in; + bouquet_t *bq; + if (mn->in_bouquet) { + iptv_bouquet_trigger(mn, 0); + } else { + if (mn->in_bouquet) { + bq = iptv_bouquet_get(mn, 0); + if (bq) + bouquet_delete(bq); + } + } +} + static htsmsg_t * iptv_auto_network_class_charset_list(void *o, const char *lang) { @@ -617,6 +676,13 @@ const idclass_t iptv_auto_network_class = { .notify = iptv_auto_network_class_notify_url, .opts = PO_MULTILINE }, + { + .type = PT_BOOL, + .id = "bouquet", + .name = N_("Create bouquet"), + .off = offsetof(iptv_network_t, in_bouquet), + .notify = iptv_auto_network_class_notify_bouquet, + }, { .type = PT_STR, .id = "ctx_charset", diff --git a/src/input/mpegts/iptv/iptv_auto.c b/src/input/mpegts/iptv/iptv_auto.c index 85008f57b..694587f9c 100644 --- a/src/input/mpegts/iptv/iptv_auto.c +++ b/src/input/mpegts/iptv/iptv_auto.c @@ -190,6 +190,7 @@ iptv_auto_network_process_m3u_item(iptv_network_t *in, change = 1; } if (im->mm_iptv_chnum != chnum) { + iptv_bouquet_trigger(in, 0); /* propagate LCN change */ im->mm_iptv_chnum = chnum; change = 1; } diff --git a/src/input/mpegts/iptv/iptv_private.h b/src/input/mpegts/iptv/iptv_private.h index 2714a9f22..5415a26af 100644 --- a/src/input/mpegts/iptv/iptv_private.h +++ b/src/input/mpegts/iptv/iptv_private.h @@ -36,6 +36,8 @@ #define IPTV_KILL_USR1 4 #define IPTV_KILL_USR2 5 +struct bouquet; + extern pthread_mutex_t iptv_lock; typedef struct iptv_input iptv_input_t; @@ -81,6 +83,8 @@ struct iptv_network char *in_url; char *in_url_sane; + int in_bouquet; + gtimer_t in_bouquet_timer; char *in_ctx_charset; int64_t in_channel_number; uint32_t in_refetch_period; @@ -155,6 +159,8 @@ extern const idclass_t iptv_auto_network_class; extern iptv_input_t *iptv_input; extern iptv_network_t *iptv_network; + +void iptv_bouquet_trigger(iptv_network_t *in, int timeout); int iptv_url_set ( char **url, char **sane_url, const char *str, int allow_file, int allow_pipe ); void iptv_mux_load_all ( void ); diff --git a/src/input/mpegts/iptv/iptv_service.c b/src/input/mpegts/iptv/iptv_service.c index c3528b381..2d2b3762a 100644 --- a/src/input/mpegts/iptv/iptv_service.c +++ b/src/input/mpegts/iptv/iptv_service.c @@ -116,6 +116,7 @@ iptv_service_create0 ( iptv_mux_t *im, uint16_t sid, uint16_t pmt, const char *uuid, htsmsg_t *conf ) { + iptv_network_t *in = (iptv_network_t *)im->mm_network; iptv_service_t *is = (iptv_service_t*) mpegts_service_create0(calloc(1, sizeof(mpegts_service_t)), &mpegts_service_class, uuid, @@ -133,5 +134,8 @@ iptv_service_create0 if (im->mm_iptv_svcname) is->s_dvb_svcname = strdup(im->mm_iptv_svcname); + if (in->in_bouquet) + iptv_bouquet_trigger(in, 1); + return is; }