static int
psi_parse_pmt(mpegts_service_t *t, const uint8_t *ptr, int len);
+/* **************************************************************************
+ * Lookup tables
+ * *************************************************************************/
+
+static const int dvb_servicetype_map[][2] = {
+ { 0x01, ST_SDTV }, /* SDTV (MPEG2) */
+ { 0x02, ST_RADIO },
+ { 0x11, ST_HDTV }, /* HDTV (MPEG2) */
+ { 0x16, ST_SDTV }, /* Advanced codec SDTV */
+ { 0x19, ST_HDTV }, /* Advanced codec HDTV */
+ { 0x80, ST_SDTV }, /* NET POA - Cabo SDTV */
+ { 0x91, ST_HDTV }, /* Bell TV HDTV */
+ { 0x96, ST_SDTV }, /* Bell TV SDTV */
+ { 0xA0, ST_HDTV }, /* Bell TV tiered HDTV */
+ { 0xA4, ST_HDTV }, /* DN HDTV */
+ { 0xA6, ST_HDTV }, /* Bell TV tiered HDTV */
+ { 0xA8, ST_SDTV }, /* DN advanced SDTV */
+ { 0xD3, ST_SDTV }, /* SKY TV SDTV */
+};
+
/* **************************************************************************
* Descriptors
* *************************************************************************/
/* Update service type */
if (stype && s->s_dvb_servicetype != stype) {
+ int i;
s->s_dvb_servicetype = stype;
save = 1;
+
+ /* Set tvh service type */
+ for (i = 0; i < ARRAY_SIZE(dvb_servicetype_map); i++) {
+ if (dvb_servicetype_map[i][0] == stype)
+ s->s_servicetype = dvb_servicetype_map[i][1];
+ }
}
/* Update scrambled state */
#include "service_mapper.h"
#include "streaming.h"
#include "service.h"
+#include "plumbing/tsfix.h"
static pthread_cond_t service_mapper_cond;
static struct service_queue service_mapper_queue;
/* Check each service */
TAILQ_FOREACH(s, &service_all, s_all_link) {
-printf("name = %s\n", s->s_channel_name(s));
-
/* Disabled */
if (!s->s_is_enabled(s)) continue;
e = service_is_encrypted(s);
tr = service_is_tv(s) || service_is_radio(s);
pthread_mutex_unlock(&s->s_stream_mutex);
-printf(" tr = %d, e = %d\n", tr, e);
/* Skip non-TV / Radio */
if (!tr) continue;
if (!s->s_sm_onqueue) {
qd = 1;
TAILQ_INSERT_TAIL(&service_mapper_queue, s, s_sm_link);
+ s->s_sm_onqueue = 1;
}
/* Process */
} else {
-printf(" map\n");
service_mapper_process(s);
}
}
streaming_queue_t sq;
streaming_message_t *sm;
const char *err;
+ streaming_target_t *st;
streaming_queue_init(&sq, 0);
}
pthread_cond_wait(&service_mapper_cond, &global_lock);
}
+ service_mapper_remove(s);
if (!working) {
working = 1;
/* Subscribe */
tvhinfo("service_mapper", "%s: checking availability", s->s_nicename);
- sub = subscription_create_from_service(s, "service_mapper", &sq.sq_st,
+ st = tsfix_create(&sq.sq_st);
+ sub = subscription_create_from_service(s, 2, "service_mapper", st,
0, NULL, NULL, "service_mapper");
/* Failed */
if (!sub) {
- service_mapper_remove(s);
tvhinfo("service_mapper", "%s: could not subscribe", s->s_nicename);
continue;
}
TAILQ_REMOVE(&sq.sq_queue, sm, sm_link);
pthread_mutex_unlock(&sq.sq_mutex);
- if(sm->sm_type == SMT_SERVICE_STATUS) {
+ if(sm->sm_type == SMT_PACKET) {
+ run = 0;
+ err = NULL;
+ } else if (sm->sm_type == SMT_SERVICE_STATUS) {
int status = sm->sm_code;
- if(status & TSS_PACKETS) {
- run = 0;
- err = NULL;
- } else if(status & (TSS_GRACEPERIOD | TSS_ERRORS)) {
+ if(status & (TSS_GRACEPERIOD | TSS_ERRORS)) {
run = 0;
err = service_tss2text(status);
}
pthread_mutex_lock(&global_lock);
subscription_unsubscribe(sub);
+ tsfix_destroy(st);
if(err)
tvhinfo("service_mapper", "%s: failed %s", s->s_nicename, err);
subscription_reschedule_cb, NULL, 2);
LIST_FOREACH(s, &subscriptions, ths_global_link) {
+#if 0
if(s->ths_channel == NULL)
continue; /* stale entry, channel has been destroyed */
+#endif
- if(s->ths_service != NULL) {
+ if(s->ths_service != NULL && s->ths_current_instance != NULL) {
/* Already got a service */
if(s->ths_state != SUBSCRIPTION_BAD_SERVICE)
time(&si->si_error_time);
}
- tvhtrace("subscription", "find service for %s weight %d", s->ths_channel->ch_name, s->ths_weight);
- si = service_find_instance(s->ths_channel, &s->ths_instances, &error,
+ if (s->ths_channel)
+ tvhtrace("subscription", "find service for %s weight %d", s->ths_channel->ch_name, s->ths_weight);
+ else
+ tvhtrace("subscription", "find instance for %s weight %d", s->ths_service->s_nicename, s->ths_weight);
+ si = service_find_instance(s->ths_service, s->ths_channel, &s->ths_instances, &error,
s->ths_weight);
s->ths_current_instance = si;
/**
*
*/
-th_subscription_t *
-subscription_create_from_channel(channel_t *ch, unsigned int weight,
- const char *name, streaming_target_t *st,
- int flags, const char *hostname,
- const char *username, const char *client)
+static th_subscription_t *
+subscription_create_from_channel_or_service
+ (channel_t *ch, service_t *t, unsigned int weight,
+ const char *name, streaming_target_t *st,
+ int flags, const char *hostname,
+ const char *username, const char *client)
{
th_subscription_t *s;
+ assert(!ch || !t);
- tvhtrace("subscription", "creating subscription for %s weight %d",
- ch->ch_name, weight);
+ if (ch)
+ tvhtrace("subscription", "creating subscription for %s weight %d",
+ ch->ch_name, weight);
s = subscription_create(weight, name, st, flags, subscription_input,
hostname, username, client);
s->ths_channel = ch;
- LIST_INSERT_HEAD(&ch->ch_subscriptions, s, ths_channel_link);
- s->ths_service = NULL;
+ if (ch)
+ LIST_INSERT_HEAD(&ch->ch_subscriptions, s, ths_channel_link);
+ s->ths_service = t;
subscription_reschedule();
tvhlog(LOG_NOTICE, "subscription",
"No transponder available for subscription \"%s\" "
"to channel \"%s\"",
- s->ths_title, ch->ch_name);
+ s->ths_title, ch ? ch->ch_name : "none");
} else {
source_info_t si;
"\"%s\" subscribing on \"%s\", weight: %d, adapter: \"%s\", "
"network: \"%s\", mux: \"%s\", provider: \"%s\", "
"service: \"%s\"",
- s->ths_title, ch->ch_name, weight,
+ s->ths_title, ch ? ch->ch_name : "none", weight,
si.si_adapter ?: "<N/A>",
si.si_network ?: "<N/A>",
si.si_mux ?: "<N/A>",
return s;
}
+th_subscription_t *
+subscription_create_from_channel(channel_t *ch, unsigned int weight,
+ const char *name, streaming_target_t *st,
+ int flags, const char *hostname,
+ const char *username, const char *client)
+{
+ return subscription_create_from_channel_or_service
+ (ch, NULL, weight, name, st, flags, hostname, username, client);
+}
/**
*
*/
th_subscription_t *
-subscription_create_from_service(service_t *t, const char *name,
+subscription_create_from_service(service_t *t, unsigned int weight,
+ const char *name,
streaming_target_t *st, int flags,
const char *hostname, const char *username,
const char *client)
{
-#if 0
- th_subscription_t *s;
- source_info_t si;
- int r;
-
- s = subscription_create(INT32_MAX, name, st, flags,
- subscription_input_direct,
- hostname, username, client);
-
- if(t->s_status != SERVICE_RUNNING) {
- if((r = service_start(t, INT32_MAX, 1)) != 0) {
- subscription_unsubscribe(s);
-
- tvhlog(LOG_INFO, "subscription",
- "\"%s\" direct subscription failed -- %s", name,
- streaming_code2txt(r));
- return NULL;
- }
- }
-
- t->s_setsourceinfo(t, &si);
-
- tvhlog(LOG_INFO, "subscription",
- "\"%s\" direct subscription to adapter: \"%s\", "
- "network: \"%s\", mux: \"%s\", provider: \"%s\", "
- "service: \"%s\"",
- s->ths_title,
- si.si_adapter ?: "<N/A>",
- si.si_network ?: "<N/A>",
- si.si_mux ?: "<N/A>",
- si.si_provider ?: "<N/A>",
- si.si_service ?: "<N/A>");
- service_source_info_free(&si);
-
- subscription_link_service(s, t);
- notify_reload("subscriptions");
- return s;
-#endif
- abort();
+ return subscription_create_from_channel_or_service
+ (NULL, t, weight, name, st, flags, hostname, username, client);
}
-
/**
*
*/
st = calloc(1, sizeof(streaming_target_t));
streaming_target_init(st, dummy_callback, NULL, 0);
- subscription_create_from_service(t, "dummy", st, 0, NULL, NULL, "dummy");
+ subscription_create_from_service(t, 1, "dummy", st, 0, NULL, NULL, "dummy");
tvhlog(LOG_NOTICE, "subscription",
"Dummy join %s ok", id);