mpegts/linuxdvb: reworking of network creation and notification

Should now get notifications for most things in the UI. However
there could be possible data overload if there are frequent small
updates.
This commit is contained in:
Adam Sutton 2013-07-09 14:37:23 +01:00
parent 3c9ac3a64f
commit 3e6ff52146
12 changed files with 180 additions and 125 deletions

View file

@ -402,28 +402,35 @@ struct mpegts_input
void (*mi_open_service) (mpegts_input_t*,mpegts_service_t*,int first);
void (*mi_close_service) (mpegts_input_t*,mpegts_service_t*);
void (*mi_create_mux_instance) (mpegts_input_t*,mpegts_mux_t*);
const idclass_t *(*mi_network_class) (mpegts_input_t *mi);
mpegts_network_t *(*mi_network_create) (mpegts_input_t *mi, htsmsg_t *c);
void (*mi_started_mux) (mpegts_input_t*,mpegts_mux_instance_t*);
void (*mi_stopped_mux) (mpegts_input_t*,mpegts_mux_instance_t*);
int (*mi_has_subscription) (mpegts_input_t*, mpegts_mux_t *mm);
int (*mi_grace_period) (mpegts_input_t*, mpegts_mux_t *mm);
};
#endif /* __TVH_MPEGTS_H__ */
/* ****************************************************************************
* Lists
* ***************************************************************************/
extern mpegts_network_list_t mpegts_network_all;
typedef struct mpegts_network_builder {
LIST_ENTRY(mpegts_network_builder) link;
const idclass_t *idc;
mpegts_network_t * (*build) ( const idclass_t *idc, htsmsg_t *conf );
} mpegts_network_builder_t;
typedef LIST_HEAD(,mpegts_network_builder) mpegts_network_builder_list_t;
extern mpegts_network_builder_list_t mpegts_network_builders;
extern mpegts_input_list_t mpegts_input_all;
/* ****************************************************************************
* Functions
* ***************************************************************************/
extern mpegts_input_list_t mpegts_input_all;
mpegts_input_t *mpegts_input_create0
( mpegts_input_t *mi, const idclass_t *idc, const char *uuid, htsmsg_t *c );
@ -439,6 +446,13 @@ void mpegts_input_set_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_network_register_builder
( const idclass_t *idc,
mpegts_network_t *(*build)(const idclass_t *idc, htsmsg_t *conf) );
mpegts_network_t *mpegts_network_build
( const char *clazz, htsmsg_t *conf );
mpegts_network_t *mpegts_network_create0
( mpegts_network_t *mn, const idclass_t *idc, const char *uuid,
const char *name, htsmsg_t *conf );
@ -532,6 +546,7 @@ mpegts_service_t *mpegts_service_find
void mpegts_service_save ( mpegts_service_t *s, htsmsg_t *c );
#endif /* __TVH_MPEGTS_H__ */
/******************************************************************************
* Editor Configuration

View file

@ -124,7 +124,8 @@ linuxdvb_adapter_create0
}
LIST_INSERT_HEAD(&ld->lh_children, (linuxdvb_hardware_t*)la, lh_parent_link);
la->lh_parent = (linuxdvb_hardware_t*)ld;
la->lh_parent = (linuxdvb_hardware_t*)ld;
la->mi_enabled = 1;
/* No conf */
if (!conf)

View file

@ -232,6 +232,9 @@ linuxdvb_device_create0 ( const char *uuid, htsmsg_t *conf )
}
LIST_INSERT_HEAD(&linuxdvb_device_all, (linuxdvb_hardware_t*)ld, lh_parent_link);
/* Defaults */
ld->mi_enabled = 1;
/* No config */
if (!conf)
return ld;

View file

@ -1,4 +1,5 @@
/*
rk_class
* Tvheadend - Linux DVB frontend
*
* Copyright (C) 2013 Adam Sutton
@ -42,17 +43,6 @@ linuxdvb_frontend_input_thread ( void *aux );
extern const idclass_t linuxdvb_hardware_class;
static const char *
linuxdvb_frontend_class_get_title ( idnode_t *in )
{
linuxdvb_frontend_t *lfe = (linuxdvb_frontend_t*)in;
if (lfe->mi_displayname)
return lfe->mi_displayname;
if (lfe->lfe_fe_path)
return lfe->lfe_fe_path;
return "unknown";
}
static void
linuxdvb_frontend_class_save ( idnode_t *in )
{
@ -126,7 +116,6 @@ const idclass_t linuxdvb_frontend_class =
.ic_super = &linuxdvb_hardware_class,
.ic_class = "linuxdvb_frontend",
.ic_caption = "Linux DVB Frontend",
.ic_get_title = linuxdvb_frontend_class_get_title,
.ic_save = linuxdvb_frontend_class_save,
.ic_properties = (const property_t[]) {
{
@ -235,21 +224,6 @@ const idclass_t linuxdvb_frontend_atsc_class =
* Class methods
* *************************************************************************/
static const idclass_t *
linuxdvb_frontend_network_class ( mpegts_input_t *mi )
{
extern const idclass_t linuxdvb_network_class;
return &linuxdvb_network_class;
}
static mpegts_network_t *
linuxdvb_frontend_network_create ( mpegts_input_t *mi, htsmsg_t *conf )
{
linuxdvb_frontend_t *lfe = (linuxdvb_frontend_t*)mi;
return (mpegts_network_t*)
linuxdvb_network_create0(NULL, lfe->lfe_info.type, conf);
}
static int
linuxdvb_frontend_is_enabled ( mpegts_input_t *mi )
{
@ -260,12 +234,6 @@ linuxdvb_frontend_is_enabled ( mpegts_input_t *mi )
return 1;
}
static void
linuxdvb_frontend_display_name ( mpegts_input_t* mi, char *buf, size_t len )
{
strncpy(buf, linuxdvb_frontend_class_get_title(&mi->mi_id) ?: "", len);
}
#if 0
static int
linuxdvb_frontend_is_free ( mpegts_input_t *mi )
@ -857,13 +825,10 @@ linuxdvb_frontend_create0
/* Input callbacks */
lfe->mi_is_enabled = linuxdvb_frontend_is_enabled;
lfe->mi_display_name = linuxdvb_frontend_display_name;
lfe->mi_start_mux = linuxdvb_frontend_start_mux;
lfe->mi_stop_mux = linuxdvb_frontend_stop_mux;
lfe->mi_open_service = linuxdvb_frontend_open_service;
lfe->mi_close_service = linuxdvb_frontend_close_service;
lfe->mi_network_class = linuxdvb_frontend_network_class;
lfe->mi_network_create = linuxdvb_frontend_network_create;
lfe->lfe_open_pid = linuxdvb_frontend_open_pid;
/* Adapter link */
@ -930,6 +895,10 @@ linuxdvb_frontend_added
}
}
/* Defaults */
if (!lfe->mi_displayname)
lfe->mi_displayname = strdup(fe_path);
/* Copy info */
lfe->lfe_number = fe_num;
memcpy(&lfe->lfe_info, fe_info, sizeof(struct dvb_frontend_info));

View file

@ -36,38 +36,52 @@
extern const idclass_t mpegts_network_class;
static const void *
mpegts_network_class_get_lntype
( void * ptr )
{
static const char *s;
s = dvb_type2str(((linuxdvb_network_t*)ptr)->ln_type);
return &s;
}
static int
mpegts_network_class_set_lntype
( void *ptr, const void *v )
{
const char *str = v;
((linuxdvb_network_t*)ptr)->ln_type = dvb_str2type(str);
return 1;
}
const idclass_t linuxdvb_network_class =
{
.ic_super = &mpegts_network_class,
.ic_class = "linuxdvb_network",
.ic_caption = "LinuxDVB Network",
.ic_properties = (const property_t[]){
{
.type = PT_STR,
.id = "type",
.name = "Network Type",
.opts = PO_RDONLY,
.get = mpegts_network_class_get_lntype,
.set = mpegts_network_class_set_lntype,
},
{}
}
};
const idclass_t linuxdvb_network_dvbt_class =
{
.ic_super = &linuxdvb_network_class,
.ic_class = "linuxdvb_network_dvbt",
.ic_caption = "DVB-T Network",
.ic_properties = (const property_t[]) {
{}
}
};
const idclass_t linuxdvb_network_dvbc_class =
{
.ic_super = &linuxdvb_network_class,
.ic_class = "linuxdvb_network_dvbc",
.ic_caption = "DVB-C Network",
.ic_properties = (const property_t[]) {
{}
}
};
const idclass_t linuxdvb_network_dvbs_class =
{
.ic_super = &linuxdvb_network_class,
.ic_class = "linuxdvb_network_dvbs",
.ic_caption = "DVB-S Network",
.ic_properties = (const property_t[]) {
{}
}
};
const idclass_t linuxdvb_network_atsc_class =
{
.ic_super = &linuxdvb_network_class,
.ic_class = "linuxdvb_network_atsc",
.ic_caption = "ATSC Network",
.ic_properties = (const property_t[]) {
{}
}
};
@ -97,6 +111,7 @@ linuxdvb_network_config_save ( mpegts_network_t *mn )
{
htsmsg_t *c = htsmsg_create_map();
idnode_save(&mn->mn_id, c);
htsmsg_add_str(c, "class", mn->mn_id.in_class->ic_class);
hts_settings_save(c, "input/linuxdvb/networks/%s/config",
idnode_uuid_as_str(&mn->mn_id));
htsmsg_destroy(c);
@ -133,19 +148,15 @@ linuxdvb_network_mux_class
extern const idclass_t linuxdvb_mux_dvbc_class;
extern const idclass_t linuxdvb_mux_dvbs_class;
extern const idclass_t linuxdvb_mux_atsc_class;
linuxdvb_network_t *ln = (linuxdvb_network_t*)mn;
switch (ln->ln_type) {
case FE_OFDM:
return &linuxdvb_mux_dvbt_class;
case FE_QAM:
return &linuxdvb_mux_dvbc_class;
case FE_QPSK:
return &linuxdvb_mux_dvbs_class;
case FE_ATSC:
return &linuxdvb_mux_atsc_class;
default:
return NULL;
}
if (idnode_is_instance(&mn->mn_id, &linuxdvb_network_dvbt_class))
return &linuxdvb_mux_dvbt_class;
if (idnode_is_instance(&mn->mn_id, &linuxdvb_network_dvbc_class))
return &linuxdvb_mux_dvbc_class;
if (idnode_is_instance(&mn->mn_id, &linuxdvb_network_dvbs_class))
return &linuxdvb_mux_dvbs_class;
if (idnode_is_instance(&mn->mn_id, &linuxdvb_network_atsc_class))
return &linuxdvb_mux_atsc_class;
return NULL;
}
static mpegts_mux_t *
@ -164,17 +175,25 @@ linuxdvb_network_mux_create2
linuxdvb_network_t *
linuxdvb_network_create0
( const char *uuid, fe_type_t type, htsmsg_t *conf )
( const char *uuid, const idclass_t *idc, htsmsg_t *conf )
{
linuxdvb_network_t *ln;
htsmsg_t *c, *e;
htsmsg_field_t *f;
/* Create */
if (!(ln = mpegts_network_create(linuxdvb_network, uuid, NULL, conf)))
if (!(ln = (linuxdvb_network_t*)mpegts_network_create0(calloc(1, sizeof(linuxdvb_network_t)),
idc, uuid, NULL, conf)))
return NULL;
if (type != -1)
ln->ln_type = type;
if (idc == &linuxdvb_network_dvbt_class)
ln->ln_type = FE_OFDM;
else if (idc == &linuxdvb_network_dvbc_class)
ln->ln_type = FE_QAM;
else if (idc == &linuxdvb_network_dvbs_class)
ln->ln_type = FE_QPSK;
else
ln->ln_type = FE_ATSC;
/* Callbacks */
ln->mn_create_mux = linuxdvb_network_create_mux;
@ -199,18 +218,45 @@ linuxdvb_network_create0
return ln;
}
static mpegts_network_t *
linuxdvb_network_builder
( const idclass_t *idc, htsmsg_t *conf )
{
return (mpegts_network_t*)linuxdvb_network_create0(NULL, idc, conf);
}
void linuxdvb_network_init ( void )
{
htsmsg_t *c, *e;
htsmsg_field_t *f;
const char *s;
int i;
const idclass_t* classes[] = {
&linuxdvb_network_dvbt_class,
&linuxdvb_network_dvbc_class,
&linuxdvb_network_dvbs_class,
&linuxdvb_network_atsc_class,
};
/* Register class builders */
for (i = 0; i < ARRAY_SIZE(classes); i++)
mpegts_network_register_builder(classes[i], linuxdvb_network_builder);
/* Load settings */
if (!(c = hts_settings_load_r(1, "input/linuxdvb/networks")))
return;
HTSMSG_FOREACH(f, c) {
if (!(e = htsmsg_get_map_by_field(f))) continue;
if (!(e = htsmsg_get_map(e, "config"))) continue;
(void)linuxdvb_network_create0(f->hmf_name, -1, e);
if (!(s = htsmsg_get_str(e, "class"))) continue;
for (i = 0; i < ARRAY_SIZE(classes); i++) {
if(!strcmp(classes[i]->ic_class, s)) {
(void)linuxdvb_network_create0(f->hmf_name, classes[i], e);
break;
}
}
}
htsmsg_destroy(c);
}

View file

@ -188,7 +188,7 @@ void linuxdvb_network_init ( void );
linuxdvb_network_t *linuxdvb_network_find_by_uuid(const char *uuid);
linuxdvb_network_t *linuxdvb_network_create0
( const char *uuid, fe_type_t type, htsmsg_t *conf );
( const char *uuid, const idclass_t *idc, htsmsg_t *conf );
struct linuxdvb_mux
{

View file

@ -234,7 +234,10 @@ linuxdvb_satconf_class_get_title ( idnode_t *o )
{
static char buf[128];
linuxdvb_satconf_t *ls = (linuxdvb_satconf_t*)o;
ls->mi_display_name((mpegts_input_t*)ls, buf, sizeof(buf));
if (ls->mi_display_name)
ls->mi_display_name((mpegts_input_t*)ls, buf, sizeof(buf));
else
*buf = 0;
return buf;
}
@ -325,20 +328,6 @@ linuxdvb_satconf_display_name ( mpegts_input_t* mi, char *buf, size_t len )
strncpy(buf, "Unknown", len);
}
static const idclass_t *
linuxdvb_satconf_network_class ( mpegts_input_t *mi )
{
extern const idclass_t linuxdvb_network_class;
return &linuxdvb_network_class;
}
static mpegts_network_t *
linuxdvb_satconf_network_create ( mpegts_input_t *mi, htsmsg_t *conf )
{
return (mpegts_network_t*)
linuxdvb_network_create0(NULL, FE_QPSK, conf);
}
static int
linuxdvb_satconf_is_enabled ( mpegts_input_t *mi )
{
@ -549,8 +538,6 @@ linuxdvb_satconf_create0
ls->mi_stop_mux = linuxdvb_satconf_stop_mux;
ls->mi_open_service = linuxdvb_satconf_open_service;
ls->mi_close_service = linuxdvb_satconf_close_service;
ls->mi_network_class = linuxdvb_satconf_network_class;
ls->mi_network_create = linuxdvb_satconf_network_create;
ls->mi_started_mux = linuxdvb_satconf_started_mux;
ls->mi_stopped_mux = linuxdvb_satconf_stopped_mux;
ls->mi_has_subscription = linuxdvb_satconf_has_subscription;
@ -577,6 +564,9 @@ linuxdvb_satconf_create0
if (!ls->ls_lnb)
ls->ls_lnb = linuxdvb_lnb_create0(NULL, NULL, ls);
/* Notification */
idnode_notify("linuxdvb_satconf", &ls->mi_id, 0);
return ls;
}

View file

@ -64,19 +64,6 @@ const idclass_t mpegts_input_class =
* Class methods
* *************************************************************************/
static const idclass_t *
mpegts_input_network_class (mpegts_input_t *mi)
{
extern const idclass_t mpegts_network_class;
return &mpegts_network_class;
}
static mpegts_network_t *
mpegts_input_network_create (mpegts_input_t *mi, htsmsg_t *conf)
{
return NULL;
}
static int
mpegts_input_is_enabled ( mpegts_input_t *mi )
{
@ -397,8 +384,6 @@ mpegts_input_create0
mi->mi_stop_mux = mpegts_input_stop_mux;
mi->mi_open_service = mpegts_input_open_service;
mi->mi_close_service = mpegts_input_close_service;
mi->mi_network_class = mpegts_input_network_class;
mi->mi_network_create = mpegts_input_network_create;
mi->mi_create_mux_instance = mpegts_input_create_mux_instance;
mi->mi_started_mux = mpegts_input_started_mux;
mi->mi_stopped_mux = mpegts_input_stopped_mux;

View file

@ -148,7 +148,7 @@ const idclass_t mpegts_mux_class =
.type = PT_STR,
.id = "network",
.name = "Network",
.opts = PO_RDONLY,
.opts = PO_RDONLY | PO_NOSAVE,
.get = mpegts_mux_class_get_network,
},
{
@ -484,6 +484,11 @@ mpegts_mux_create0
mm->mm_display_name(mm, buf, sizeof(buf));
tvhtrace("mpegts", "%s - created", buf);
/* Notification */
printf("NOTIFY NEW MUX\n");
idnode_notify("mpegts_mux", &mm->mm_id, 0);
idnode_notify(NULL, &mn->mn_id, 0);
return mm;
}

View file

@ -256,6 +256,35 @@ mpegts_network_set_network_name
return 1;
}
/******************************************************************************
* Network classes/creation
*****************************************************************************/
mpegts_network_builder_list_t mpegts_network_builders;
void
mpegts_network_register_builder
( const idclass_t *idc,
mpegts_network_t *(*build) (const idclass_t *idc, htsmsg_t *conf) )
{
mpegts_network_builder_t *mnb = calloc(1, sizeof(mpegts_network_builder_t));
mnb->idc = idc;
mnb->build = build;
LIST_INSERT_HEAD(&mpegts_network_builders, mnb, link);
}
mpegts_network_t *
mpegts_network_build
( const char *clazz, htsmsg_t *conf )
{
mpegts_network_builder_t *mnb;
LIST_FOREACH(mnb, &mpegts_network_builders, link) {
if (!strcmp(mnb->idc->ic_class, clazz))
return mnb->build(mnb->idc, conf);
}
return NULL;
}
/******************************************************************************
* Editor Configuration
*

View file

@ -33,7 +33,10 @@ mpegts_service_class_get_mux ( void *ptr )
{
static char buf[512], *s = buf;
mpegts_service_t *ms = ptr;
ms->s_dvb_mux->mm_display_name(ms->s_dvb_mux, buf, sizeof(buf));
if (ms->s_dvb_mux && ms->s_dvb_mux->mm_display_name)
ms->s_dvb_mux->mm_display_name(ms->s_dvb_mux, buf, sizeof(buf));
else
*buf = 0;
return &s;
}
@ -47,7 +50,7 @@ const idclass_t mpegts_service_class =
.type = PT_STR,
.id = "multiplex",
.name = "Mux",
.opts = PO_RDONLY,
.opts = PO_RDONLY | PO_NOSAVE,
.get = mpegts_service_class_get_mux,
},
{
@ -321,6 +324,11 @@ mpegts_service_create0
mm->mm_display_name(mm, buf, sizeof(buf));
tvhlog(LOG_DEBUG, "mpegts", "%s - add service %04X %s", buf, s->s_dvb_service_id, s->s_dvb_svcname);
/* Notification */
idnode_notify(NULL, &s->s_dvb_mux->mm_id, 0);
idnode_notify(NULL, &s->s_dvb_mux->mm_network->mn_id, 0);
return s;
}

View file

@ -522,6 +522,9 @@ service_create0
if (conf)
service_load(t, conf);
/* Notify */
idnode_notify("service", &t->s_id, 0);
return t;
}
@ -1003,7 +1006,8 @@ static void
service_class_save(struct idnode *self)
{
service_t *s = (service_t *)self;
s->s_config_save(s);
if (s->s_config_save)
s->s_config_save(s);
}
/**