From 5a5e4854caed5cb1a9f935220d0a3424f61f69c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20=C3=96man?= Date: Sun, 4 May 2008 18:32:46 +0000 Subject: [PATCH] Improve transport status notification changes. Also let, serviceprobe use the transport built-in timeout facilities. --- ajaxui/ajaxui_config_transport.c | 5 ++- ajaxui/ajaxui_mailbox.c | 8 ++++ ajaxui/ajaxui_mailbox.h | 3 ++ notify.c | 12 ++++++ notify.h | 3 ++ parsers.c | 12 ++++++ serviceprobe.c | 73 ++++++++++++-------------------- transports.c | 37 +++++++++++++--- tvhead.h | 12 ++++-- 9 files changed, 106 insertions(+), 59 deletions(-) diff --git a/ajaxui/ajaxui_config_transport.c b/ajaxui/ajaxui_config_transport.c index b3b78212..1950d778 100644 --- a/ajaxui/ajaxui_config_transport.c +++ b/ajaxui/ajaxui_config_transport.c @@ -125,13 +125,14 @@ ajax_transport_build_list(http_connection_t *hc, tcp_queue_t *tq, (const char *[]){"", "Last status", "Crypto", "Type", "Source service", "", "Target channel", "", NULL}, - (int[]){3,6,4,4,12,3,12,1}); + (int[]){3,8,4,4,12,3,12,1}); LIST_FOREACH(t, tlist, tht_tmp_link) { ajax_table_row_start(&ta, t->tht_identifier); ajax_table_cell_detail_toggler(&ta); - ajax_table_cell(&ta, "status", transport_status_to_text(t->tht_status)); + ajax_table_cell(&ta, "status", + transport_status_to_text(t->tht_last_status)); ajax_table_cell(&ta, NULL, "%s", t->tht_scrambled ? "Yes" : "No"); ajax_table_cell(&ta, NULL, "%s", transport_servicetype_txt(t)); ajax_table_cell(&ta, NULL, "%s", t->tht_svcname ?: ""); diff --git a/ajaxui/ajaxui_mailbox.c b/ajaxui/ajaxui_mailbox.c index 3ac5eeec..fa90dbe1 100644 --- a/ajaxui/ajaxui_mailbox.c +++ b/ajaxui/ajaxui_mailbox.c @@ -477,3 +477,11 @@ ajax_mailbox_xmltv_grabber_status_change(xmltv_grabber_t *xg) } + +void +ajax_mailbox_transport_status_change(struct th_transport *t) +{ + ajax_mailbox_update_div("xmltvgrabbers", + "status", t->tht_identifier, + transport_status_to_text(t->tht_last_status)); +} diff --git a/ajaxui/ajaxui_mailbox.h b/ajaxui/ajaxui_mailbox.h index 9aa86a60..719c4ad3 100644 --- a/ajaxui/ajaxui_mailbox.h +++ b/ajaxui/ajaxui_mailbox.h @@ -39,4 +39,7 @@ struct xmltv_grabber; void ajax_mailbox_xmltv_grabber_status_change(struct xmltv_grabber *xg); +struct th_transport; +void ajax_mailbox_transport_status_change(struct th_transport *t); + #endif /* AJAXUI_MAILBOX_H_ */ diff --git a/notify.c b/notify.c index b6ffa373..5801c97e 100644 --- a/notify.c +++ b/notify.c @@ -73,3 +73,15 @@ notify_xmltv_grabber_status_change(struct xmltv_grabber *xg) { ajax_mailbox_xmltv_grabber_status_change(xg); } + +void +notify_transprot_status_change(struct th_transport *t) +{ + th_subscription_t *s; + + LIST_FOREACH(s, &t->tht_subscriptions, ths_transport_link) + if(s->ths_status_callback != NULL) + s->ths_status_callback(s, t->tht_last_status, s->ths_opaque); + + ajax_mailbox_transport_status_change(t); +} diff --git a/notify.h b/notify.h index f13fb37a..827d4ac4 100644 --- a/notify.h +++ b/notify.h @@ -37,4 +37,7 @@ void notify_tda_change(struct th_dvb_adapter *tda); void notify_xmltv_grabber_status_change(struct xmltv_grabber *xg); +struct th_transport; +void notify_transprot_status_change(struct th_transport *t); + #endif /* NOTIFY_H_ */ diff --git a/parsers.c b/parsers.c index 90e20321..79e11bb2 100644 --- a/parsers.c +++ b/parsers.c @@ -31,6 +31,7 @@ #include "bitstream.h" #include "buffer.h" #include "dispatch.h" +#include "transports.h" static const AVRational mpeg_tc = {1, 90000}; @@ -821,6 +822,17 @@ parser_deliver(th_transport_t *t, th_stream_t *st, th_pkt_t *pkt) avgstat_add(&st->st_rate, pkt->pkt_payloadlen, dispatch_clock); + + /** + * We've got something, disarm the transport timeout timer + */ + dtimer_disarm(&t->tht_receive_timer); + + /** + * Input is ok + */ + transport_signal_status(t, TRANSPORT_STATUS_OK); + /* Alert all muxers tied to us that a new packet has arrived. Muxers may remove themself as a direct action of receiving a packet (serviceprober), so we need to traverse in a safe manner */ diff --git a/serviceprobe.c b/serviceprobe.c index 19b3220d..cb9f8e0b 100644 --- a/serviceprobe.c +++ b/serviceprobe.c @@ -43,22 +43,19 @@ static void serviceprobe_engage(void); struct th_transport_queue probequeue; typedef struct sp { - dtimer_t sp_timer; th_muxer_t *sp_muxer; th_subscription_t *sp_s; - const char *sp_error; - + dtimer_t sp_timer; } sp_t; static void -sp_done(sp_t *sp) +sp_done_callback(void *aux, int64_t now) { + sp_t *sp = aux; th_subscription_t *s = sp->sp_s; th_transport_t *t = sp->sp_s->ths_transport; - dtimer_disarm(&sp->sp_timer); - muxer_deinit(sp->sp_muxer, s); LIST_REMOVE(s, ths_transport_link); @@ -75,43 +72,25 @@ sp_done(sp_t *sp) free(sp); } - /** - * + * Got a packet, map it */ -static void -sp_timeout(void *aux, int64_t now) -{ - sp_t *sp = aux; - th_transport_t *t = sp->sp_s->ths_transport; - channel_t *ch; - - syslog(LOG_INFO, "Probed \"%s\" -- %s\n", t->tht_svcname, - sp->sp_error ?: "Ok"); - - if(sp->sp_error == NULL) { - if(t->tht_ch == NULL && t->tht_svcname != NULL) { - ch = channel_find(t->tht_svcname, 1, NULL); - transport_map_channel(t, ch); - - t->tht_config_change(t); - } - } - - sp_done(sp); -} - - static void sp_packet_input(void *opaque, th_muxstream_t *tms, th_pkt_t *pkt) { sp_t *sp = opaque; + th_transport_t *t = sp->sp_s->ths_transport; + channel_t *ch; - if(tms->tms_stream->st_type == HTSTV_MPEG2VIDEO || - tms->tms_stream->st_type == HTSTV_H264) { - sp->sp_error = NULL; - dtimer_arm(&sp->sp_timer, sp_timeout, sp, 0); + syslog(LOG_INFO, "Probed \"%s\" -- Ok\n", t->tht_svcname); + + if(t->tht_ch == NULL && t->tht_svcname != NULL) { + ch = channel_find(t->tht_svcname, 1, NULL); + transport_map_channel(t, ch); + + t->tht_config_change(t); } + dtimer_arm(&sp->sp_timer, sp_done_callback, sp, 0); } /** @@ -121,22 +100,30 @@ static void sp_status_callback(struct th_subscription *s, int status, void *opaque) { sp_t *sp = opaque; + th_transport_t *t = sp->sp_s->ths_transport; + char *errtxt; + s->ths_status_callback = NULL; switch(status) { case TRANSPORT_STATUS_OK: return; case TRANSPORT_STATUS_NO_DESCRAMBLER: - sp->sp_error = "No descrambler for stream"; + errtxt = "No descrambler for stream"; break; case TRANSPORT_STATUS_NO_ACCESS: - sp->sp_error = "Access denied"; + errtxt = "Access denied"; + break; + case TRANSPORT_STATUS_NO_INPUT: + errtxt = "No input detected"; break; default: - sp->sp_error = "Other error"; + errtxt = "Other error"; break; } - dtimer_arm(&sp->sp_timer, sp_timeout, sp, 0); + + syslog(LOG_INFO, "Probed \"%s\" -- %s\n", t->tht_svcname, errtxt); + dtimer_arm(&sp->sp_timer, sp_done_callback, sp, 0); } @@ -158,7 +145,6 @@ serviceprobe_engage(void) sp = calloc(1, sizeof(sp_t)); sp->sp_s = s = calloc(1, sizeof(th_subscription_t)); - sp->sp_error = "Timeout"; s->ths_title = "probe"; s->ths_weight = INT32_MAX; s->ths_opaque = sp; @@ -173,15 +159,8 @@ serviceprobe_engage(void) muxer_play(tm, AV_NOPTS_VALUE); s->ths_status_callback = sp_status_callback; - - dtimer_arm(&sp->sp_timer, sp_timeout, sp, 4); } - - - - - /** * */ diff --git a/transports.c b/transports.c index b3b0cd16..2069a82d 100644 --- a/transports.c +++ b/transports.c @@ -52,11 +52,13 @@ #include "buffer.h" #include "channels.h" #include "cwc.h" +#include "notify.h" #define TRANSPORT_HASH_WIDTH 101 static struct th_transport_list transporthash[TRANSPORT_HASH_WIDTH]; +static void transport_data_timeout(void *aux, int64_t now); //static dtimer_t transport_monitor_timer; @@ -79,6 +81,8 @@ transport_stop(th_transport_t *t, int flush_subscriptions) return; } + dtimer_disarm(&t->tht_receive_timer); + // dtimer_disarm(&transport_monitor_timer, transport_monitor, t, 1); t->tht_stop_feed(t); @@ -204,6 +208,8 @@ transport_start(th_transport_t *t, unsigned int weight) } cwc_transport_start(t); + dtimer_arm(&t->tht_receive_timer, transport_data_timeout, t, 4); + transport_signal_status(t, TRANSPORT_STATUS_STARTING); return 0; } @@ -423,6 +429,17 @@ transport_monitor(void *aux, int64_t now) #endif +/** + * Timer that fires if transport is not receiving any data + */ +static void +transport_data_timeout(void *aux, int64_t now) +{ + th_transport_t *t = aux; + transport_signal_status(t, TRANSPORT_STATUS_NO_INPUT); +} + + /** * Destroy a transport */ @@ -431,6 +448,8 @@ transport_destroy(th_transport_t *t) { th_stream_t *st; + dtimer_disarm(&t->tht_receive_timer); + free((void *)t->tht_name); if(t->tht_ch != NULL) { @@ -604,16 +623,20 @@ transport_is_available(th_transport_t *t) void transport_signal_status(th_transport_t *t, int newstatus) { - th_subscription_t *s; + char buf[200]; - if(t->tht_last_status != newstatus) + if(t->tht_last_status == newstatus) return; - t->tht_last_status = newstatus; + snprintf(buf, sizeof(buf), "\"%s\" on %s", + t->tht_chname ?: t->tht_svcname, t->tht_sourcename(t)); - LIST_FOREACH(s, &t->tht_subscriptions, ths_transport_link) - if(s->ths_status_callback != NULL) - s->ths_status_callback(s, newstatus, s->ths_opaque); + syslog(LOG_INFO, "%s -- Changed status from \"%s\" to \"%s\"", + buf, transport_status_to_text(t->tht_last_status), + transport_status_to_text(newstatus)); + + t->tht_last_status = newstatus; + notify_transprot_status_change(t); } @@ -622,7 +645,9 @@ transport_signal_status(th_transport_t *t, int newstatus) */ static struct strtab transportstatustab[] = { { "Unknown", TRANSPORT_STATUS_UNKNOWN }, + { "Starting", TRANSPORT_STATUS_STARTING }, { "Ok", TRANSPORT_STATUS_OK }, + { "No input", TRANSPORT_STATUS_NO_INPUT }, { "No descrambler", TRANSPORT_STATUS_NO_DESCRAMBLER }, { "No access", TRANSPORT_STATUS_NO_ACCESS }, { "Mux error", TRANSPORT_STATUS_MUX_ERROR }, diff --git a/tvhead.h b/tvhead.h index 8bcf8983..3ecf3f08 100644 --- a/tvhead.h +++ b/tvhead.h @@ -516,13 +516,17 @@ typedef struct th_transport { * Last known status (or error) */ + dtimer_t tht_receive_timer; /* we use this timer to trig when a transport + does not receive any data at all */ int tht_last_status; #define TRANSPORT_STATUS_UNKNOWN 0 -#define TRANSPORT_STATUS_OK 1 -#define TRANSPORT_STATUS_NO_DESCRAMBLER 2 -#define TRANSPORT_STATUS_NO_ACCESS 3 -#define TRANSPORT_STATUS_MUX_ERROR 4 +#define TRANSPORT_STATUS_STARTING 1 +#define TRANSPORT_STATUS_OK 2 +#define TRANSPORT_STATUS_NO_INPUT 3 +#define TRANSPORT_STATUS_NO_DESCRAMBLER 4 +#define TRANSPORT_STATUS_NO_ACCESS 5 +#define TRANSPORT_STATUS_MUX_ERROR 6 } th_transport_t;