From: Jaroslav Kysela Date: Mon, 15 Jun 2015 19:57:18 +0000 (+0200) Subject: idnode: add generic mapping interface X-Git-Tag: v4.2.1~2326 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=dcf5643f4ee6c135bf47f20938f95f86edc8f8be;p=thirdparty%2Ftvheadend.git idnode: add generic mapping interface - channel-service mapping rewritten - channel-chtag mapping rewritten --- diff --git a/src/bouquet.c b/src/bouquet.c index ad846d992..a78d4cc86 100644 --- a/src/bouquet.c +++ b/src/bouquet.c @@ -224,7 +224,7 @@ static void bouquet_map_channel(bouquet_t *bq, service_t *t) { channel_t *ch = NULL; - channel_service_mapping_t *csm; + idnode_list_mapping_t *ilm; if (!t->s_enabled) return; @@ -236,15 +236,18 @@ bouquet_map_channel(bouquet_t *bq, service_t *t) return; if (!bq->bq_mapnoname && noname(service_get_channel_name(t))) return; - LIST_FOREACH(csm, &t->s_channels, csm_svc_link) - if (csm->csm_chn->ch_bouquet == bq) + LIST_FOREACH(ilm, &t->s_channels, ilm_in1_link) + if (((channel_t *)ilm->ilm_in2)->ch_bouquet == bq) break; - if (!csm) + if (!ilm) ch = service_mapper_process(t, bq); else - ch = csm->csm_chn; + ch = (channel_t *)ilm->ilm_in2; if (ch && bq->bq_chtag) - channel_tag_map(ch, bouquet_tag(bq, 1)); + if (channel_tag_map(bouquet_tag(bq, 1), ch, ch)) { + idnode_notify_changed(&ch->ch_id); + channel_save(ch); + } } /* @@ -254,7 +257,7 @@ void bouquet_add_service(bouquet_t *bq, service_t *s, uint64_t lcn, uint32_t tag) { service_lcn_t *tl; - channel_service_mapping_t *csm; + idnode_list_mapping_t *ilm; lock_assert(&global_lock); @@ -282,8 +285,8 @@ bouquet_add_service(bouquet_t *bq, service_t *s, uint64_t lcn, uint32_t tag) } if (lcn != tl->sl_lcn) { tl->sl_lcn = lcn; - LIST_FOREACH(csm, &s->s_channels, csm_svc_link) - idnode_notify_changed(&csm->csm_chn->ch_id); + LIST_FOREACH(ilm, &s->s_channels, ilm_in1_link) + idnode_notify_changed(ilm->ilm_in2); } tl->sl_seen = 1; @@ -307,18 +310,18 @@ bouquet_add_service(bouquet_t *bq, service_t *s, uint64_t lcn, uint32_t tag) static void bouquet_unmap_channel(bouquet_t *bq, service_t *t) { - channel_service_mapping_t *csm, *csm_next; + idnode_list_mapping_t *ilm, *ilm_next; - csm = LIST_FIRST(&t->s_channels); - while (csm) { - csm_next = LIST_NEXT(csm, csm_svc_link); - if (csm->csm_chn->ch_bouquet == bq) { + ilm = LIST_FIRST(&t->s_channels); + while (ilm) { + ilm_next = LIST_NEXT(ilm, ilm_in1_link); + if (((channel_t *)ilm->ilm_in2)->ch_bouquet == bq) { tvhinfo("bouquet", "%s / %s: unmapped from %s", - channel_get_name(csm->csm_chn), t->s_nicename, + channel_get_name((channel_t *)ilm->ilm_in2), t->s_nicename, bq->bq_name ?: ""); - channel_delete(csm->csm_chn, 1); + channel_delete((channel_t *)ilm->ilm_in2, 1); } - csm = csm_next; + ilm = ilm_next; } } @@ -448,15 +451,15 @@ bouquet_map_to_channels(bouquet_t *bq) void bouquet_notify_channels(bouquet_t *bq) { - channel_service_mapping_t *csm; + idnode_list_mapping_t *ilm; service_t *t; size_t z; for (z = 0; z < bq->bq_services->is_count; z++) { t = (service_t *)bq->bq_services->is_array[z]; - LIST_FOREACH(csm, &t->s_channels, csm_svc_link) - if (csm->csm_chn->ch_bouquet == bq) - idnode_notify_changed(&csm->csm_chn->ch_id); + LIST_FOREACH(ilm, &t->s_channels, ilm_in1_link) + if (((channel_t *)ilm->ilm_in2)->ch_bouquet == bq) + idnode_notify_changed(ilm->ilm_in2); } } @@ -661,7 +664,7 @@ bouquet_class_chtag_notify ( void *obj ) { bouquet_t *bq = obj; service_t *t; - channel_service_mapping_t *csm; + idnode_list_mapping_t *ilm; channel_tag_t *ct; size_t z; @@ -673,11 +676,11 @@ bouquet_class_chtag_notify ( void *obj ) return; for (z = 0; z < bq->bq_services->is_count; z++) { t = (service_t *)bq->bq_services->is_array[z]; - LIST_FOREACH(csm, &t->s_channels, csm_svc_link) - if (csm->csm_chn->ch_bouquet == bq) + LIST_FOREACH(ilm, &t->s_channels, ilm_in1_link) + if (((channel_t *)ilm->ilm_in2)->ch_bouquet == bq) break; - if (csm) - channel_tag_unmap(csm->csm_chn, ct); + if (ilm) + channel_tag_unmap((channel_t *)ilm->ilm_in2, ct); } } else { bouquet_map_to_channels(bq); diff --git a/src/channels.c b/src/channels.c index fddad4216..8ad4db99b 100644 --- a/src/channels.c +++ b/src/channels.c @@ -53,13 +53,7 @@ struct channel_tag_queue channel_tags; static void channel_tag_init ( void ); static void channel_tag_done ( void ); -static void channel_tag_mapping_destroy(channel_tag_mapping_t *ctm, - int flags); -static void channel_tag_destroy(channel_tag_t *ct, int delconf); - - -#define CTM_DESTROY_UPDATE_TAG 0x1 -#define CTM_DESTROY_UPDATE_CHANNEL 0x2 +static void channel_tag_mapping_destroy(idnode_list_mapping_t *ilm, void *origin); static int ch_id_cmp ( channel_t *a, channel_t *b ) @@ -86,37 +80,24 @@ channel_class_delete ( idnode_t *self ) static const void * channel_class_services_get ( void *obj ) { - htsmsg_t *l = htsmsg_create_list(); channel_t *ch = obj; - channel_service_mapping_t *csm; - - /* Add all */ - LIST_FOREACH(csm, &ch->ch_services, csm_chn_link) - htsmsg_add_str(l, NULL, idnode_uuid_as_str(&csm->csm_svc->s_id)); - - return l; + return idnode_list_get2(&ch->ch_services); } static char * channel_class_services_rend ( void *obj ) { - char *str; - htsmsg_t *l = htsmsg_create_list(); channel_t *ch = obj; - channel_service_mapping_t *csm; - - LIST_FOREACH(csm, &ch->ch_services, csm_chn_link) - htsmsg_add_str(l, NULL, idnode_get_title(&csm->csm_svc->s_id) ?: ""); - - str = htsmsg_list_2_csv(l); - htsmsg_destroy(l); - return str; + return idnode_list_get_csv2(&ch->ch_services); } static int channel_class_services_set ( void *obj, const void *p ) { - return channel_set_services_by_list(obj, (htsmsg_t*)p); + channel_t *ch = obj; + return idnode_list_set2(&ch->ch_id, &ch->ch_services, + &service_class, (htsmsg_t *)p, + service_mapper_create); } static htsmsg_t * @@ -135,37 +116,30 @@ channel_class_services_enum ( void *obj ) static const void * channel_class_tags_get ( void *obj ) { - channel_tag_mapping_t *ctm; channel_t *ch = obj; - htsmsg_t *m = htsmsg_create_list(); - - /* Add all */ - LIST_FOREACH(ctm, &ch->ch_ctms, ctm_channel_link) - htsmsg_add_str(m, NULL, idnode_uuid_as_str(&ctm->ctm_tag->ct_id)); - - return m; + return idnode_list_get2(&ch->ch_ctms); } static char * channel_class_tags_rend ( void *obj ) { - char *str; - htsmsg_t *l = htsmsg_create_list(); channel_t *ch = obj; - channel_tag_mapping_t *ctm; - - LIST_FOREACH(ctm, &ch->ch_ctms, ctm_channel_link) - htsmsg_add_str(l, NULL, ctm->ctm_tag->ct_name); + return idnode_list_get_csv2(&ch->ch_ctms); +} - str = htsmsg_list_2_csv(l); - htsmsg_destroy(l); - return str; +static int +channel_class_tags_set_cb ( idnode_t *in1, idnode_t *in2, void *origin ) +{ + return channel_tag_map((channel_tag_t *)in1, (channel_t *)in2, origin); } static int channel_class_tags_set ( void *obj, const void *p ) { - return channel_set_tags_by_list(obj, (htsmsg_t*)p); + channel_t *ch = obj; + return idnode_list_set2(&ch->ch_id, &ch->ch_ctms, + &channel_tag_class, (htsmsg_t *)p, + channel_class_tags_set_cb); } static void @@ -487,12 +461,12 @@ channel_access(channel_t *ch, access_t *a, int disabled) /* Channel tag check */ if (a->aa_chtags) { - channel_tag_mapping_t *ctm; + idnode_list_mapping_t *ilm; htsmsg_field_t *f; HTSMSG_FOREACH(f, a->aa_chtags) { - LIST_FOREACH(ctm, &ch->ch_ctms, ctm_channel_link) { + LIST_FOREACH(ilm, &ch->ch_ctms, ilm_in2_link) { if (!strcmp(htsmsg_field_get_str(f) ?: "", - idnode_uuid_as_str(&ctm->ctm_tag->ct_id))) + idnode_uuid_as_str(ilm->ilm_in1))) goto chtags_ok; } } @@ -507,75 +481,15 @@ chtags_ok: * Property updating * *************************************************************************/ -int -channel_set_services_by_list ( channel_t *ch, htsmsg_t *svcs ) -{ - int save = 0; - const char *str; - service_t *svc; - htsmsg_field_t *f; - channel_service_mapping_t *csm; - - /* Mark all for deletion */ - LIST_FOREACH(csm, &ch->ch_services, csm_chn_link) - csm->csm_mark = 1; - - /* Link */ - HTSMSG_FOREACH(f, svcs) { - if ((str = htsmsg_field_get_str(f))) - if ((svc = service_find(str))) - save |= service_mapper_link(svc, ch, ch); - } - - /* Remove */ - save |= service_mapper_clean(NULL, ch, ch); - - return save; -} - -int -channel_set_tags_by_list ( channel_t *ch, htsmsg_t *tags ) -{ - int save = 0; - const char *uuid; - channel_tag_mapping_t *ctm, *n; - channel_tag_t *ct; - htsmsg_field_t *f; - - /* Mark for deletion */ - LIST_FOREACH(ctm, &ch->ch_ctms, ctm_channel_link) - ctm->ctm_mark = 1; - - /* Link */ - HTSMSG_FOREACH(f, tags) - if ((uuid = htsmsg_field_get_str(f)) != NULL) { - if ((ct = channel_tag_find_by_uuid(uuid))) - save |= channel_tag_map(ch, ct); - } - - /* Remove */ - for (ctm = LIST_FIRST(&ch->ch_ctms); ctm != NULL; ctm = n) { - n = LIST_NEXT(ctm, ctm_channel_link); - if (ctm->ctm_mark) { - LIST_REMOVE(ctm, ctm_channel_link); - LIST_REMOVE(ctm, ctm_tag_link); - free(ctm); - save = 1; - } - } - - return save; -} - const char * channel_get_name ( channel_t *ch ) { static const char *blank = CHANNEL_BLANK_NAME; const char *s; - channel_service_mapping_t *csm; + idnode_list_mapping_t *ilm; if (ch->ch_name && *ch->ch_name) return ch->ch_name; - LIST_FOREACH(csm, &ch->ch_services, csm_chn_link) - if ((s = service_get_channel_name(csm->csm_svc))) + LIST_FOREACH(ilm, &ch->ch_services, ilm_in2_link) + if ((s = service_get_channel_name((service_t *)ilm->ilm_in1))) return s; return blank; } @@ -597,15 +511,15 @@ int64_t channel_get_number ( channel_t *ch ) { int64_t n = 0; - channel_service_mapping_t *csm; + idnode_list_mapping_t *ilm; if (ch->ch_number) { n = ch->ch_number; } else { - LIST_FOREACH(csm, &ch->ch_services, csm_chn_link) { + LIST_FOREACH(ilm, &ch->ch_services, ilm_in2_link) { if (ch->ch_bouquet && - (n = bouquet_get_channel_number(ch->ch_bouquet, csm->csm_svc))) + (n = bouquet_get_channel_number(ch->ch_bouquet, (service_t *)ilm->ilm_in1))) break; - if ((n = service_get_channel_number(csm->csm_svc))) + if ((n = service_get_channel_number((service_t *)ilm->ilm_in1))) break; } } @@ -642,7 +556,7 @@ const char * channel_get_icon ( channel_t *ch ) { static char buf[512], buf2[512]; - channel_service_mapping_t *csm; + idnode_list_mapping_t *ilm; const char *chicon = config_get_chicon_path(), *picon = config_get_picon_path(), *icon = ch->ch_icon, @@ -718,9 +632,9 @@ channel_get_icon ( channel_t *ch ) /* No user icon - try access from services */ if (pick && picon) { - LIST_FOREACH(csm, &ch->ch_services, csm_chn_link) { + LIST_FOREACH(ilm, &ch->ch_services, ilm_in2_link) { const char *icn; - if (!(icn = service_get_channel_icon(csm->csm_svc))) continue; + if (!(icn = service_get_channel_icon((service_t *)ilm->ilm_in1))) continue; if (strncmp(icn, "picon://", 8)) continue; snprintf(buf2, sizeof(buf2), "%s/%s", picon, icn+8); @@ -829,8 +743,7 @@ void channel_delete ( channel_t *ch, int delconf ) { th_subscription_t *s; - channel_tag_mapping_t *ctm; - channel_service_mapping_t *csm; + idnode_list_mapping_t *ilm; lock_assert(&global_lock); @@ -838,8 +751,8 @@ channel_delete ( channel_t *ch, int delconf ) tvhinfo("channel", "%s - deleting", channel_get_name(ch)); /* Tags */ - while((ctm = LIST_FIRST(&ch->ch_ctms)) != NULL) - channel_tag_mapping_destroy(ctm, CTM_DESTROY_UPDATE_TAG); + while((ilm = LIST_FIRST(&ch->ch_ctms)) != NULL) + channel_tag_mapping_destroy(ilm, ch); /* DVR */ autorec_destroy_by_channel(ch, delconf); @@ -847,8 +760,8 @@ channel_delete ( channel_t *ch, int delconf ) dvr_destroy_by_channel(ch, delconf); /* Services */ - while((csm = LIST_FIRST(&ch->ch_services)) != NULL) - service_mapper_unlink(csm->csm_svc, ch, ch); + while((ilm = LIST_FIRST(&ch->ch_services)) != NULL) + idnode_list_unlink(ilm, ch); /* Subscriptions */ while((s = LIST_FIRST(&ch->ch_subscriptions)) != NULL) { @@ -934,44 +847,22 @@ channel_done ( void ) * */ int -channel_tag_map(channel_t *ch, channel_tag_t *ct) +channel_tag_map(channel_tag_t *ct, channel_t *ch, void *origin) { - channel_tag_mapping_t *ctm; - - LIST_FOREACH(ctm, &ch->ch_ctms, ctm_channel_link) - if(ctm->ctm_tag == ct) - break; - if (!ctm) - LIST_FOREACH(ctm, &ct->ct_ctms, ctm_tag_link) - if(ctm->ctm_channel == ch) - break; - - if (ctm) { - ctm->ctm_mark = 0; - return 0; - } - - LIST_FOREACH(ctm, &ch->ch_ctms, ctm_channel_link) - assert(ctm->ctm_tag != ct); - - LIST_FOREACH(ctm, &ct->ct_ctms, ctm_tag_link) - assert(ctm->ctm_channel != ch); - - ctm = malloc(sizeof(channel_tag_mapping_t)); - - ctm->ctm_channel = ch; - LIST_INSERT_HEAD(&ch->ch_ctms, ctm, ctm_channel_link); - - ctm->ctm_tag = ct; - LIST_INSERT_HEAD(&ct->ct_ctms, ctm, ctm_tag_link); - - ctm->ctm_mark = 0; - - if(ct->ct_enabled && !ct->ct_internal) { - htsp_tag_update(ct); - htsp_channel_update(ch); + idnode_list_mapping_t *ilm; + + ilm = idnode_list_link(&ct->ct_id, &ct->ct_ctms, + &ch->ch_id, &ch->ch_ctms, + origin); + if (ilm) { + ilm->ilm_in2_save = 1; /* channel */ + if(ct->ct_enabled && !ct->ct_internal) { + htsp_tag_update(ct); + htsp_channel_update(ch); + } + return 1; } - return 1; + return 0; } @@ -979,19 +870,17 @@ channel_tag_map(channel_t *ch, channel_tag_t *ct) * */ static void -channel_tag_mapping_destroy(channel_tag_mapping_t *ctm, int flags) +channel_tag_mapping_destroy(idnode_list_mapping_t *ilm, void *origin) { - channel_tag_t *ct = ctm->ctm_tag; - channel_t *ch = ctm->ctm_channel; + channel_tag_t *ct = (channel_tag_t *)ilm->ilm_in1; + channel_t *ch = (channel_t *)ilm->ilm_in2; - LIST_REMOVE(ctm, ctm_channel_link); - LIST_REMOVE(ctm, ctm_tag_link); - free(ctm); + idnode_list_unlink(ilm, origin); if(ct->ct_enabled && !ct->ct_internal) { - if(flags & CTM_DESTROY_UPDATE_TAG) + if(origin == ch) htsp_tag_update(ct); - if(flags & CTM_DESTROY_UPDATE_CHANNEL) + if(origin == ct) htsp_channel_update(ch); } } @@ -1000,22 +889,14 @@ channel_tag_mapping_destroy(channel_tag_mapping_t *ctm, int flags) * */ void -channel_tag_unmap(channel_t *ch, channel_tag_t *ct) +channel_tag_unmap(channel_t *ch, void *origin) { - channel_tag_mapping_t *ctm, *n; - - for (ctm = LIST_FIRST(&ch->ch_ctms); ctm != NULL; ctm = n) { - n = LIST_NEXT(ctm, ctm_channel_link); - if (ctm->ctm_channel == ch) { - LIST_REMOVE(ctm, ctm_channel_link); - LIST_REMOVE(ctm, ctm_tag_link); - free(ctm); - channel_save(ch); - idnode_notify_changed(&ch->ch_id); - if (ct->ct_enabled && !ct->ct_internal) { - htsp_tag_update(ct); - htsp_channel_update(ch); - } + idnode_list_mapping_t *ilm, *n; + + for (ilm = LIST_FIRST(&ch->ch_ctms); ilm != NULL; ilm = n) { + n = LIST_NEXT(ilm, ilm_in2_link); + if ((channel_t *)ilm->ilm_in2 == ch) { + channel_tag_mapping_destroy(ilm, origin); return; } } @@ -1061,15 +942,11 @@ channel_tag_create(const char *uuid, htsmsg_t *conf) static void channel_tag_destroy(channel_tag_t *ct, int delconf) { - channel_tag_mapping_t *ctm; - channel_t *ch; + idnode_list_mapping_t *ilm; if (delconf) { - while((ctm = LIST_FIRST(&ct->ct_ctms)) != NULL) { - ch = ctm->ctm_channel; - channel_tag_mapping_destroy(ctm, CTM_DESTROY_UPDATE_CHANNEL); - channel_save(ch); - } + while((ilm = LIST_FIRST(&ct->ct_ctms)) != NULL) + channel_tag_mapping_destroy(ilm, ilm->ilm_in1); hts_settings_remove("channel/tag/%s", idnode_uuid_as_str(&ct->ct_id)); } diff --git a/src/channels.h b/src/channels.h index 92f51eab4..2ebc5e009 100644 --- a/src/channels.h +++ b/src/channels.h @@ -27,7 +27,6 @@ struct bouquet; RB_HEAD(channel_tree, channel); -LIST_HEAD(channel_tag_mapping_list, channel_tag_mapping); TAILQ_HEAD(channel_tag_queue, channel_tag); extern struct channel_tag_queue channel_tags; @@ -53,12 +52,12 @@ typedef struct channel char *ch_name; // Note: do not access directly! int64_t ch_number; char *ch_icon; - struct channel_tag_mapping_list ch_ctms; + idnode_list_head_t ch_ctms; struct bouquet *ch_bouquet; /* Service/subscriptions */ - LIST_HEAD(, channel_service_mapping) ch_services; - LIST_HEAD(, th_subscription) ch_subscriptions; + idnode_list_head_t ch_services; + LIST_HEAD(, th_subscription) ch_subscriptions; /* EPG fields */ epg_broadcast_tree_t ch_epg_schedule; @@ -99,7 +98,7 @@ typedef struct channel_tag { char *ct_comment; char *ct_icon; - struct channel_tag_mapping_list ct_ctms; + idnode_list_head_t ct_ctms; struct dvr_autorec_entry_list ct_autorecs; @@ -109,33 +108,6 @@ typedef struct channel_tag { } channel_tag_t; -/** - * Channel tag mapping - */ -typedef struct channel_tag_mapping { - LIST_ENTRY(channel_tag_mapping) ctm_channel_link; - channel_t *ctm_channel; - - LIST_ENTRY(channel_tag_mapping) ctm_tag_link; - channel_tag_t *ctm_tag; - - int ctm_mark; - -} channel_tag_mapping_t; - -/* - * Service mappings - */ -typedef struct channel_service_mapping { - LIST_ENTRY(channel_service_mapping) csm_chn_link; - LIST_ENTRY(channel_service_mapping) csm_svc_link; - - struct channel *csm_chn; - struct service *csm_svc; - - int csm_mark; -} channel_service_mapping_t; - extern const idclass_t channel_class; extern const idclass_t channel_tag_class; @@ -163,7 +135,6 @@ channel_t *channel_find_by_number(const char *no); htsmsg_t * channel_class_get_list(void *o); int channel_set_tags_by_list ( channel_t *ch, htsmsg_t *tags ); -int channel_set_services_by_list ( channel_t *ch, htsmsg_t *svcs ); channel_tag_t *channel_tag_create(const char *uuid, htsmsg_t *conf); @@ -182,8 +153,8 @@ const char * channel_tag_get_icon(channel_tag_t *ct); int channel_access(channel_t *ch, struct access *a, int disabled); -int channel_tag_map(channel_t *ch, channel_tag_t *ct); -void channel_tag_unmap(channel_t *ch, channel_tag_t *ct); +int channel_tag_map(channel_tag_t *ct, channel_t *ch, void *origin); +void channel_tag_unmap(channel_t *ch, void *origin); int channel_tag_access(channel_tag_t *ct, struct access *a, int disabled); @@ -203,8 +174,8 @@ int channel_set_number ( channel_t *ch, uint32_t major, uint32_t minor ); const char *channel_get_icon ( channel_t *ch ); int channel_set_icon ( channel_t *ch, const char *icon ); -#define channel_get_uuid(ch) idnode_uuid_as_str(&ch->ch_id) +#define channel_get_uuid(ch) idnode_uuid_as_str(&(ch)->ch_id) -#define channel_get_id(ch) idnode_get_short_uuid((&ch->ch_id)) +#define channel_get_id(ch) idnode_get_short_uuid((&(ch)->ch_id)) #endif /* CHANNELS_H */ diff --git a/src/dvr/dvr_autorec.c b/src/dvr/dvr_autorec.c index 07efd5834..7112da68f 100644 --- a/src/dvr/dvr_autorec.c +++ b/src/dvr/dvr_autorec.c @@ -63,7 +63,7 @@ dvr_autorec_purge_spawns(dvr_autorec_entry_t *dae, int del) static int autorec_cmp(dvr_autorec_entry_t *dae, epg_broadcast_t *e) { - channel_tag_mapping_t *ctm; + idnode_list_mapping_t *ilm; dvr_config_t *cfg; double duration; @@ -130,10 +130,10 @@ autorec_cmp(dvr_autorec_entry_t *dae, epg_broadcast_t *e) } if(dae->dae_channel_tag != NULL) { - LIST_FOREACH(ctm, &dae->dae_channel_tag->ct_ctms, ctm_tag_link) - if(ctm->ctm_channel == e->channel) + LIST_FOREACH(ilm, &dae->dae_channel_tag->ct_ctms, ilm_in1_link) + if((channel_t *)ilm->ilm_in2 == e->channel) break; - if(ctm == NULL) + if(ilm == NULL) return 0; } diff --git a/src/epg.c b/src/epg.c index 0889880c2..f0ba80683 100644 --- a/src/epg.c +++ b/src/epg.c @@ -2581,10 +2581,10 @@ epg_query ( epg_query_t *eq, access_t *perm ) /* Tag based */ } else if (tag) { - channel_tag_mapping_t *ctm; + idnode_list_mapping_t *ilm; channel_t *ch2; - LIST_FOREACH(ctm, &tag->ct_ctms, ctm_tag_link) { - ch2 = ctm->ctm_channel; + LIST_FOREACH(ilm, &tag->ct_ctms, ilm_in1_link) { + ch2 = (channel_t *)ilm->ilm_in2; if(ch2 == channel || channel == NULL) if (channel_access(ch2, perm, 0)) _eq_add_channel(eq, ch2); diff --git a/src/epggrab/module/eit.c b/src/epggrab/module/eit.c index c1dc40b73..1079b9568 100644 --- a/src/epggrab/module/eit.c +++ b/src/epggrab/module/eit.c @@ -557,13 +557,14 @@ static int _eit_process_event mpegts_service_t *svc, const uint8_t *ptr, int len, int local, int *resched, int *save ) { - channel_service_mapping_t *csm; + idnode_list_mapping_t *ilm; int ret = 0; if ( len < 12 ) return -1; - LIST_FOREACH(csm, &svc->s_channels, csm_svc_link) - ret = _eit_process_event_one(mod, tableid, svc, csm->csm_chn, + LIST_FOREACH(ilm, &svc->s_channels, ilm_in1_link) + ret = _eit_process_event_one(mod, tableid, svc, + (channel_t *)ilm->ilm_in2, ptr, len, local, resched, save); return ret; } diff --git a/src/epggrab/module/opentv.c b/src/epggrab/module/opentv.c index c104c738d..9ff7d1bc1 100644 --- a/src/epggrab/module/opentv.c +++ b/src/epggrab/module/opentv.c @@ -516,7 +516,7 @@ skip_chnum: if (svc && LIST_FIRST(&svc->s_channels)) { ec =_opentv_find_epggrab_channel(mod, cid, 1, &save); ecl = LIST_FIRST(&ec->channels); - ch = LIST_FIRST(&svc->s_channels)->csm_chn; + ch = (channel_t *)LIST_FIRST(&svc->s_channels)->ilm_in2; tvhtrace(mt->mt_name, " ec = %p, ecl = %p", ec, ecl); if (ecl && ecl->ecl_channel != ch) { diff --git a/src/htsp_server.c b/src/htsp_server.c index 37cdfd17d..fef799aa3 100644 --- a/src/htsp_server.c +++ b/src/htsp_server.c @@ -592,8 +592,7 @@ htsp_file_destroy(htsp_file_t *hf) static htsmsg_t * htsp_build_channel(channel_t *ch, const char *method, htsp_connection_t *htsp) { - channel_tag_mapping_t *ctm; - channel_service_mapping_t *csm; + idnode_list_mapping_t *ilm; channel_tag_t *ct; service_t *t; epg_broadcast_t *now, *next = NULL; @@ -647,14 +646,14 @@ htsp_build_channel(channel_t *ch, const char *method, htsp_connection_t *htsp) htsmsg_add_u32(out, "eventId", now ? now->id : 0); htsmsg_add_u32(out, "nextEventId", next ? next->id : 0); - LIST_FOREACH(ctm, &ch->ch_ctms, ctm_channel_link) { - ct = ctm->ctm_tag; + LIST_FOREACH(ilm, &ch->ch_ctms, ilm_in2_link) { + ct = (channel_tag_t *)ilm->ilm_in1; if(channel_tag_access(ct, htsp->htsp_granted_access, 0)) htsmsg_add_u32(tags, NULL, htsp_channel_tag_get_identifier(ct)); } - LIST_FOREACH(csm, &ch->ch_services, csm_chn_link) { - t = csm->csm_svc; + LIST_FOREACH(ilm, &ch->ch_services, ilm_in2_link) { + t = (service_t *)ilm->ilm_in1; htsmsg_t *svcmsg = htsmsg_create_map(); uint16_t caid; htsmsg_add_str(svcmsg, "name", service_nicename(t)); @@ -679,7 +678,7 @@ htsp_build_channel(channel_t *ch, const char *method, htsp_connection_t *htsp) static htsmsg_t * htsp_build_tag(channel_tag_t *ct, const char *method, int include_channels) { - channel_tag_mapping_t *ctm; + idnode_list_mapping_t *ilm; htsmsg_t *out = htsmsg_create_map(); htsmsg_t *members = include_channels ? htsmsg_create_list() : NULL; @@ -691,8 +690,8 @@ htsp_build_tag(channel_tag_t *ct, const char *method, int include_channels) htsmsg_add_u32(out, "tagTitledIcon", ct->ct_titled_icon); if(members != NULL) { - LIST_FOREACH(ctm, &ct->ct_ctms, ctm_tag_link) - htsmsg_add_u32(members, NULL, channel_get_id(ctm->ctm_channel)); + LIST_FOREACH(ilm, &ct->ct_ctms, ilm_in1_link) + htsmsg_add_u32(members, NULL, channel_get_id((channel_t *)ilm->ilm_in2)); htsmsg_add_msg(out, "members", members); } diff --git a/src/idnode.c b/src/idnode.c index d6011da24..18ef88d2d 100644 --- a/src/idnode.c +++ b/src/idnode.c @@ -1328,6 +1328,222 @@ idnode_serialize0(idnode_t *self, htsmsg_t *list, int optmask) return m; } +/* ************************************************************************** + * List helpers + * *************************************************************************/ + +static void +idnode_list_notify ( idnode_list_mapping_t *ilm, void *origin ) +{ + if (origin == NULL) + return; + if (origin == ilm->ilm_in1) { + idnode_notify_changed(ilm->ilm_in2); + if (ilm->ilm_in2_save) + idnode_savefn(ilm->ilm_in2); + } + if (origin == ilm->ilm_in2) { + idnode_notify_changed(ilm->ilm_in1); + if (ilm->ilm_in1_save) + idnode_savefn(ilm->ilm_in1); + } +} + +/* + * Link class1 and class2 + */ +idnode_list_mapping_t * +idnode_list_link ( idnode_t *in1, idnode_list_head_t *in1_list, + idnode_t *in2, idnode_list_head_t *in2_list, + void *origin ) +{ + idnode_list_mapping_t *ilm; + + /* Already linked */ + LIST_FOREACH(ilm, in1_list, ilm_in1_link) + if (ilm->ilm_in2 == in2) { + ilm->ilm_mark = 0; + return NULL; + } + LIST_FOREACH(ilm, in2_list, ilm_in2_link) + if (ilm->ilm_in1 == in1) { + ilm->ilm_mark = 0; + return NULL; + } + + /* Link */ + ilm = calloc(1, sizeof(idnode_list_mapping_t)); + ilm->ilm_in1 = in1; + ilm->ilm_in2 = in2; + LIST_INSERT_HEAD(in1_list, ilm, ilm_in1_link); + LIST_INSERT_HEAD(in2_list, ilm, ilm_in2_link); + idnode_list_notify(ilm, origin); + return ilm; +} + +void +idnode_list_unlink ( idnode_list_mapping_t *ilm, void *origin ) +{ + LIST_REMOVE(ilm, ilm_in1_link); + LIST_REMOVE(ilm, ilm_in2_link); + idnode_list_notify(ilm, origin); + free(ilm); +} + +static int +idnode_list_clean + ( idnode_t *in1, idnode_list_head_t *in1_list, + idnode_t *in2, idnode_list_head_t *in2_list, + void *origin ) +{ + int save = 0; + idnode_list_mapping_t *ilm, *n; + + for (ilm = LIST_FIRST(in1 ? in1_list : in2_list); ilm != NULL; ilm = n) { + n = in1 ? LIST_NEXT(ilm, ilm_in1_link) : LIST_NEXT(ilm, ilm_in2_link); + if (ilm->ilm_mark) { + idnode_list_unlink(ilm, origin); + save = 1; + } + } + return save; +} + +htsmsg_t * +idnode_list_get1 + ( idnode_list_head_t *in1_list ) +{ + idnode_list_mapping_t *ilm; + htsmsg_t *l = htsmsg_create_list(); + + LIST_FOREACH(ilm, in1_list, ilm_in1_link) + htsmsg_add_str(l, NULL, idnode_uuid_as_str(ilm->ilm_in2)); + return l; +} + +htsmsg_t * +idnode_list_get2 + ( idnode_list_head_t *in2_list ) +{ + idnode_list_mapping_t *ilm; + htsmsg_t *l = htsmsg_create_list(); + + LIST_FOREACH(ilm, in2_list, ilm_in2_link) + htsmsg_add_str(l, NULL, idnode_uuid_as_str(ilm->ilm_in1)); + return l; +} + +char * +idnode_list_get_csv1 + ( idnode_list_head_t *in1_list ) +{ + char *str; + idnode_list_mapping_t *ilm; + htsmsg_t *l = htsmsg_create_list(); + + LIST_FOREACH(ilm, in1_list, ilm_in1_link) + htsmsg_add_str(l, NULL, idnode_get_title(ilm->ilm_in2)); + + str = htsmsg_list_2_csv(l); + htsmsg_destroy(l); + return str; +} + +char * +idnode_list_get_csv2 + ( idnode_list_head_t *in2_list ) +{ + char *str; + idnode_list_mapping_t *ilm; + htsmsg_t *l = htsmsg_create_list(); + + LIST_FOREACH(ilm, in2_list, ilm_in2_link) + htsmsg_add_str(l, NULL, idnode_get_title(ilm->ilm_in1)); + + str = htsmsg_list_2_csv(l); + htsmsg_destroy(l); + return str; +} + +int +idnode_list_set1 + ( idnode_t *in1, idnode_list_head_t *in1_list, + const idclass_t *in2_class, htsmsg_t *in2_list, + int (*in2_create)(idnode_t *in1, idnode_t *in2, void *origin) ) +{ + const char *str; + htsmsg_field_t *f; + idnode_t *in2; + idnode_list_mapping_t *ilm; + int save = 0; + + /* Mark all for deletion */ + LIST_FOREACH(ilm, in1_list, ilm_in1_link) + ilm->ilm_mark = 1; + + /* Make new links */ + HTSMSG_FOREACH(f, in2_list) + if ((str = htsmsg_field_get_str(f))) + if ((in2 = idnode_find(str, in2_class, NULL)) != NULL) + if (in2_create(in1, in2, in1)) + save = 1; + + /* Delete unlinked */ + if (idnode_list_clean(in1, in1_list, NULL, NULL, in1)) + save = 1; + + /* Change notification */ + if (save) + idnode_notify_changed(in1); + + /* Save only on demand */ + ilm = LIST_FIRST(in1_list); + if (ilm && !ilm->ilm_in1_save) + save = 0; + + return save; +} + +int +idnode_list_set2 + ( idnode_t *in2, idnode_list_head_t *in2_list, + const idclass_t *in1_class, htsmsg_t *in1_list, + int (*in1_create)(idnode_t *in1, idnode_t *in2, void *origin) ) +{ + const char *str; + htsmsg_field_t *f; + idnode_t *in1; + idnode_list_mapping_t *ilm; + int save = 0; + + /* Mark all for deletion */ + LIST_FOREACH(ilm, in2_list, ilm_in2_link) + ilm->ilm_mark = 1; + + /* Make new links */ + HTSMSG_FOREACH(f, in1_list) + if ((str = htsmsg_field_get_str(f))) + if ((in1 = idnode_find(str, in1_class, NULL)) != NULL) + if (in1_create(in1, in2, in2)) + save = 1; + + /* Delete unlinked */ + if (idnode_list_clean(in2, in2_list, NULL, NULL, in2)) + save = 1; + + /* Change notification */ + if (save) + idnode_notify_changed(in2); + + /* Save only on demand */ + ilm = LIST_FIRST(in2_list); + if (ilm && !ilm->ilm_in2_save) + save = 0; + + return save; +} + + /* ************************************************************************** * Notification * *************************************************************************/ diff --git a/src/idnode.h b/src/idnode.h index fcd6b6117..fb335b442 100644 --- a/src/idnode.h +++ b/src/idnode.h @@ -91,6 +91,27 @@ struct idnode { }; +/* + * Node list mapping definition + */ +struct idnode_list_mapping; + +typedef struct idnode_list_head { + struct idnode_list_mapping *lh_first; +} idnode_list_head_t; + +typedef struct idnode_list_mapping { + LIST_ENTRY(idnode_list_mapping) ilm_in1_link; + LIST_ENTRY(idnode_list_mapping) ilm_in2_link; + + idnode_t *ilm_in1; + idnode_t *ilm_in2; + + uint8_t ilm_in1_save; + uint8_t ilm_in2_save; + uint8_t ilm_mark; +} idnode_list_mapping_t; + /* * Sorting definition */ @@ -183,6 +204,22 @@ int idnode_perm(idnode_t *self, struct access *a, htsmsg_t *msg_to_write); static inline void idnode_perm_set(idnode_t *self, struct access *a) { self->in_access = a; } static inline void idnode_perm_unset(idnode_t *self) { self->in_access = NULL; } +idnode_list_mapping_t * idnode_list_link + ( idnode_t *in1, idnode_list_head_t *in1_list, + idnode_t *in2, idnode_list_head_t *in2_list, + void *origin ); +void idnode_list_unlink ( idnode_list_mapping_t *ilm, void *origin ); +htsmsg_t * idnode_list_get1 ( idnode_list_head_t *in1_list ); +htsmsg_t * idnode_list_get2 ( idnode_list_head_t *in2_list ); +char * idnode_list_get_csv1 ( idnode_list_head_t *in1_list ); +char * idnode_list_get_csv2 ( idnode_list_head_t *in2_list ); +int idnode_list_set1 ( idnode_t *in1, idnode_list_head_t *in1_list, + const idclass_t *in2_class, htsmsg_t *in2_list, + int (*in2_create)(idnode_t *in1, idnode_t *in2, void *origin) ); +int idnode_list_set2 ( idnode_t *in2, idnode_list_head_t *in2_list, + const idclass_t *in1_class, htsmsg_t *in1_list, + int (*in2_create)(idnode_t *in1, idnode_t *in2, void *origin) ); + const char *idnode_get_str (idnode_t *self, const char *key ); int idnode_get_u32 (idnode_t *self, const char *key, uint32_t *u32); int idnode_get_s64 (idnode_t *self, const char *key, int64_t *s64); diff --git a/src/input/mpegts/mpegts_mux.c b/src/input/mpegts/mpegts_mux.c index 20fc493b8..4f68a5db7 100644 --- a/src/input/mpegts/mpegts_mux.c +++ b/src/input/mpegts/mpegts_mux.c @@ -331,11 +331,11 @@ mpegts_mux_class_get_num_chn ( void *ptr ) static int n; mpegts_mux_t *mm = ptr; mpegts_service_t *s; - channel_service_mapping_t *csm; + idnode_list_mapping_t *ilm; n = 0; LIST_FOREACH(s, &mm->mm_services, s_dvb_mux_link) - LIST_FOREACH(csm, &s->s_channels, csm_svc_link) + LIST_FOREACH(ilm, &s->s_channels, ilm_in1_link) n++; return &n; diff --git a/src/input/mpegts/mpegts_network.c b/src/input/mpegts/mpegts_network.c index 9311ffc8d..c81a0a58b 100644 --- a/src/input/mpegts/mpegts_network.c +++ b/src/input/mpegts/mpegts_network.c @@ -85,12 +85,12 @@ mpegts_network_class_get_num_chn ( void *ptr ) mpegts_mux_t *mm; mpegts_service_t *s; mpegts_network_t *mn = ptr; - channel_service_mapping_t *csm; + idnode_list_mapping_t *ilm; n = 0; LIST_FOREACH(mm, &mn->mn_muxes, mm_network_link) LIST_FOREACH(s, &mm->mm_services, s_dvb_mux_link) - LIST_FOREACH(csm, &s->s_channels, csm_svc_link) + LIST_FOREACH(ilm, &s->s_channels, ilm_in1_link) n++; return &n; diff --git a/src/service.c b/src/service.c index a66a3e743..373c724d6 100644 --- a/src/service.c +++ b/src/service.c @@ -69,29 +69,14 @@ static const void * service_class_channel_get ( void *obj ) { service_t *svc = obj; - channel_service_mapping_t *csm; - - htsmsg_t *l = htsmsg_create_list(); - LIST_FOREACH(csm, &svc->s_channels, csm_svc_link) - htsmsg_add_str(l, NULL, idnode_uuid_as_str(&csm->csm_chn->ch_id)); - - return l; + return idnode_list_get1(&svc->s_channels); } static char * service_class_channel_rend ( void *obj ) { - char *str; service_t *svc = obj; - channel_service_mapping_t *csm; - - htsmsg_t *l = htsmsg_create_list(); - LIST_FOREACH(csm, &svc->s_channels, csm_svc_link) - htsmsg_add_str(l, NULL, idnode_get_title(&csm->csm_chn->ch_id)); - - str = htsmsg_list_2_csv(l); - htsmsg_destroy(l); - return str; + return idnode_list_get_csv1(&svc->s_channels); } static int @@ -99,30 +84,9 @@ service_class_channel_set ( void *obj, const void *p ) { service_t *svc = obj; - htsmsg_t *chns = (htsmsg_t*)p; - const char *str; - htsmsg_field_t *f; - channel_t *ch; - channel_service_mapping_t *csm; - - /* Mark all for deletion */ - LIST_FOREACH(csm, &svc->s_channels, csm_svc_link) - csm->csm_mark = 1; - - /* Make new links */ - HTSMSG_FOREACH(f, chns) { - if ((str = htsmsg_field_get_str(f))) - if ((ch = channel_find(str))) - service_mapper_link(svc, ch, svc); - } - - /* Delete unlinked */ - service_mapper_clean(svc, NULL, svc); - - /* no save - the link information is in the saved channel record */ - /* only send a notify about the change to other clients */ - idnode_notify_changed(&svc->s_id); - return 0; + return idnode_list_set1(&svc->s_id, &svc->s_channels, + &channel_class, (htsmsg_t *)p, + service_mapper_create); } static htsmsg_t * @@ -699,7 +663,7 @@ service_find_instance profile_chain_t *prch, service_instance_list_t *sil, int *error, int weight, int flags, int timeout, int postpone) { - channel_service_mapping_t *csm; + idnode_list_mapping_t *ilm; service_instance_t *si, *next; profile_t *pro = prch ? prch->prch_pro : NULL; int enlisted, weight2; @@ -716,8 +680,8 @@ service_find_instance return NULL; } enlisted = 0; - LIST_FOREACH(csm, &ch->ch_services, csm_chn_link) { - s = csm->csm_svc; + LIST_FOREACH(ilm, &ch->ch_services, ilm_in2_link) { + s = (service_t *)ilm->ilm_in1; if (s->s_is_enabled(s, flags)) { if (pro == NULL || pro->pro_svfilter == PROFILE_SVF_NONE || @@ -729,8 +693,8 @@ service_find_instance } } if (enlisted == 0) { - LIST_FOREACH(csm, &ch->ch_services, csm_chn_link) { - s = csm->csm_svc; + LIST_FOREACH(ilm, &ch->ch_services, ilm_in2_link) { + s = (service_t *)ilm->ilm_in1; if (s->s_is_enabled(s, flags)) s->s_enlist(s, ti, sil, flags); } @@ -838,7 +802,7 @@ service_destroy(service_t *t, int delconf) { elementary_stream_t *st; th_subscription_t *s; - channel_service_mapping_t *csm; + idnode_list_mapping_t *ilm; if(t->s_delete != NULL) t->s_delete(t, delconf); @@ -851,11 +815,8 @@ service_destroy(service_t *t, int delconf) subscription_unlink_service(s, SM_CODE_SOURCE_DELETED); } - while ((csm = LIST_FIRST(&t->s_channels))) { - LIST_REMOVE(csm, csm_svc_link); - LIST_REMOVE(csm, csm_chn_link); - free(csm); - } + while ((ilm = LIST_FIRST(&t->s_channels))) + idnode_list_unlink(ilm, t); idnode_unlink(&t->s_id); diff --git a/src/service.h b/src/service.h index 3307babb0..1c1187e3b 100644 --- a/src/service.h +++ b/src/service.h @@ -336,7 +336,7 @@ typedef struct service { /** * Channel mapping */ - LIST_HEAD(,channel_service_mapping) s_channels; + idnode_list_head_t s_channels; /** * Service mapping, see service_mapper.c form details diff --git a/src/service_mapper.c b/src/service_mapper.c index cf5414b35..37cb8eb88 100644 --- a/src/service_mapper.c +++ b/src/service_mapper.c @@ -178,88 +178,29 @@ service_mapper_remove ( service_t *s ) api_service_mapper_notify(); } -static void -service_mapper_notify ( channel_service_mapping_t *csm, void *origin ) -{ - if (origin == NULL) - return; - if (origin == csm->csm_svc) { - idnode_notify_changed(&csm->csm_chn->ch_id); - channel_save(csm->csm_chn); - } - if (origin == csm->csm_chn) - idnode_notify_changed(&csm->csm_svc->s_id); -} - /* * Link service and channel */ int service_mapper_link ( service_t *s, channel_t *c, void *origin ) { - channel_service_mapping_t *csm; - - /* Already linked */ - LIST_FOREACH(csm, &s->s_channels, csm_svc_link) - if (csm->csm_chn == c) { - csm->csm_mark = 0; - return 0; - } - LIST_FOREACH(csm, &c->ch_services, csm_chn_link) - if (csm->csm_svc == s) { - csm->csm_mark = 0; - return 0; - } - - /* Link */ - csm = calloc(1, sizeof(channel_service_mapping_t)); - csm->csm_chn = c; - csm->csm_svc = s; - LIST_INSERT_HEAD(&s->s_channels, csm, csm_svc_link); - LIST_INSERT_HEAD(&c->ch_services, csm, csm_chn_link); - service_mapped( s ); - service_mapper_notify( csm, origin ); - return 1; -} - -static void -service_mapper_unlink0 ( channel_service_mapping_t *csm, void *origin ) -{ - LIST_REMOVE(csm, csm_chn_link); - LIST_REMOVE(csm, csm_svc_link); - service_mapper_notify( csm, origin ); - free(csm); -} - -void -service_mapper_unlink ( service_t *s, channel_t *c, void *origin ) -{ - channel_service_mapping_t *csm; - - /* Unlink */ - LIST_FOREACH(csm, &s->s_channels, csm_svc_link) { - if (csm->csm_chn == c) { - service_mapper_unlink0(csm, origin); - break; - } + idnode_list_mapping_t *ilm; + + ilm = idnode_list_link(&s->s_id, &s->s_channels, + &c->ch_id, &c->ch_services, + origin); + if (ilm) { + service_mapped(s); + ilm->ilm_in2_save = 1; /* channel */ + return 1; } + return 0; } int -service_mapper_clean ( service_t *s, channel_t *c, void *origin ) +service_mapper_create ( idnode_t *s, idnode_t *c, void *origin ) { - int save = 0; - channel_service_mapping_t *csm, *n; - - csm = s ? LIST_FIRST(&s->s_channels) : LIST_FIRST(&c->ch_services); - for (; csm != NULL; csm = n ) { - n = s ? LIST_NEXT(csm, csm_svc_link) : LIST_NEXT(csm, csm_chn_link); - if (csm->csm_mark) { - service_mapper_unlink0(csm, origin); - save = 1; - } - } - return save; + return service_mapper_link((service_t *)s, (channel_t *)c, origin); } /* @@ -300,19 +241,19 @@ service_mapper_process ( service_t *s, bouquet_t *bq ) /* Type tags */ if (service_is_hdtv(s)) { - channel_tag_map(chn, channel_tag_find_by_name("TV channels", 1)); - channel_tag_map(chn, channel_tag_find_by_name("HDTV", 1)); + channel_tag_map(channel_tag_find_by_name("TV channels", 1), chn, chn); + channel_tag_map(channel_tag_find_by_name("HDTV", 1), chn, chn); } else if (service_is_sdtv(s)) { - channel_tag_map(chn, channel_tag_find_by_name("TV channels", 1)); - channel_tag_map(chn, channel_tag_find_by_name("SDTV", 1)); + channel_tag_map(channel_tag_find_by_name("TV channels", 1), chn, chn); + channel_tag_map(channel_tag_find_by_name("SDTV", 1), chn, chn); } else if (service_is_radio(s)) { - channel_tag_map(chn, channel_tag_find_by_name("Radio", 1)); + channel_tag_map(channel_tag_find_by_name("Radio", 1), chn, chn); } /* Provider */ if (service_mapper_conf.provider_tags) if ((prov = s->s_provider_name(s))) - channel_tag_map(chn, channel_tag_find_by_name(prov, 1)); + channel_tag_map(channel_tag_find_by_name(prov, 1), chn, chn); /* save */ idnode_notify_changed(&chn->ch_id); diff --git a/src/service_mapper.h b/src/service_mapper.h index 6651d66f8..b8dfaf386 100644 --- a/src/service_mapper.h +++ b/src/service_mapper.h @@ -57,22 +57,8 @@ service_mapper_status_t service_mapper_status ( void ); // Link service to channel int service_mapper_link ( struct service *s, struct channel *c, void *origin ); -// Unlink service from channel -void service_mapper_unlink ( struct service *s, struct channel *c, void *origin ); - -/** - * Clean linkages that are marked for deletion - * - * Note: only ever pass one of s and c - * - * @param s The service to clean linkages for - * @param c The channel to clean linkages for - * @parma origin Origin of the change (should be a service or a channel ptr). - * NULL = no save and notifications. - * - * @return 1 if changes were made, else 0 - */ -int service_mapper_clean ( struct service *s, struct channel *ch, void *origin ); +// Create new link +int service_mapper_create ( idnode_t *s, idnode_t *c, void *origin ); // Process one service struct channel *service_mapper_process ( struct service *s, struct bouquet *bq ); diff --git a/src/webui/webui.c b/src/webui/webui.c index 4a7578bd7..76b31e80a 100644 --- a/src/webui/webui.c +++ b/src/webui/webui.c @@ -442,8 +442,9 @@ http_tag_playlist(http_connection_t *hc, channel_tag_t *tag) { htsbuf_queue_t *hq; char buf[255]; - channel_tag_mapping_t *ctm; + idnode_list_mapping_t *ilm; char *profile, *hostpath; + channel_t *ch; if(hc->hc_access == NULL || access_verify2(hc->hc_access, ACCESS_STREAMING)) @@ -455,11 +456,12 @@ http_tag_playlist(http_connection_t *hc, channel_tag_t *tag) hostpath = http_get_hostpath(hc); htsbuf_qprintf(hq, "#EXTM3U\n"); - LIST_FOREACH(ctm, &tag->ct_ctms, ctm_tag_link) { - if (http_access_verify_channel(hc, ACCESS_STREAMING, ctm->ctm_channel, 0)) + LIST_FOREACH(ilm, &tag->ct_ctms, ilm_in1_link) { + ch = (channel_t *)ilm->ilm_in2; + if (http_access_verify_channel(hc, ACCESS_STREAMING, ch, 0)) continue; - snprintf(buf, sizeof(buf), "/stream/channelid/%d", channel_get_id(ctm->ctm_channel)); - htsbuf_qprintf(hq, "#EXTINF:-1,%s\n", channel_get_name(ctm->ctm_channel)); + snprintf(buf, sizeof(buf), "/stream/channelid/%d", channel_get_id(ch)); + htsbuf_qprintf(hq, "#EXTINF:-1,%s\n", channel_get_name(ch)); htsbuf_qprintf(hq, "%s%s?ticket=%s", hostpath, buf, access_ticket_create(buf, hc->hc_access)); htsbuf_qprintf(hq, "&profile=%s\n", profile);