From c2723dd7cfaf79ec3e96cfd1858305d59ef60b55 Mon Sep 17 00:00:00 2001 From: Adam Sutton Date: Tue, 6 Aug 2013 22:22:49 +0100 Subject: [PATCH] mpegts: added the ability to delete muxes --- src/idnode.c | 3 ++ src/input/mpegts.h | 11 +++++ src/input/mpegts/linuxdvb/linuxdvb_mux.c | 15 +++++++ src/input/mpegts/mpegts_mux.c | 52 ++++++++++++++++++++++++ src/input/mpegts/mpegts_service.c | 16 ++++++++ src/service.c | 4 +- src/service.h | 2 +- src/webui/extjs_dvb.c | 48 ++++++++++++++++++++-- src/webui/static/app/idnode.js | 23 ++++++++++- 9 files changed, 165 insertions(+), 9 deletions(-) diff --git a/src/idnode.c b/src/idnode.c index 10be0a5d..6c3b8481 100644 --- a/src/idnode.c +++ b/src/idnode.c @@ -134,6 +134,7 @@ int idnode_insert(idnode_t *in, const char *uuid, const idclass_t *class) { idnode_t *c; + lock_assert(&global_lock); if(uuid == NULL) { if(read(randfd, in->in_uuid, 16) != 16) { perror("read(random for uuid)"); @@ -160,7 +161,9 @@ idnode_insert(idnode_t *in, const char *uuid, const idclass_t *class) void idnode_unlink(idnode_t *in) { + lock_assert(&global_lock); RB_REMOVE(&idnodes, in, in_link); + idnode_updated(in); } /* ************************************************************************** diff --git a/src/input/mpegts.h b/src/input/mpegts.h index 0215422f..85639f00 100644 --- a/src/input/mpegts.h +++ b/src/input/mpegts.h @@ -247,6 +247,7 @@ struct mpegts_mux * Functions */ + void (*mm_delete) (mpegts_mux_t *mm); void (*mm_config_save) (mpegts_mux_t *mm); void (*mm_display_name) (mpegts_mux_t*, char *buf, size_t len); int (*mm_is_enabled) (mpegts_mux_t *mm); @@ -350,6 +351,8 @@ struct mpegts_mux_instance // TODO: remove this int mmi_tune_failed; // this is really DVB + + void (*mmi_delete) (mpegts_mux_instance_t *mmi); }; /* Input source */ @@ -485,8 +488,16 @@ mpegts_mux_t *mpegts_mux_create0 mpegts_mux_create0(calloc(1, sizeof(mpegts_mux_t)), &mpegts_mux_class, uuid,\ mn, onid, tsid, conf) +#define mpegts_mux_find(u)\ + idnode_find(u, &mpegts_mux_class); + +#define mpegts_mux_delete_by_uuid(u)\ + { mpegts_mux_t *mm = mpegts_mux_find(u); if (mm) mm->mm_delete(mm); } + void mpegts_mux_initial_scan_done ( mpegts_mux_t *mm ); +void mpegts_mux_delete ( mpegts_mux_t *mm ); + void mpegts_mux_save ( mpegts_mux_t *mm, htsmsg_t *c ); mpegts_mux_instance_t *mpegts_mux_instance_create0 diff --git a/src/input/mpegts/linuxdvb/linuxdvb_mux.c b/src/input/mpegts/linuxdvb/linuxdvb_mux.c index 08034600..656248a4 100644 --- a/src/input/mpegts/linuxdvb/linuxdvb_mux.c +++ b/src/input/mpegts/linuxdvb/linuxdvb_mux.c @@ -449,6 +449,20 @@ linuxdvb_mux_close_table ( mpegts_mux_t *mm, mpegts_table_t *mt ) close(mt->mt_fd); } +static void +linuxdvb_mux_delete + ( mpegts_mux_t *mm ) +{ + printf("delete %p\n", mm); + /* Remove config */ + hts_settings_remove("input/linuxdvb/networks/%s/muxes/%s/config", + idnode_uuid_as_str(&mm->mm_network->mn_id), + idnode_uuid_as_str(&mm->mm_id)); + + /* Delete the mux */ + mpegts_mux_delete(mm); +} + /* ************************************************************************** * Creation/Config * *************************************************************************/ @@ -490,6 +504,7 @@ linuxdvb_mux_create0 memcpy(&lm->lm_tuning, dmc, sizeof(dvb_mux_conf_t)); /* Callbacks */ + lm->mm_delete = linuxdvb_mux_delete; lm->mm_display_name = linuxdvb_mux_display_name; lm->mm_config_save = linuxdvb_mux_config_save; lm->mm_create_instances = linuxdvb_mux_create_instances; diff --git a/src/input/mpegts/mpegts_mux.c b/src/input/mpegts/mpegts_mux.c index 7a9437de..5910629d 100644 --- a/src/input/mpegts/mpegts_mux.c +++ b/src/input/mpegts/mpegts_mux.c @@ -36,6 +36,16 @@ const idclass_t mpegts_mux_instance_class = .ic_caption = "MPEGTS Multiplex Phy", }; +static void +mpegts_mux_instance_delete + ( mpegts_mux_instance_t *mmi ) +{ + idnode_unlink(&mmi->mmi_id); + LIST_REMOVE(mmi, mmi_mux_link); + LIST_REMOVE(mmi, mmi_input_link); + free(mmi); +} + mpegts_mux_instance_t * mpegts_mux_instance_create0 ( mpegts_mux_instance_t *mmi, const idclass_t *class, const char *uuid, @@ -47,8 +57,13 @@ mpegts_mux_instance_create0 /* Setup links */ mmi->mmi_mux = mm; mmi->mmi_input = mi; + + /* Callbacks */ + mmi->mmi_delete = mpegts_mux_instance_delete; LIST_INSERT_HEAD(&mm->mm_instances, mmi, mmi_mux_link); + LIST_INSERT_HEAD(&mi->mi_mux_instances, mmi, mmi_input_link); + return mmi; } @@ -220,6 +235,42 @@ mpegts_mux_display_name ( mpegts_mux_t *mm, char *buf, size_t len ) mm->mm_onid, mm->mm_tsid); } +void +mpegts_mux_delete ( mpegts_mux_t *mm ) +{ + mpegts_mux_instance_t *mmi; + mpegts_network_t *mn = mm->mm_network; + mpegts_service_t *s; + char buf[256]; + + mm->mm_display_name(mm, buf, sizeof(buf)); + tvhinfo("mpegts", "%s - deleting", buf); + + /* Stop */ + mm->mm_stop(mm); + + /* Remove from lists */ + LIST_REMOVE(mm, mm_network_link); + printf("SCAN STATUS = %d\n", mm->mm_initial_scan_done); + if (mm->mm_initial_scan_status != MM_SCAN_DONE) { + printf("remove from pending Q\n"); + TAILQ_REMOVE(&mn->mn_initial_scan_pending_queue, mm, mm_initial_scan_link); + } + while ((mmi = LIST_FIRST(&mm->mm_instances))) { + mmi->mmi_delete(mmi); + } + + /* Delete services */ + while ((s = LIST_FIRST(&mm->mm_services))) { + service_destroy((service_t*)s); + } + + /* Free memory */ + idnode_unlink(&mm->mm_id); + free(mm->mm_crid_authority); + free(mm); +} + static void mpegts_mux_config_save ( mpegts_mux_t *mm ) { @@ -481,6 +532,7 @@ mpegts_mux_create0 mm->mm_network = mn; /* Debug/Config */ + mm->mm_delete = mpegts_mux_delete; mm->mm_display_name = mpegts_mux_display_name; mm->mm_config_save = mpegts_mux_config_save; mm->mm_is_enabled = mpegts_mux_is_enabled; diff --git a/src/input/mpegts/mpegts_service.c b/src/input/mpegts/mpegts_service.c index 45d19776..ff493cba 100644 --- a/src/input/mpegts/mpegts_service.c +++ b/src/input/mpegts/mpegts_service.c @@ -306,6 +306,21 @@ mpegts_service_provider_name ( service_t *s ) return ((mpegts_service_t*)s)->s_dvb_provider; } +static void +mpegts_service_delete ( service_t *t ) +{ + mpegts_service_t *ms = (mpegts_service_t*)t; + free(ms->s_dvb_svcname); + free(ms->s_dvb_provider); + free(ms->s_dvb_charset); + LIST_REMOVE(ms, s_dvb_mux_link); + + // TODO: delete config + + // Note: the ultimate deletion and removal from the idnode list + // is done in service_destroy +} + /* ************************************************************************** * Creation/Location * *************************************************************************/ @@ -330,6 +345,7 @@ mpegts_service_create0 s->s_dvb_mux = mm; LIST_INSERT_HEAD(&mm->mm_services, s, s_dvb_mux_link); + s->s_delete = mpegts_service_delete; s->s_is_enabled = mpegts_service_is_enabled; s->s_config_save = mpegts_service_config_save; s->s_enlist = mpegts_service_enlist; diff --git a/src/service.c b/src/service.c index e8e5beee..6c80ec35 100644 --- a/src/service.c +++ b/src/service.c @@ -359,8 +359,8 @@ service_destroy(service_t *t) th_subscription_t *s; channel_service_mapping_t *csm; - if(t->s_dtor != NULL) - t->s_dtor(t); + if(t->s_delete != NULL) + t->s_delete(t); lock_assert(&global_lock); diff --git a/src/service.h b/src/service.h index 93fd1f98..0f6e5451 100644 --- a/src/service.h +++ b/src/service.h @@ -278,7 +278,7 @@ typedef struct service { int (*s_grace_period)(struct service *t); - void (*s_dtor)(struct service *t); + void (*s_delete)(struct service *t); /** * Channel info diff --git a/src/webui/extjs_dvb.c b/src/webui/extjs_dvb.c index f436c242..89ecb8e7 100644 --- a/src/webui/extjs_dvb.c +++ b/src/webui/extjs_dvb.c @@ -166,6 +166,20 @@ extjs_mpegts_service return 0; } +static void +http_api_boilerplate + (http_connection_t *hc, const char **op, htsmsg_t **args) +{ + const char *s; + *op = http_arg_get(&hc->hc_req_args, "op"); + s = http_arg_get(&hc->hc_req_args, "args"); + if (s) + *args = htsmsg_json_deserialize(s); + else + *args = NULL; + if (!*op && *args) + *op = htsmsg_get_str(*args, "method"); // HTSP compat +} static int extjs_mpegts_mux @@ -173,11 +187,16 @@ extjs_mpegts_mux { mpegts_network_t *mn; mpegts_mux_t *mm; - htsbuf_queue_t *hq = &hc->hc_reply; - const char *op = http_arg_get(&hc->hc_req_args, "op"); + htsbuf_queue_t *hq = &hc->hc_reply; + const char *op; + htsmsg_t *args; htsmsg_t *out = htsmsg_create_map(); extjs_grid_conf_t conf = { 0 }; + http_api_boilerplate(hc, &op, &args); + if (!op) + return HTTP_STATUS_BAD_REQUEST; + if (!strcmp(op, "list")) { idnode_set_t ins = { 0 }; extjs_grid_conf(&hc->hc_req_args, &conf); @@ -191,6 +210,17 @@ extjs_mpegts_mux } else if (!strcmp(op, "class")) { htsmsg_t *list = idclass_serialize(&mpegts_mux_class); htsmsg_add_msg(out, "entries", list); + } else if (!strcmp(op, "delete") && args) { + htsmsg_field_t *f; + htsmsg_t *uuids = htsmsg_get_list(args, "uuids"); + if (uuids) { + pthread_mutex_lock(&global_lock); + HTSMSG_FOREACH(f, uuids) { + if (f->hmf_type == HMF_STR) + mpegts_mux_delete_by_uuid(f->hmf_str); + } + pthread_mutex_unlock(&global_lock); + } } htsmsg_json_serialize(out, hq, 0); @@ -363,22 +393,32 @@ extjs_mpegts_input } else if (!strcmp(op, "network_class")) { const char *uuid = http_arg_get(&hc->hc_req_args, "uuid"); if (!uuid) return 404; + pthread_mutex_lock(&global_lock); mpegts_input_t *mi = idnode_find(uuid, &mpegts_input_class); - if (!mi) return 404; + if (!mi) { + pthread_mutex_unlock(&global_lock); + return 404; + } htsmsg_t *list= idclass_serialize(mi->mi_network_class(mi)); htsmsg_add_msg(out, "entries", list); + pthread_mutex_unlock(&global_lock); } else if (!strcmp(op, "network_create")) { const char *uuid = http_arg_get(&hc->hc_req_args, "uuid"); const char *conf = http_arg_get(&hc->hc_req_args, "conf"); if (!uuid || !conf) return 404; + pthread_mutex_lock(&global_lock); mi = idnode_find(uuid, &mpegts_input_class); - if (!mi) return 404; + if (!mi) { + pthread_mutex_unlock(&global_lock); + return 404; + } mn = mi->mi_network_create(mi, htsmsg_json_deserialize(conf)); if (mn) mn->mn_config_save(mn); else { // TODO: Check for error } + pthread_mutex_unlock(&global_lock); #endif } diff --git a/src/webui/static/app/idnode.js b/src/webui/static/app/idnode.js index 6615ee8a..7b56d24d 100644 --- a/src/webui/static/app/idnode.js +++ b/src/webui/static/app/idnode.js @@ -4,6 +4,8 @@ json_decode = function(d) d = Ext.util.JSON.decode(d.responseText) if (d.entries) d = d.entries; + if (d.nodes) + d = d.nodes; } else { d = [] } @@ -498,7 +500,24 @@ tvheadend.idnode_grid = function(panel, conf) iconCls : 'remove', text : 'Delete', disabled : true, - handler : function(){} + handler : function() { + var r = select.getSelections(); + if (r) { + var uuids = [] + for ( var i = 0; i < r.length; i++ ) + uuids.push(r[i].id) + Ext.Ajax.request({ + url : conf.url, + params : { + op: 'delete', + args : Ext.util.JSON.encode({ uuids: uuids}) + }, + success : function(d) + { + } + }); + } + } }); buttons.push(delBtn); } @@ -539,7 +558,7 @@ tvheadend.idnode_grid = function(panel, conf) success : function(d) { d = json_decode(d); - var p = tvheadend.idnode_editor(d[0], {}); + var p = tvheadend.idnode_editor(d, {}); var w = new Ext.Window({ title : 'Edit ' + conf.titleS, layout : 'fit',