From 3e6ff52146a495e771c19937cd8cabcfa73c736f Mon Sep 17 00:00:00 2001 From: Adam Sutton Date: Tue, 9 Jul 2013 14:37:23 +0100 Subject: [PATCH] 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. --- src/input/mpegts.h | 29 +++- src/input/mpegts/linuxdvb/linuxdvb_adapter.c | 3 +- src/input/mpegts/linuxdvb/linuxdvb_device.c | 3 + src/input/mpegts/linuxdvb/linuxdvb_frontend.c | 41 +----- src/input/mpegts/linuxdvb/linuxdvb_network.c | 134 ++++++++++++------ src/input/mpegts/linuxdvb/linuxdvb_private.h | 2 +- src/input/mpegts/linuxdvb/linuxdvb_satconf.c | 24 +--- src/input/mpegts/mpegts_input.c | 15 -- src/input/mpegts/mpegts_mux.c | 7 +- src/input/mpegts/mpegts_network.c | 29 ++++ src/input/mpegts/mpegts_service.c | 12 +- src/service.c | 6 +- 12 files changed, 180 insertions(+), 125 deletions(-) diff --git a/src/input/mpegts.h b/src/input/mpegts.h index c1f2b3a3..0215422f 100644 --- a/src/input/mpegts.h +++ b/src/input/mpegts.h @@ -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 ); @@ -438,6 +445,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, @@ -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 diff --git a/src/input/mpegts/linuxdvb/linuxdvb_adapter.c b/src/input/mpegts/linuxdvb/linuxdvb_adapter.c index 485b009f..c4407c3b 100644 --- a/src/input/mpegts/linuxdvb/linuxdvb_adapter.c +++ b/src/input/mpegts/linuxdvb/linuxdvb_adapter.c @@ -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) diff --git a/src/input/mpegts/linuxdvb/linuxdvb_device.c b/src/input/mpegts/linuxdvb/linuxdvb_device.c index f4b12b46..37b4b0e8 100644 --- a/src/input/mpegts/linuxdvb/linuxdvb_device.c +++ b/src/input/mpegts/linuxdvb/linuxdvb_device.c @@ -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; diff --git a/src/input/mpegts/linuxdvb/linuxdvb_frontend.c b/src/input/mpegts/linuxdvb/linuxdvb_frontend.c index 103c535a..bc05fae5 100644 --- a/src/input/mpegts/linuxdvb/linuxdvb_frontend.c +++ b/src/input/mpegts/linuxdvb/linuxdvb_frontend.c @@ -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)); diff --git a/src/input/mpegts/linuxdvb/linuxdvb_network.c b/src/input/mpegts/linuxdvb/linuxdvb_network.c index 0cbe4e69..0cfede78 100644 --- a/src/input/mpegts/linuxdvb/linuxdvb_network.c +++ b/src/input/mpegts/linuxdvb/linuxdvb_network.c @@ -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); } diff --git a/src/input/mpegts/linuxdvb/linuxdvb_private.h b/src/input/mpegts/linuxdvb/linuxdvb_private.h index 7eac14a9..85cdc512 100644 --- a/src/input/mpegts/linuxdvb/linuxdvb_private.h +++ b/src/input/mpegts/linuxdvb/linuxdvb_private.h @@ -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 { diff --git a/src/input/mpegts/linuxdvb/linuxdvb_satconf.c b/src/input/mpegts/linuxdvb/linuxdvb_satconf.c index 5c07ca39..32d3e272 100644 --- a/src/input/mpegts/linuxdvb/linuxdvb_satconf.c +++ b/src/input/mpegts/linuxdvb/linuxdvb_satconf.c @@ -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; } diff --git a/src/input/mpegts/mpegts_input.c b/src/input/mpegts/mpegts_input.c index 42312dc3..e862e7e5 100644 --- a/src/input/mpegts/mpegts_input.c +++ b/src/input/mpegts/mpegts_input.c @@ -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; diff --git a/src/input/mpegts/mpegts_mux.c b/src/input/mpegts/mpegts_mux.c index bea5c4e0..50261afe 100644 --- a/src/input/mpegts/mpegts_mux.c +++ b/src/input/mpegts/mpegts_mux.c @@ -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; } diff --git a/src/input/mpegts/mpegts_network.c b/src/input/mpegts/mpegts_network.c index b38228d6..d0c42c56 100644 --- a/src/input/mpegts/mpegts_network.c +++ b/src/input/mpegts/mpegts_network.c @@ -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 * diff --git a/src/input/mpegts/mpegts_service.c b/src/input/mpegts/mpegts_service.c index ac5bc4a6..47f31713 100644 --- a/src/input/mpegts/mpegts_service.c +++ b/src/input/mpegts/mpegts_service.c @@ -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; } diff --git a/src/service.c b/src/service.c index 9801f4b1..a612d16c 100644 --- a/src/service.c +++ b/src/service.c @@ -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); } /**