diff --git a/ajaxui/ajaxui_config_dvb.c b/ajaxui/ajaxui_config_dvb.c index c6172f07..65bda45c 100644 --- a/ajaxui/ajaxui_config_dvb.c +++ b/ajaxui/ajaxui_config_dvb.c @@ -142,6 +142,12 @@ dvb_make_add_link(tcp_queue_t *tq, th_dvb_adapter_t *tda, const char *result) "onClick=\"new Ajax.Updater('addmux', " "'/ajax/dvbadapteraddmux/%s', {method: 'get'})\"" ">Add new...

", tda->tda_identifier); + + tcp_qprintf(tq, + "

Delete all muxes

", tda->tda_identifier); } if(result) { @@ -641,6 +647,38 @@ ajax_dvbmuxeditor(http_connection_t *hc, http_reply_t *hr, return 0; } + +/** + * Delete all muxes on an adapter + */ +static int +ajax_adapterdelmuxes(http_connection_t *hc, http_reply_t *hr, + const char *remain, void *opaque) +{ + th_dvb_adapter_t *tda; + th_dvb_mux_instance_t *tdmi; + tcp_queue_t *tq = &hr->hr_tq; + + if(remain == NULL || (tda = dvb_adapter_find_by_identifier(remain)) == NULL) + return HTTP_STATUS_NOT_FOUND; + + printf("Deleting all muxes on %s\n", tda->tda_identifier); + + while((tdmi = LIST_FIRST(&tda->tda_muxes)) != NULL) { + printf("\tdeleting mux %s\n", tdmi->tdmi_identifier); + dvb_mux_destroy(tdmi); + } + + tcp_qprintf(tq, + "new Ajax.Updater('dvbadaptereditor', " + "'/ajax/dvbadaptereditor/%s', " + "{method: 'get', evalScripts: true});", + tda->tda_identifier); + + http_output(hc, hr, "text/javascript; charset=UTF8", NULL, 0); + return 0; +} + /** * */ @@ -651,6 +689,7 @@ ajax_config_dvb_init(void) http_path_add("/ajax/dvbadaptersummary" , NULL, ajax_adaptersummary); http_path_add("/ajax/dvbadaptereditor", NULL, ajax_adaptereditor); http_path_add("/ajax/dvbadapteraddmux", NULL, ajax_adapteraddmux); + http_path_add("/ajax/dvbadapterdelmuxes", NULL, ajax_adapterdelmuxes); http_path_add("/ajax/dvbadaptercreatemux", NULL, ajax_adaptercreatemux); http_path_add("/ajax/dvbmuxeditor", NULL, ajax_dvbmuxeditor); diff --git a/avgen.c b/avgen.c index e9879e9c..6b71702b 100644 --- a/avgen.c +++ b/avgen.c @@ -114,7 +114,6 @@ avgen_init(void) t->tht_name = strdup(ch->ch_name); t->tht_provider = strdup("HTS Tvheadend"); - t->tht_network = strdup("Internal"); t->tht_identifier = strdup("test1"); diff --git a/dvb.c b/dvb.c index cb2daf27..1eb8cfa6 100644 Binary files a/dvb.c and b/dvb.c differ diff --git a/dvb.h b/dvb.h index fab485a1..ce73cf8f 100644 --- a/dvb.h +++ b/dvb.h @@ -60,4 +60,12 @@ void dvb_tdmi_save(th_dvb_mux_instance_t *tdmi); void dvb_tda_save(th_dvb_adapter_t *tda); +void dvb_mux_unref(th_dvb_mux_instance_t *tdmi); + +void dvb_fe_flush(th_dvb_mux_instance_t *tdmi); + +void dvb_mux_destroy(th_dvb_mux_instance_t *tdmi); + +void tdmi_stop(th_dvb_mux_instance_t *tdmi); + #endif /* DVB_H_ */ diff --git a/dvb_fe.c b/dvb_fe.c index f600eb80..32931dde 100644 --- a/dvb_fe.c +++ b/dvb_fe.c @@ -72,10 +72,14 @@ dvb_fe_manager(void *aux) pthread_mutex_lock(&tda->tda_lock); pthread_cond_timedwait(&tda->tda_cond, &tda->tda_lock, &ts); c = TAILQ_FIRST(&tda->tda_fe_cmd_queue); - if(c != NULL) - TAILQ_REMOVE(&tda->tda_fe_cmd_queue, c, link); + if(c != NULL) { + + if(tdmi != NULL) + dvb_mux_unref(tdmi); + + TAILQ_REMOVE(&tda->tda_fe_cmd_queue, c, link); + } - pthread_mutex_unlock(&tda->tda_lock); if(c != NULL) { @@ -83,6 +87,15 @@ dvb_fe_manager(void *aux) tdmi = c->tdmi; + if(tdmi->tdmi_refcnt == 1) { + dvb_mux_unref(tdmi); + tdmi = NULL; + pthread_mutex_unlock(&tda->tda_lock); + continue; + } + + pthread_mutex_unlock(&tda->tda_lock); + p = *tdmi->tdmi_fe_params; if(tda->tda_type == FE_QPSK) { @@ -141,6 +154,8 @@ dvb_fe_manager(void *aux) ioctl(tda->tda_fe_fd, FE_READ_UNCORRECTED_BLOCKS, &v); } + pthread_mutex_unlock(&tda->tda_lock); + if(tdmi == NULL) continue; @@ -188,11 +203,13 @@ dvb_fe_start(th_dvb_adapter_t *tda) /** * Stop the given TDMI */ -static void +void tdmi_stop(th_dvb_mux_instance_t *tdmi) { th_dvb_table_t *tdt; + tdmi->tdmi_adapter->tda_mux_current = NULL; + pthread_mutex_lock(&tdmi->tdmi_table_lock); while((tdt = LIST_FIRST(&tdmi->tdmi_tables)) != NULL) @@ -242,7 +259,31 @@ dvb_tune_tdmi(th_dvb_mux_instance_t *tdmi, int maylog, tdmi_state_t state) c = malloc(sizeof(dvb_fe_cmd_t)); c->tdmi = tdmi; pthread_mutex_lock(&tda->tda_lock); + tdmi->tdmi_refcnt++; TAILQ_INSERT_TAIL(&tda->tda_fe_cmd_queue, c, link); pthread_cond_signal(&tda->tda_cond); pthread_mutex_unlock(&tda->tda_lock); } + + +/** + * Flush pending tuning commands for frontend + * + * tda_lock must be held + */ +void +dvb_fe_flush(th_dvb_mux_instance_t *tdmi) +{ + dvb_fe_cmd_t *c; + th_dvb_adapter_t *tda = tdmi->tdmi_adapter; + + TAILQ_FOREACH(c, &tda->tda_fe_cmd_queue, link) + if(c->tdmi == tdmi) + break; + if(c == NULL) + return; + + TAILQ_REMOVE(&tda->tda_fe_cmd_queue, c, link); + dvb_mux_unref(tdmi); + free(c); +} diff --git a/file_input.c b/file_input.c index 30e4d315..6694e9bc 100644 --- a/file_input.c +++ b/file_input.c @@ -154,7 +154,6 @@ file_input_init(void) t->tht_name = strdup(ch->ch_name); t->tht_provider = strdup("HTS Tvheadend"); - t->tht_network = strdup("Internal"); t->tht_identifier = strdup(ch->ch_name); t->tht_file_input = fi; transport_set_channel(t, ch->ch_name); diff --git a/iptv_input.c b/iptv_input.c index a43213ad..e87a8a13 100644 --- a/iptv_input.c +++ b/iptv_input.c @@ -232,12 +232,6 @@ iptv_configure_transport(th_transport_t *t, const char *iptv_type, else t->tht_provider = strdup("IPTV"); - s = config_get_str_sub(head, "network", NULL); - if(s != NULL) - t->tht_network = strdup(s); - else - t->tht_network = strdup(inet_ntoa(t->tht_iptv_group_addr)); - snprintf(buf, sizeof(buf), "iptv_%s_%d", inet_ntoa(t->tht_iptv_group_addr), t->tht_iptv_port); t->tht_identifier = strdup(buf); diff --git a/transports.c b/transports.c index e24ab09e..f3dc3f85 100644 --- a/transports.c +++ b/transports.c @@ -402,6 +402,37 @@ transport_monitor(void *aux, int64_t now) #endif +/** + * Destroy a transport + */ +void +transport_destroy(th_transport_t *t) +{ + th_stream_t *st; + + free((void *)t->tht_name); + + if(t->tht_channel != NULL) { + t->tht_channel = NULL; + LIST_REMOVE(t, tht_channel_link); + } + + LIST_REMOVE(t, tht_mux_link); + + transport_flush_subscribers(t); + + free(t->tht_identifier); + free(t->tht_servicename); + free(t->tht_channelname); + free(t->tht_provider); + + while((st = LIST_FIRST(&t->tht_streams)) != NULL) { + LIST_REMOVE(st, st_link); + free(st); + } +} + + /** * Create and initialize a new transport struct */ diff --git a/transports.h b/transports.h index 29d61495..754dc7fc 100644 --- a/transports.h +++ b/transports.h @@ -49,4 +49,6 @@ int transport_is_tv(th_transport_t *t); int transport_is_available(th_transport_t *t); +void transport_destroy(th_transport_t *t); + #endif /* TRANSPORTS_H */ diff --git a/tvhead.h b/tvhead.h index a0f15a34..40dcaa45 100644 --- a/tvhead.h +++ b/tvhead.h @@ -146,6 +146,8 @@ typedef enum { * DVB Mux instance */ typedef struct th_dvb_mux_instance { + int tdmi_refcnt; + LIST_ENTRY(th_dvb_mux_instance) tdmi_global_link; LIST_ENTRY(th_dvb_mux_instance) tdmi_adapter_link; @@ -179,8 +181,7 @@ typedef struct th_dvb_mux_instance { uint16_t tdmi_transport_stream_id; char *tdmi_identifier; - - const char *tdmi_network; /* Name of network, from NIT table */ + char *tdmi_network; /* Name of network, from NIT table */ struct th_transport_list tdmi_transports; /* via tht_mux_link */ @@ -430,8 +431,6 @@ typedef struct th_transport { struct th_muxer_list tht_muxers; /* muxers */ - struct pluginaux_list tht_plugin_aux; - /* * Per source type structs */ @@ -469,11 +468,11 @@ typedef struct th_transport { } file_input; } u; - const char *tht_identifier; - const char *tht_servicename; - const char *tht_channelname; - const char *tht_provider; - const char *tht_network; + char *tht_identifier; + char *tht_servicename; + char *tht_channelname; + char *tht_provider; + enum { /* Service types defined in EN 300 468 */ diff --git a/v4l.c b/v4l.c index 0650df92..09b83980 100644 --- a/v4l.c +++ b/v4l.c @@ -93,7 +93,6 @@ v4l_configure_transport(th_transport_t *t, const char *muxname, (float)t->tht_v4l_frequency / 1000000.0f); t->tht_name = strdup(buf); - t->tht_network = strdup("Analog TV"); t->tht_provider = strdup("Analog TV"); snprintf(buf, sizeof(buf), "analog_%u", t->tht_v4l_frequency); t->tht_identifier = strdup(buf);