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.
This commit is contained in:
Adam Sutton 2014-03-17 17:40:37 +00:00
parent a3d2062c01
commit 1298adb956
3 changed files with 169 additions and 29 deletions

View file

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

View file

@ -23,12 +23,15 @@
#include "subscriptions.h"
#include "atomic.h"
#include "notify.h"
#include "idnode.h"
#include <pthread.h>
#include <assert.h>
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;
}
/******************************************************************************

View file

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