#include "bouquet.h"
#include "api.h"
+typedef struct service_mapper_item {
+ TAILQ_ENTRY(service_mapper_item) link;
+ service_t *s;
+ service_mapper_conf_t conf;
+} service_mapper_item_t;
+
static service_mapper_status_t service_mapper_stat;
static pthread_cond_t service_mapper_cond;
-static struct service_queue service_mapper_queue;
-static service_mapper_conf_t service_mapper_conf;
+static TAILQ_HEAD(, service_mapper_item) service_mapper_queue;
static void *service_mapper_thread ( void *p );
service_mapper_start ( const service_mapper_conf_t *conf, htsmsg_t *uuids )
{
int e, tr, qd = 0;
+ service_mapper_item_t *smi;
service_t *s;
/* Reset stat counters */
if (TAILQ_EMPTY(&service_mapper_queue))
service_mapper_reset_stats();
- /* Store config */
- service_mapper_conf = *conf;
-
/* Check each service */
TAILQ_FOREACH(s, &service_all, s_all_link) {
if (uuids) {
if (conf->check_availability) {
tvhtrace("service_mapper", " queue for checking");
qd = 1;
- TAILQ_INSERT_TAIL(&service_mapper_queue, s, s_sm_link);
+ smi = malloc(sizeof(*smi));
+ smi->s = s;
+ smi->conf = *conf;
+ TAILQ_INSERT_TAIL(&service_mapper_queue, smi, link);
s->s_sm_onqueue = 1;
/* Process */
} else {
tvhtrace("service_mapper", " process");
- service_mapper_process(s, NULL);
+ service_mapper_process(conf, s, NULL);
}
}
void
service_mapper_stop ( void )
{
- service_t *s;
- while ((s = TAILQ_FIRST(&service_mapper_queue))) {
+ service_mapper_item_t *smi;
+ while ((smi = TAILQ_FIRST(&service_mapper_queue))) {
service_mapper_stat.total--;
- service_mapper_remove(s);
+ TAILQ_REMOVE(&service_mapper_queue, smi, link);
+ free(smi);
}
/* Notify */
void
service_mapper_remove ( service_t *s )
{
+ service_mapper_item_t *smi;
+
if (s->s_sm_onqueue) {
- TAILQ_REMOVE(&service_mapper_queue, s, s_sm_link);
+ TAILQ_FOREACH(smi, &service_mapper_queue, link)
+ if (smi->s == s) break;
+ assert(smi);
+ TAILQ_REMOVE(&service_mapper_queue, smi, link);
+ free(smi);
s->s_sm_onqueue = 0;
}
* Process a service
*/
channel_t *
-service_mapper_process ( service_t *s, bouquet_t *bq )
+service_mapper_process
+ ( const service_mapper_conf_t *conf, service_t *s, bouquet_t *bq )
{
channel_t *chn = NULL;
const char *name, *tagname;
/* Find existing channel */
name = service_get_channel_name(s);
- if (!bq && service_mapper_conf.merge_same_name && name && *name)
+ if (!bq && conf->merge_same_name && name && *name)
chn = channel_find_by_name(name);
if (!chn) {
chn = channel_create(NULL, NULL, NULL);
channel_tag_map(channel_tag_find_by_name(tagname, 1), chn, chn);
/* Provider */
- if (service_mapper_conf.provider_tags)
+ if (conf->provider_tags)
if ((prov = s->s_provider_name(s)))
channel_tag_map(channel_tag_find_by_name(prov, 1), chn, chn);
/* Network */
- if (service_mapper_conf.network_tags) {
+ if (conf->network_tags) {
source_info_t si;
s->s_setsourceinfo(s, &si);
channel_tag_map(channel_tag_find_by_name(si.si_network, 1), chn, chn);
service_mapper_thread ( void *aux )
{
service_t *s;
+ service_mapper_item_t *smi;
profile_chain_t prch;
th_subscription_t *sub;
int run, working = 0;
while (tvheadend_running) {
/* Wait for work */
- while (!(s = TAILQ_FIRST(&service_mapper_queue))) {
+ while (!(smi = TAILQ_FIRST(&service_mapper_queue))) {
if (working) {
working = 0;
tvhinfo("service_mapper", "idle");
}
if (!tvheadend_running)
break;
+ s = smi->s;
service_mapper_remove(s);
if (!working) {
tvhinfo("service_mapper", "%s: failed [err %s]", s->s_nicename, err);
service_mapper_stat.fail++;
} else
- service_mapper_process(s, NULL);
+ service_mapper_process(&smi->conf, s, NULL);
service_unref(s);
service_mapper_stat.active = NULL;
typedef struct service_mapper_conf
{
- int check_availability; ///< Check service is receivable
- int encrypted; ///< Include encrypted services
- int merge_same_name; ///< Merge entries with the same name
- int provider_tags; ///< Create tags based on provider name
- int network_tags; ///< Create tags based on network name (useful for multi adapter equipments)
+ uint8_t check_availability; ///< Check service is receivable
+ uint8_t encrypted; ///< Include encrypted services
+ uint8_t merge_same_name; ///< Merge entries with the same name
+ uint8_t provider_tags; ///< Create tags based on provider name
+ uint8_t network_tags; ///< Create tags based on network name (useful for multi adapter equipments)
} service_mapper_conf_t;
typedef struct service_mapper_status
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 );
+struct channel *service_mapper_process
+ ( const service_mapper_conf_t *conf, struct service *s, struct bouquet *bq );
// Resets the stat counters
void service_mapper_reset_stats ( void );