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);