diff --git a/src/channels.c b/src/channels.c index 5105a522..668bb09a 100644 --- a/src/channels.c +++ b/src/channels.c @@ -424,7 +424,7 @@ channel_set_services_by_list ( channel_t *ch, htsmsg_t *svcs ) const char *str; service_t *svc; htsmsg_field_t *f; - channel_service_mapping_t *csm, *n; + channel_service_mapping_t *csm; /* Mark all for deletion */ LIST_FOREACH(csm, &ch->ch_services, csm_chn_link) @@ -434,19 +434,11 @@ channel_set_services_by_list ( channel_t *ch, htsmsg_t *svcs ) HTSMSG_FOREACH(f, svcs) { if ((str = htsmsg_field_get_str(f))) if ((svc = service_find(str))) - save |= service_mapper_link(svc, ch); + save |= service_mapper_link(svc, ch, 0); } /* Remove */ - for (csm = LIST_FIRST(&ch->ch_services); csm != NULL; csm = n) { - n = LIST_NEXT(csm, csm_chn_link); - if (csm->csm_mark) { - LIST_REMOVE(csm, csm_chn_link); - LIST_REMOVE(csm, csm_svc_link); - free(csm); - save = 1; - } - } + save |= service_mapper_clean(NULL, ch, 0); return save; } @@ -567,7 +559,7 @@ channel_delete ( channel_t *ch, int delconf ) /* Services */ while((csm = LIST_FIRST(&ch->ch_services)) != NULL) - service_mapper_unlink(csm->csm_svc, ch); + service_mapper_unlink(csm->csm_svc, ch, 0); /* Subscriptions */ while((s = LIST_FIRST(&ch->ch_subscriptions)) != NULL) { diff --git a/src/input/mpegts/tsfile/tsfile.c b/src/input/mpegts/tsfile/tsfile.c index d05fe469..938a0c1b 100644 --- a/src/input/mpegts/tsfile/tsfile.c +++ b/src/input/mpegts/tsfile/tsfile.c @@ -47,7 +47,7 @@ tsfile_network_create_service // TODO: HACK: REMOVE ME if (s) { channel_t *c = channel_create(NULL, NULL, NULL); - service_mapper_link((service_t*)s, c); + service_mapper_link((service_t*)s, c, 0); } return s; } diff --git a/src/service.c b/src/service.c index a3ff609c..5a250ef7 100644 --- a/src/service.c +++ b/src/service.c @@ -89,7 +89,7 @@ service_class_channel_set const char *str; htsmsg_field_t *f; channel_t *ch; - channel_service_mapping_t *csm, *n; + channel_service_mapping_t *csm; /* Mark all for deletion */ LIST_FOREACH(csm, &svc->s_channels, csm_svc_link) @@ -99,19 +99,11 @@ service_class_channel_set HTSMSG_FOREACH(f, chns) { if ((str = htsmsg_field_get_str(f))) if ((ch = channel_find(str))) - save |= service_mapper_link(svc, ch); + save |= service_mapper_link(svc, ch, 1); } /* Delete unlinked */ - for (csm = LIST_FIRST(&svc->s_channels); csm != NULL; csm = n ) { - n = LIST_NEXT(csm, csm_svc_link); - if (csm->csm_mark) { - save = 1; - LIST_REMOVE(csm, csm_chn_link); - LIST_REMOVE(csm, csm_svc_link); - free(csm); - } - } + service_mapper_clean(svc, NULL, 1); return save; } diff --git a/src/service_mapper.c b/src/service_mapper.c index 3e0310e4..349eee14 100644 --- a/src/service_mapper.c +++ b/src/service_mapper.c @@ -178,7 +178,7 @@ service_mapper_remove ( service_t *s ) * Link service and channel */ int -service_mapper_link ( service_t *s, channel_t *c ) +service_mapper_link ( service_t *s, channel_t *c, int dosave ) { channel_service_mapping_t *csm; @@ -200,25 +200,50 @@ service_mapper_link ( service_t *s, channel_t *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); + if (dosave) channel_save(c); return 1; } +static void +service_mapper_unlink0 ( channel_service_mapping_t *csm, int save ) +{ + if (save) channel_save(csm->csm_chn); + LIST_REMOVE(csm, csm_chn_link); + LIST_REMOVE(csm, csm_svc_link); + free(csm); +} + void -service_mapper_unlink ( service_t *s, channel_t *c ) +service_mapper_unlink ( service_t *s, channel_t *c, int save ) { channel_service_mapping_t *csm; /* Unlink */ LIST_FOREACH(csm, &s->s_channels, csm_svc_link) { if (csm->csm_chn == c) { - LIST_REMOVE(csm, csm_chn_link); - LIST_REMOVE(csm, csm_svc_link); - free(csm); + service_mapper_unlink0(csm, save); break; } } } +int +service_mapper_clean ( service_t *s, channel_t *c, int dosave ) +{ + 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, dosave); + save = 1; + } + } + return save; +} + /* * Process a service */ @@ -250,7 +275,7 @@ service_mapper_process ( service_t *s ) /* Map */ if (chn) { const char *prov; - service_mapper_link(s, chn); + service_mapper_link(s, chn, 0); /* Type tags */ if (service_is_hdtv(s)) { diff --git a/src/service_mapper.h b/src/service_mapper.h index a6c5fb54..8e54dd6e 100644 --- a/src/service_mapper.h +++ b/src/service_mapper.h @@ -53,9 +53,22 @@ void service_mapper_remove ( struct service *t ); service_mapper_status_t service_mapper_status ( void ); // Link service to channel -int service_mapper_link ( struct service *s, struct channel *c ); +int service_mapper_link ( struct service *s, struct channel *c, int save ); // Unlink service from channel -void service_mapper_unlink ( struct service *s, struct channel *c ); +void service_mapper_unlink ( struct service *s, struct channel *c, int save ); + +/** + * 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 save Force channel saves for affected channels + * + * @return 1 if changes were made, else 0 + */ +int service_mapper_clean ( struct service *s, struct channel *ch, int save ); #endif /* __TVH_SERVICE_MAPPER_H__ */