From 1298adb95602640509136363dfbde33b0f375ce3 Mon Sep 17 00:00:00 2001 From: Adam Sutton Date: Mon, 17 Mar 2014 17:40:37 +0000 Subject: [PATCH] mpegts: make the mapping of network<->input N<->N I've rejected doing this for ages, however there are real limitations with not being able to do this. And I've specifically come across one while thinking about how some IPTV changes would be handled. This will probably result in a break to peoples config, I will try and mitigate this. --- src/input/mpegts.h | 35 +++++-- src/input/mpegts/mpegts_input.c | 148 ++++++++++++++++++++++++++---- src/input/mpegts/mpegts_network.c | 15 ++- 3 files changed, 169 insertions(+), 29 deletions(-) diff --git a/src/input/mpegts.h b/src/input/mpegts.h index 6370b49c..1e537316 100644 --- a/src/input/mpegts.h +++ b/src/input/mpegts.h @@ -40,12 +40,14 @@ typedef struct mpegts_mux_instance mpegts_mux_instance_t; typedef struct mpegts_mux_sub mpegts_mux_sub_t; typedef struct mpegts_input mpegts_input_t; typedef struct mpegts_table_feed mpegts_table_feed_t; +typedef struct mpegts_network_link mpegts_network_link_t; /* Lists */ -typedef LIST_HEAD (,mpegts_network) mpegts_network_list_t; -typedef LIST_HEAD (mpegts_input_list,mpegts_input) mpegts_input_list_t; -typedef TAILQ_HEAD(mpegts_mux_queue,mpegts_mux) mpegts_mux_queue_t; -typedef LIST_HEAD (mpegts_mux_list,mpegts_mux) mpegts_mux_list_t; +typedef LIST_HEAD (,mpegts_network) mpegts_network_list_t; +typedef LIST_HEAD (,mpegts_input) mpegts_input_list_t; +typedef TAILQ_HEAD(mpegts_mux_queue,mpegts_mux) mpegts_mux_queue_t; +typedef LIST_HEAD (,mpegts_mux) mpegts_mux_list_t; +typedef LIST_HEAD (,mpegts_network_link) mpegts_network_link_list_t; TAILQ_HEAD(mpegts_table_feed_queue, mpegts_table_feed); /* Classes */ @@ -190,6 +192,16 @@ void mpegts_psi_section_reassemble * Logical network * *************************************************************************/ +/* Network/Input linkage */ +struct mpegts_network_link +{ + int mnl_mark; + mpegts_input_t *mnl_input; + mpegts_network_t *mnl_network; + LIST_ENTRY(mpegts_network_link) mnl_mn_link; + LIST_ENTRY(mpegts_network_link) mnl_mi_link; +}; + /* Network */ struct mpegts_network { @@ -212,7 +224,7 @@ struct mpegts_network /* * Inputs */ - mpegts_input_list_t mn_inputs; + mpegts_network_link_list_t mn_inputs; /* * Multiplexes @@ -419,8 +431,7 @@ struct mpegts_input LIST_ENTRY(mpegts_input) mi_global_link; - mpegts_network_t *mi_network; - LIST_ENTRY(mpegts_input) mi_network_link; + mpegts_network_link_list_t mi_networks; LIST_HEAD(,mpegts_mux_instance) mi_mux_active; @@ -509,13 +520,21 @@ void mpegts_input_delete ( mpegts_input_t *mi, int delconf ); #define mpegts_input_find(u) idnode_find(u, &mpegts_input_class); -void mpegts_input_set_network ( mpegts_input_t *mi, mpegts_network_t *mn ); +int mpegts_input_set_networks ( mpegts_input_t *mi, htsmsg_t *msg ); + +int mpegts_input_add_network ( mpegts_input_t *mi, mpegts_network_t *mn ); void mpegts_input_open_service ( mpegts_input_t *mi, mpegts_service_t *s, int init ); void mpegts_input_close_service ( mpegts_input_t *mi, mpegts_service_t *s ); void mpegts_input_status_timer ( void *p ); +/* TODO: exposing these class methods here is a bit of a hack */ +const void *mpegts_input_class_network_get ( void *o ); +int mpegts_input_class_network_set ( void *o, const void *p ); +htsmsg_t *mpegts_input_class_network_enum ( void *o ); +char *mpegts_input_class_network_rend ( void *o ); + void mpegts_network_register_builder ( const idclass_t *idc, mpegts_network_t *(*build)(const idclass_t *idc, htsmsg_t *conf) ); diff --git a/src/input/mpegts/mpegts_input.c b/src/input/mpegts/mpegts_input.c index 2c053bd0..9d715ac3 100644 --- a/src/input/mpegts/mpegts_input.c +++ b/src/input/mpegts/mpegts_input.c @@ -23,12 +23,15 @@ #include "subscriptions.h" #include "atomic.h" #include "notify.h" +#include "idnode.h" #include #include SKEL_DECLARE(mpegts_pid_sub_skel, mpegts_pid_sub_t); +static void +mpegts_input_del_network ( mpegts_network_link_t *mnl ); /* ************************************************************************** * Class definition @@ -43,6 +46,59 @@ mpegts_input_class_get_title ( idnode_t *in ) return buf; } +const void * +mpegts_input_class_network_get ( void *obj ) +{ + mpegts_network_link_t *mnl; + mpegts_input_t *mi = obj; + htsmsg_t *l = htsmsg_create_list(); + + LIST_FOREACH(mnl, &mi->mi_networks, mnl_mi_link) + htsmsg_add_str(l, NULL, idnode_uuid_as_str(&mnl->mnl_network->mn_id)); + + return l; +} + +int +mpegts_input_class_network_set ( void *obj, const void *p ) +{ + return mpegts_input_set_networks(obj, (htsmsg_t*)p); +} + +htsmsg_t * +mpegts_input_class_network_enum ( void *obj ) +{ + htsmsg_t *p, *m; + + p = htsmsg_create_map(); + htsmsg_add_str (p, "uuid", idnode_uuid_as_str((idnode_t*)obj)); + htsmsg_add_bool(p, "enum", 1); + + m = htsmsg_create_map(); + htsmsg_add_str (m, "type", "api"); + htsmsg_add_str (m, "uri", "mpegts/input/network_list"); + htsmsg_add_str (m, "event", "mpegts_network"); + htsmsg_add_msg (m, "params", p); + return m; +} + +char * +mpegts_input_class_network_rend ( void *obj ) +{ + char *str; + mpegts_network_link_t *mnl; + mpegts_input_t *mi = obj; + htsmsg_t *l = htsmsg_create_list(); + + LIST_FOREACH(mnl, &mi->mi_networks, mnl_mi_link) + htsmsg_add_str(l, NULL, idnode_get_title(&mnl->mnl_network->mn_id)); + + str = htsmsg_list_2_csv(l); + htsmsg_destroy(l); + + return str; +} + const idclass_t mpegts_input_class = { .ic_class = "mpegts_input", @@ -71,6 +127,16 @@ const idclass_t mpegts_input_class = .off = offsetof(mpegts_input_t, mi_name), .notify = idnode_notify_title_changed, }, + { + .type = PT_STR, + .id = "networks", + .name = "Networks", + .islist = 1, + .set = mpegts_input_class_network_set, + .get = mpegts_input_class_network_get, + .list = mpegts_input_class_network_enum, + .rend = mpegts_input_class_network_rend, + }, {} } }; @@ -711,7 +777,9 @@ mpegts_input_create0 void mpegts_input_delete ( mpegts_input_t *mi, int delconf ) { - mpegts_input_set_network(mi, NULL); + mpegts_network_link_t *mnl; + while ((mnl = LIST_FIRST(&mi->mi_networks))) + mpegts_input_del_network(mnl); idnode_unlink(&mi->ti_id); pthread_mutex_destroy(&mi->mi_delivery_mutex); pthread_cond_destroy(&mi->mi_table_feed_cond); @@ -728,27 +796,71 @@ mpegts_input_save ( mpegts_input_t *mi, htsmsg_t *m ) idnode_save(&mi->ti_id, m); } -void -mpegts_input_set_network ( mpegts_input_t *mi, mpegts_network_t *mn ) +int +mpegts_input_add_network ( mpegts_input_t *mi, mpegts_network_t *mn ) { - char buf1[256], buf2[265]; - if (mi->mi_network == mn) return; - *buf1 = *buf2 = 0; - if (mi->mi_display_name) { - mi->mi_display_name(mi, buf1, sizeof(buf1)); + mpegts_network_link_t *mnl; + + /* Find existing */ + LIST_FOREACH(mnl, &mi->mi_networks, mnl_mi_link) + if (mnl->mnl_network == mn) + break; + + /* Clear mark */ + if (mnl) { + mnl->mnl_mark = 0; + return 0; } - if (mi->mi_network) { - mi->mi_network->mn_display_name(mi->mi_network, buf2, sizeof(buf2)); - LIST_REMOVE(mi, mi_network_link); - tvhdebug("mpegts", "%s - remove network %s", buf1, buf2); - mi->mi_network = NULL; + + /* Create new */ + mnl = calloc(1, sizeof(mpegts_network_link_t)); + mnl->mnl_input = mi; + mnl->mnl_network = mn; + LIST_INSERT_HEAD(&mi->mi_networks, mnl, mnl_mi_link); + LIST_INSERT_HEAD(&mn->mn_inputs, mnl, mnl_mn_link); + idnode_notify_simple(&mnl->mnl_network->mn_id); + return 1; +} + +static void +mpegts_input_del_network ( mpegts_network_link_t *mnl ) +{ + idnode_notify_simple(&mnl->mnl_network->mn_id); + LIST_REMOVE(mnl, mnl_mn_link); + LIST_REMOVE(mnl, mnl_mi_link); + free(mnl); +} + +int +mpegts_input_set_networks ( mpegts_input_t *mi, htsmsg_t *msg ) +{ + int save = 0; + const char *str; + htsmsg_field_t *f; + mpegts_network_t *mn; + mpegts_network_link_t *mnl, *nxt; + + /* Mark for deletion */ + LIST_FOREACH(mnl, &mi->mi_networks, mnl_mi_link) + mnl->mnl_mark = 1; + + /* Link */ + HTSMSG_FOREACH(f, msg) { + if (!(str = htsmsg_field_get_str(f))) continue; + if (!(mn = mpegts_network_find(str))) continue; + save |= mpegts_input_add_network(mi, mn); } - if (mn) { - mn->mn_display_name(mn, buf2, sizeof(buf2)); - mi->mi_network = mn; - LIST_INSERT_HEAD(&mn->mn_inputs, mi, mi_network_link); - tvhdebug("mpegts", "%s - added network %s", buf1, buf2); + + /* Unlink */ + for (mnl = LIST_FIRST(&mi->mi_networks); mnl != NULL; mnl = nxt) { + nxt = LIST_NEXT(mnl, mnl_mi_link); + if (mnl->mnl_mark) { + mpegts_input_del_network(mnl); + save = 1; + } } + + return save; } /****************************************************************************** diff --git a/src/input/mpegts/mpegts_network.c b/src/input/mpegts/mpegts_network.c index f531e6a9..b62cffcd 100644 --- a/src/input/mpegts/mpegts_network.c +++ b/src/input/mpegts/mpegts_network.c @@ -208,12 +208,21 @@ mpegts_network_mux_create2 return NULL; } +static void +mpegts_network_link_delete ( mpegts_network_link_t *mnl ) +{ + idnode_notify_simple(&mnl->mnl_input->ti_id); + LIST_REMOVE(mnl, mnl_mn_link); + LIST_REMOVE(mnl, mnl_mi_link); + free(mnl); +} + void mpegts_network_delete ( mpegts_network_t *mn, int delconf ) { - mpegts_input_t *mi; mpegts_mux_t *mm; + mpegts_network_link_t *mnl; /* Remove from global list */ LIST_REMOVE(mn, mn_global_link); @@ -231,8 +240,8 @@ mpegts_network_delete gtimer_disarm(&mn->mn_initial_scan_timer); /* Remove from input */ - while ((mi = LIST_FIRST(&mn->mn_inputs))) - mpegts_input_set_network(mi, NULL); + while ((mnl = LIST_FIRST(&mn->mn_inputs))) + mpegts_network_link_delete(mnl); /* Free memory */ idnode_unlink(&mn->mn_id);