diff --git a/src/bouquet.c b/src/bouquet.c index 202b7c57..daa7384d 100644 --- a/src/bouquet.c +++ b/src/bouquet.c @@ -98,6 +98,8 @@ bouquet_destroy(bouquet_t *bq) idnode_set_free(bq->bq_active_services); idnode_set_free(bq->bq_services); + assert(bq->bq_services_waiting == NULL); + free((char *)bq->bq_chtag_waiting); free(bq->bq_name); free(bq->bq_src); free(bq); @@ -118,6 +120,21 @@ bouquet_destroy_by_service(service_t *t) idnode_set_remove(bq->bq_services, &t->s_id); } +/** + * + */ +void +bouquet_destroy_by_channel_tag(channel_tag_t *ct) +{ + bouquet_t *bq; + + lock_assert(&global_lock); + + RB_FOREACH(bq, &bouquets, bq_link) + if (bq->bq_chtag_ptr == ct) + bq->bq_chtag_ptr = NULL; +} + /* * */ @@ -146,10 +163,24 @@ bouquet_find_by_source(const char *name, const char *src, int create) static channel_tag_t * bouquet_tag(bouquet_t *bq, int create) { + channel_tag_t *ct; char buf[128]; - /* TODO: cache the channel_tag_t * pointer */ + + assert(!bq->bq_in_load); + if (bq->bq_chtag_waiting) { + bq->bq_chtag_ptr = channel_tag_find_by_uuid(bq->bq_chtag_waiting); + free((char *)bq->bq_chtag_waiting); + bq->bq_chtag_waiting = NULL; + } + if (bq->bq_chtag_ptr) + return bq->bq_chtag_ptr; snprintf(buf, sizeof(buf), "*** %s", bq->bq_name ?: "???"); - return channel_tag_find_by_name(buf, create); + ct = channel_tag_find_by_name(buf, create); + if (ct) { + bq->bq_chtag_ptr = ct; + bouquet_save(bq, 0); + } + return ct; } /* @@ -386,6 +417,8 @@ bouquet_class_mapnolcn_notify ( void *obj ) service_t *t; size_t z; + if (bq->bq_in_load) + return; if (!bq->bq_mapnolcn && bq->bq_enabled && bq->bq_maptoch) { for (z = 0; z < bq->bq_services->is_count; z++) { t = (service_t *)bq->bq_services->is_array[z]; @@ -404,6 +437,8 @@ bouquet_class_mapnoname_notify ( void *obj ) service_t *t; size_t z; + if (bq->bq_in_load) + return; if (!bq->bq_mapnoname && bq->bq_enabled && bq->bq_maptoch) { for (z = 0; z < bq->bq_services->is_count; z++) { t = (service_t *)bq->bq_services->is_array[z]; @@ -424,6 +459,8 @@ bouquet_class_chtag_notify ( void *obj ) channel_tag_t *ct; size_t z; + if (bq->bq_in_load) + return; if (!bq->bq_chtag && bq->bq_enabled && bq->bq_maptoch) { ct = bouquet_tag(bq, 0); if (!ct) @@ -444,9 +481,46 @@ bouquet_class_chtag_notify ( void *obj ) static void bouquet_class_lcn_offset_notify ( void *obj ) { + if (((bouquet_t *)obj)->bq_in_load) + return; bouquet_notify_channels((bouquet_t *)obj); } +static const void * +bouquet_class_chtag_ref_get ( void *obj ) +{ + static const char *buf; + bouquet_t *bq = obj; + + if (bq->bq_chtag_ptr) + buf = idnode_uuid_as_str(&bq->bq_chtag_ptr->ct_id); + else + buf = ""; + return &buf; +} + +static char * +bouquet_class_chtag_ref_rend ( void *obj ) +{ + bouquet_t *bq = obj; + if (bq->bq_chtag_ptr) + return strdup(bq->bq_chtag_ptr->ct_name ?: ""); + else + return strdup(""); +} + +static int +bouquet_class_chtag_ref_set ( void *obj, const void *p ) +{ + bouquet_t *bq = obj; + + free((char *)bq->bq_chtag_waiting); + bq->bq_chtag_waiting = NULL; + if (bq->bq_in_load) + bq->bq_chtag_waiting = strdup((const char *)p); + return 0; +} + static const void * bouquet_class_services_get ( void *obj ) { @@ -537,6 +611,15 @@ const idclass_t bouquet_class = { .off = offsetof(bouquet_t, bq_chtag), .notify = bouquet_class_chtag_notify, }, + { + .type = PT_STR, + .id = "chtag_ref", + .name = "Channel Tag Reference", + .get = bouquet_class_chtag_ref_get, + .set = bouquet_class_chtag_ref_set, + .rend = bouquet_class_chtag_ref_rend, + .opts = PO_RDONLY | PO_HIDDEN, + }, { .type = PT_STR, .id = "name", diff --git a/src/bouquet.h b/src/bouquet.h index 77a4dac8..fe34571f 100644 --- a/src/bouquet.h +++ b/src/bouquet.h @@ -22,6 +22,7 @@ #include "idnode.h" #include "htsmsg.h" #include "service.h" +#include "channels.h" typedef struct bouquet { idnode_t bq_id; @@ -37,6 +38,8 @@ typedef struct bouquet { int bq_mapnolcn; int bq_mapnoname; int bq_chtag; + channel_tag_t*bq_chtag_ptr; + const char *bq_chtag_waiting; char *bq_name; char *bq_src; char *bq_comment; @@ -63,6 +66,7 @@ bouquet_t * bouquet_create(const char *uuid, htsmsg_t *conf, const char *name, const char *src); void bouquet_destroy_by_service(service_t *t); +void bouquet_destroy_by_channel_tag(channel_tag_t *ct); static inline bouquet_t * bouquet_find_by_uuid(const char *uuid) diff --git a/src/channels.c b/src/channels.c index 141497e6..227bdfba 100644 --- a/src/channels.c +++ b/src/channels.c @@ -926,7 +926,12 @@ channel_tag_unmap(channel_t *ch, channel_tag_t *ct) LIST_REMOVE(ctm, ctm_channel_link); LIST_REMOVE(ctm, ctm_tag_link); free(ctm); - channel_tag_save(ct); + channel_save(ch); + idnode_notify_simple(&ch->ch_id); + if (ct->ct_enabled && !ct->ct_internal) { + htsp_tag_update(ct); + htsp_channel_update(ch); + } return; } } @@ -990,6 +995,7 @@ channel_tag_destroy(channel_tag_t *ct, int delconf) TAILQ_REMOVE(&channel_tags, ct, ct_link); idnode_unlink(&ct->ct_id); + bouquet_destroy_by_channel_tag(ct); autorec_destroy_by_channel_tag(ct, delconf); access_destroy_by_channel_tag(ct, delconf);