diff --git a/src/input/mpegts.h b/src/input/mpegts.h index 8cbfb1f9..a2ac78ec 100644 --- a/src/input/mpegts.h +++ b/src/input/mpegts.h @@ -252,28 +252,7 @@ struct mpegts_mux * Fields */ char *mm_dvb_default_authority; - -#if 0 - dvb_mux_conf_t dm_conf; - - char *dm_default_authority; - - TAILQ_HEAD(, epggrab_ota_mux) dm_epg_grab; -#endif - -#if 0 // TODO: do we need this here? or linuxdvb? - struct th_dvb_mux_instance *dm_current_tdmi; - - struct th_dvb_mux_instance_list dm_tdmis; -#endif - -#if 0 // TODO: what about these? - // Derived from dm_conf (more or less) - char *dm_local_identifier; - - int dm_enabled; // TODO: could be derived? -#endif - + int mm_enabled; }; /* Service */ diff --git a/src/input/mpegts/linuxdvb/linuxdvb_adapter.c b/src/input/mpegts/linuxdvb/linuxdvb_adapter.c index f560cbaf..05a26c66 100644 --- a/src/input/mpegts/linuxdvb/linuxdvb_adapter.c +++ b/src/input/mpegts/linuxdvb/linuxdvb_adapter.c @@ -33,11 +33,19 @@ * DVB Adapter * **************************************************************************/ +static void +linuxdvb_adapter_class_save ( idnode_t *in ) +{ + linuxdvb_adapter_t *la = (linuxdvb_adapter_t*)in; + linuxdvb_device_save((linuxdvb_device_t*)la->lh_parent); +} + const idclass_t linuxdvb_adapter_class = { .ic_super = &linuxdvb_hardware_class, .ic_class = "linuxdvb_adapter", .ic_caption = "LinuxDVB Adapter", + .ic_save = linuxdvb_adapter_class_save, .ic_properties = (const property_t[]){ { PROPDEF2("rootpath", "Device Path", PT_STR, linuxdvb_adapter_t, la_rootpath, 1) }, @@ -45,6 +53,30 @@ const idclass_t linuxdvb_adapter_class = } }; +/* + * Save data + */ +void +linuxdvb_adapter_save ( linuxdvb_adapter_t *la, htsmsg_t *m ) +{ + htsmsg_t *l; + linuxdvb_hardware_t *lh; + + linuxdvb_hardware_save((linuxdvb_hardware_t*)la, m); + htsmsg_add_u32(m, "number", la->la_number); + if (la->la_rootpath) + htsmsg_add_str(m, "rootpath", la->la_rootpath); + + /* Frontends */ + l = htsmsg_create_map(); + LIST_FOREACH(lh, &la->lh_children, lh_parent_link) { + htsmsg_t *e = htsmsg_create_map(); + linuxdvb_frontend_save((linuxdvb_frontend_t*)lh, e); + htsmsg_add_msg(l, idnode_uuid_as_str(&lh->mi_id), e); + } + htsmsg_add_msg(m, "frontends", l); +} + /* * Check is free */ @@ -66,9 +98,14 @@ linuxdvb_adapter_current_weight ( linuxdvb_adapter_t *la ) /* * Create */ -static linuxdvb_adapter_t * -linuxdvb_adapter_create0 ( const char *uuid, linuxdvb_device_t *ld, int n ) +linuxdvb_adapter_t * +linuxdvb_adapter_create0 + ( linuxdvb_device_t *ld, const char *uuid, htsmsg_t *conf ) { + uint32_t u32; + const char *str; + htsmsg_t *e; + htsmsg_field_t *f; linuxdvb_adapter_t *la; la = calloc(1, sizeof(linuxdvb_adapter_t)); @@ -76,11 +113,28 @@ linuxdvb_adapter_create0 ( const char *uuid, linuxdvb_device_t *ld, int n ) free(la); return NULL; } - la->la_number = n; LIST_INSERT_HEAD(&ld->lh_children, (linuxdvb_hardware_t*)la, lh_parent_link); la->lh_parent = (linuxdvb_hardware_t*)ld; + /* No conf */ + if (!conf) + return la; + + linuxdvb_hardware_load((linuxdvb_hardware_t*)la, conf); + if (!htsmsg_get_u32(conf, "number", &u32)) + la->la_number = u32; + if ((str = htsmsg_get_str(conf, "rootpath"))) + la->la_rootpath = strdup(str); + + /* Frontends */ + if ((conf = htsmsg_get_map(conf, "frontends"))) { + HTSMSG_FOREACH(f, conf) { + if (!(e = htsmsg_get_map_by_field(f))) continue; + (void)linuxdvb_frontend_create0(la, f->hmf_name, e, 0); + } + } + return la; } @@ -110,11 +164,12 @@ linuxdvb_adapter_find_by_number ( int adapter ) /* Create */ if (!la) { - if (!(la = linuxdvb_adapter_create0(NULL, ld, a))) + if (!(la = linuxdvb_adapter_create0(ld, NULL, NULL))) return NULL; } /* Update */ + la->la_number = a; snprintf(buf, sizeof(buf), "/dev/dvb/adapter%d", adapter); tvh_str_update(&la->la_rootpath, buf); if (!la->lh_displayname) @@ -181,7 +236,8 @@ linuxdvb_adapter_added ( int adapter ) linuxdvb_frontend_added(la, i, fe_path, dmx_path, dvr_path, &dfi); } + if (la) + linuxdvb_device_save((linuxdvb_device_t*)la->lh_parent); + return la; } - - diff --git a/src/input/mpegts/linuxdvb/linuxdvb_device.c b/src/input/mpegts/linuxdvb/linuxdvb_device.c index 3025f128..c268d3ea 100644 --- a/src/input/mpegts/linuxdvb/linuxdvb_device.c +++ b/src/input/mpegts/linuxdvb/linuxdvb_device.c @@ -48,6 +48,11 @@ devinfo_bus2str ( int p ) { return val2str(p, bustab); } +static int +devinfo_str2bus ( const char *str ) +{ + return str2val(str, bustab); +} /* * Get bus information @@ -143,12 +148,70 @@ get_device_info ( device_info_t *di, int a ) } di->di_id = strdup(buf); } +static void +get_min_dvb_adapter ( device_info_t *di ) +{ + int mina = -1; + char path[512]; + DIR *dp; + struct dirent *de; + + snprintf(path, sizeof(path), "/sys/bus/%s/devices/%s/dvb", + di->di_bus == BUS_PCI ? "pci" : "usb", di->di_path); + + /* Find minimum adapter number */ + if ((dp = opendir(path))) { + while ((de = readdir(dp))) { + int t; + if ((sscanf(de->d_name, "dvb%d.frontend0", &t))) + if (mina == -1 || t < mina) mina = t; + } + } + di->di_min_adapter = mina; +} + + +static void +linuxdvb_device_class_save ( idnode_t *in ) +{ + linuxdvb_device_save((linuxdvb_device_t*)in); +} +void linuxdvb_device_save ( linuxdvb_device_t *ld ) +{ + htsmsg_t *m, *e, *l; + linuxdvb_hardware_t *lh; + + m = htsmsg_create_map(); + + linuxdvb_hardware_save((linuxdvb_hardware_t*)ld, m); + if (ld->ld_devid.di_id) { + htsmsg_add_str(m, "devid", ld->ld_devid.di_id); + htsmsg_add_str(m, "devbus", devinfo_bus2str(ld->ld_devid.di_bus)); + htsmsg_add_str(m, "devpath", ld->ld_devid.di_path); + } else { + printf("OH NO, no device ID\n"); + } + + /* Adapters */ + l = htsmsg_create_map(); + LIST_FOREACH(lh, &ld->lh_children, lh_parent_link) { + e = htsmsg_create_map(); + linuxdvb_adapter_save((linuxdvb_adapter_t*)lh, e); + htsmsg_add_msg(l, idnode_uuid_as_str(&lh->mi_id), e); + } + htsmsg_add_msg(m, "adapters", l); + + /* Save */ + hts_settings_save(m, "input/linuxdvb/devices/%s", + idnode_uuid_as_str(&ld->mi_id)); +} const idclass_t linuxdvb_device_class = { .ic_super = &linuxdvb_hardware_class, .ic_class = "linuxdvb_device", .ic_caption = "LinuxDVB Device", + .ic_save = linuxdvb_device_class_save, .ic_properties = (const property_t[]){ { PROPDEF2("devid", "Device ID", PT_STR, linuxdvb_device_t, ld_devid.di_id, 1) }, @@ -170,6 +233,8 @@ linuxdvb_device_create0 ( const char *uuid, htsmsg_t *conf ) uint32_t u32; const char *str; linuxdvb_device_t *ld; + htsmsg_t *e; + htsmsg_field_t *f; /* Create */ ld = calloc(1, sizeof(linuxdvb_device_t)); @@ -184,15 +249,26 @@ linuxdvb_device_create0 ( const char *uuid, htsmsg_t *conf ) return ld; /* Load config */ + linuxdvb_hardware_load((linuxdvb_hardware_t*)ld, conf); if (!htsmsg_get_u32(conf, "enabled", &u32) && u32) ld->lh_enabled = 1; if ((str = htsmsg_get_str(conf, "displayname"))) ld->lh_displayname = strdup(str); if ((str = htsmsg_get_str(conf, "devid"))) - strncpy(ld->ld_devid.di_id, str, sizeof(ld->ld_devid.di_id)); + ld->ld_devid.di_id = strdup(str); + if ((str = htsmsg_get_str(conf, "devbus"))) + ld->ld_devid.di_bus = devinfo_str2bus(str); + if ((str = htsmsg_get_str(conf, "devpath"))) + strncpy(ld->ld_devid.di_path, str, sizeof(ld->ld_devid.di_path)); + get_min_dvb_adapter(&ld->ld_devid); - // TODO: adapters - // TODO: frontends + /* Adapters */ + if ((conf = htsmsg_get_map(conf, "adapters"))) { + HTSMSG_FOREACH(f, conf) { + if (!(e = htsmsg_get_map_by_field(f))) continue; + (void)linuxdvb_adapter_create0(ld, f->hmf_name, e); + } + } return ld; } @@ -247,7 +323,7 @@ void linuxdvb_device_init ( int adapter_mask ) } } } - + /* Scan for hardware */ if ((dp = opendir("/dev/dvb"))) { struct dirent *de; diff --git a/src/input/mpegts/linuxdvb/linuxdvb_frontend.c b/src/input/mpegts/linuxdvb/linuxdvb_frontend.c index 1dba30e3..45f790b2 100644 --- a/src/input/mpegts/linuxdvb/linuxdvb_frontend.c +++ b/src/input/mpegts/linuxdvb/linuxdvb_frontend.c @@ -39,12 +39,20 @@ linuxdvb_frontend_class_get_title ( idnode_t *in ) return "unknown"; } +static void +linuxdvb_frontend_class_save ( idnode_t *in ) +{ + linuxdvb_frontend_t *lfe = (linuxdvb_frontend_t*)in; + linuxdvb_device_save((linuxdvb_device_t*)lfe->lh_parent->lh_parent); +} + 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[]) { { PROPDEF2("fe_path", "Frontend Path", PT_STR, linuxdvb_frontend_t, lfe_fe_path, 1) }, @@ -100,6 +108,19 @@ const idclass_t linuxdvb_frontend_atsc_class = * Frontend * *************************************************************************/ +void +linuxdvb_frontend_save ( linuxdvb_frontend_t *lfe, htsmsg_t *m ) +{ + htsmsg_add_u32(m, "number", lfe->lfe_number); + htsmsg_add_str(m, "type", dvb_type2str(lfe->lfe_info.type)); + if (lfe->lfe_fe_path) + htsmsg_add_str(m, "fe_path", lfe->lfe_fe_path); + if (lfe->lfe_dmx_path) + htsmsg_add_str(m, "dmx_path", lfe->lfe_dmx_path); + if (lfe->lfe_dvr_path) + htsmsg_add_str(m, "dvr_path", lfe->lfe_dvr_path); +} + static int linuxdvb_frontend_is_free ( mpegts_input_t *mi ) { @@ -250,12 +271,21 @@ linuxdvb_frontend_close_service { } -static linuxdvb_frontend_t * +linuxdvb_frontend_t * linuxdvb_frontend_create0 - ( const char *uuid, linuxdvb_adapter_t *la, int num, fe_type_t type ) + ( linuxdvb_adapter_t *la, const char *uuid, htsmsg_t *conf, fe_type_t type ) { + uint32_t u32; + const char *str; const idclass_t *idc; + /* Get type */ + if (conf) { + if (!(str = htsmsg_get_str(conf, "type"))) + return NULL; + type = dvb_str2type(str); + } + /* Class */ if (type == FE_QPSK) idc = &linuxdvb_frontend_dvbs_class; @@ -273,6 +303,7 @@ linuxdvb_frontend_create0 linuxdvb_frontend_t *lfe = (linuxdvb_frontend_t*) mpegts_input_create0(calloc(1, sizeof(linuxdvb_frontend_t)), idc, uuid); + lfe->lfe_info.type = type; /* Input callbacks */ lfe->mi_start_mux = linuxdvb_frontend_start_mux; @@ -286,6 +317,14 @@ linuxdvb_frontend_create0 lfe->lh_parent = (linuxdvb_hardware_t*)la; LIST_INSERT_HEAD(&la->lh_children, (linuxdvb_hardware_t*)lfe, lh_parent_link); + /* No conf */ + if (!conf) + return lfe; + + if (!htsmsg_get_u32(conf, "number", &u32)) + lfe->lfe_number = u32; + // TODO: network + return lfe; } @@ -315,13 +354,14 @@ linuxdvb_frontend_added /* Create new */ if (!lfe) { - if (!(lfe = linuxdvb_frontend_create0(NULL, la, fe_num, fe_info->type))) { + if (!(lfe = linuxdvb_frontend_create0(la, NULL, NULL, fe_info->type))) { tvhlog(LOG_ERR, "linuxdvb", "failed to create frontend"); return NULL; } } /* Copy info */ + lfe->lfe_number = fe_num; memcpy(&lfe->lfe_info, fe_info, sizeof(struct dvb_frontend_info)); /* Set paths */ diff --git a/src/input/mpegts/linuxdvb/linuxdvb_hardware.c b/src/input/mpegts/linuxdvb/linuxdvb_hardware.c index 1e7b9214..0c62c5c1 100644 --- a/src/input/mpegts/linuxdvb/linuxdvb_hardware.c +++ b/src/input/mpegts/linuxdvb/linuxdvb_hardware.c @@ -45,6 +45,23 @@ linuxdvb_hardware_enumerate ( linuxdvb_hardware_list_t *list ) return v; } +void linuxdvb_hardware_save ( linuxdvb_hardware_t *lh, htsmsg_t *m ) +{ + htsmsg_add_u32(m, "enabled", lh->lh_enabled); + if (lh->lh_displayname) + htsmsg_add_str(m, "displayname", lh->lh_displayname); +} + +void linuxdvb_hardware_load ( linuxdvb_hardware_t *lh, htsmsg_t *conf ) +{ + uint32_t u32; + const char *str; + if (!htsmsg_get_u32(conf, "enabled", &u32) && u32) + lh->lh_enabled = 1; + if ((str = htsmsg_get_str(conf, "displayname"))) + lh->lh_displayname = strdup(str); +} + static const char * linuxdvb_hardware_class_get_title ( idnode_t *in ) { diff --git a/src/input/mpegts/linuxdvb/linuxdvb_mux.c b/src/input/mpegts/linuxdvb/linuxdvb_mux.c index 90248353..a7f446d0 100644 --- a/src/input/mpegts/linuxdvb/linuxdvb_mux.c +++ b/src/input/mpegts/linuxdvb/linuxdvb_mux.c @@ -116,13 +116,64 @@ linuxdvb_mux_close_table ( mpegts_mux_t *mm, mpegts_table_t *mt ) { } +static const char * +dvb_mux_conf_load ( fe_type_t type, dvb_mux_conf_t *dmc, htsmsg_t *m ) +{ + //const char *s; + dmc->dmc_fe_params.inversion = INVERSION_AUTO; + htsmsg_get_u32(m, "frequency", &dmc->dmc_fe_params.frequency); + +#if 0 + switch(tda->tda_type) { + case FE_OFDM: + s = htsmsg_get_str(m, "bandwidth"); + if(s == NULL || (r = str2val(s, bwtab)) < 0) + return "Invalid bandwidth"; + dmc->dmc_fe_params.u.ofdm.bandwidth = r; + + s = htsmsg_get_str(m, "constellation"); + if(s == NULL || (r = str2val(s, qamtab)) < 0) + return "Invalid QAM constellation"; + dmc->dmc_fe_params.u.ofdm.constellation = r; + + s = htsmsg_get_str(m, "transmission_mode"); + if(s == NULL || (r = str2val(s, modetab)) < 0) + return "Invalid transmission mode"; + dmc->dmc_fe_params.u.ofdm.transmission_mode = r; + + s = htsmsg_get_str(m, "guard_interval"); + if(s == NULL || (r = str2val(s, guardtab)) < 0) + return "Invalid guard interval"; + dmc->dmc_fe_params.u.ofdm.guard_interval = r; + + s = htsmsg_get_str(m, "hierarchy"); + if(s == NULL || (r = str2val(s, hiertab)) < 0) + return "Invalid heirarchy information"; + dmc->dmc_fe_params.u.ofdm.hierarchy_information = r; + + s = htsmsg_get_str(m, "fec_hi"); + if(s == NULL || (r = str2val(s, fectab)) < 0) + return "Invalid hi-FEC"; + dmc->dmc_fe_params.u.ofdm.code_rate_HP = r; + + s = htsmsg_get_str(m, "fec_lo"); + if(s == NULL || (r = str2val(s, fectab)) < 0) + return "Invalid lo-FEC"; + dmc->dmc_fe_params.u.ofdm.code_rate_LP = r; + break; + } +#endif + return "Not yet supported"; +} linuxdvb_mux_t * linuxdvb_mux_create0 ( linuxdvb_network_t *ln, const char *uuid, htsmsg_t *conf ) { - //uint32_t u32; - //const char *str; + uint32_t u32; + const char *str; + htsmsg_t *c, *e; + htsmsg_field_t *f; mpegts_mux_t *mm; linuxdvb_mux_t *lm; const idclass_t *idc; @@ -151,10 +202,6 @@ linuxdvb_mux_create0 /* Callbacks */ lm->mm_config_save = linuxdvb_mux_config_save; -#if 0 - lm->mm_start = linuxdvb_mux_start; - lm->mm_stop = linuxdvb_mux_stop; -#endif lm->mm_open_table = linuxdvb_mux_open_table; lm->mm_close_table = linuxdvb_mux_close_table; @@ -163,6 +210,30 @@ linuxdvb_mux_create0 return lm; /* Config */ + // TODO: this could go in mpegts_mux + if (!htsmsg_get_u32(conf, "enabled", &u32) && u32) + lm->mm_enabled = 1; + if (!htsmsg_get_u32(conf, "onid", &u32)) + lm->mm_onid = u32; + if (!htsmsg_get_u32(conf, "tsid", &u32)) + lm->mm_tsid = u32; + if ((str = htsmsg_get_str(conf, "default_authority"))) + lm->mm_dvb_default_authority = strdup(str); + + /* Tuning info */ + if ((e = htsmsg_get_map(conf, "tuning"))) + (void)dvb_mux_conf_load(ln->ln_type, &lm->lm_tuning, e); + + /* Services */ + if ((c = hts_settings_load_r(1, "input/linuxdvb/networks/%s/muxes/%s/services", + "TODO", uuid))) { + HTSMSG_FOREACH(f, c) { + if (!(e = htsmsg_get_map_by_field(f))) continue; + if (!(e = htsmsg_get_map(e, "config"))) continue; + //(void)linuxdvb_service_create0(lm, f->hmf_name, e); + } + htsmsg_destroy(c); + } return lm; } diff --git a/src/input/mpegts/linuxdvb/linuxdvb_private.h b/src/input/mpegts/linuxdvb/linuxdvb_private.h index e9a7595f..985602e3 100644 --- a/src/input/mpegts/linuxdvb/linuxdvb_private.h +++ b/src/input/mpegts/linuxdvb/linuxdvb_private.h @@ -70,6 +70,8 @@ extern const idclass_t linuxdvb_hardware_class; idnode_t ** linuxdvb_hardware_enumerate ( linuxdvb_hardware_list_t *list ); +void linuxdvb_hardware_save ( linuxdvb_hardware_t *lh, htsmsg_t *m ); +void linuxdvb_hardware_load ( linuxdvb_hardware_t *lh, htsmsg_t *m ); struct linuxdvb_device @@ -83,6 +85,7 @@ struct linuxdvb_device }; void linuxdvb_device_init ( int adapter_mask ); +void linuxdvb_device_save ( linuxdvb_device_t *ld ); linuxdvb_device_t *linuxdvb_device_create0 (const char *uuid, htsmsg_t *conf); @@ -103,6 +106,11 @@ struct linuxdvb_adapter #define LINUXDVB_SUBSYS_FE 0x01 #define LINUXDVB_SUBSYS_DVR 0x02 +void linuxdvb_adapter_save ( linuxdvb_adapter_t *la, htsmsg_t *m ); + +linuxdvb_adapter_t *linuxdvb_adapter_create0 + ( linuxdvb_device_t *ld, const char *uuid, htsmsg_t *conf ); + linuxdvb_adapter_t *linuxdvb_adapter_added (int a); int linuxdvb_adapter_is_free ( linuxdvb_adapter_t *la ); @@ -131,11 +139,19 @@ struct linuxdvb_frontend gtimer_t lfe_monitor_timer; }; +linuxdvb_frontend_t * +linuxdvb_frontend_create0 + ( linuxdvb_adapter_t *la, const char *uuid, htsmsg_t *conf, fe_type_t type ); + +void linuxdvb_frontend_save ( linuxdvb_frontend_t *lfe, htsmsg_t *m ); + linuxdvb_frontend_t * linuxdvb_frontend_added ( linuxdvb_adapter_t *la, int fe_num, const char *fe_path, const char *dmx_path, const char *dvr_path, const struct dvb_frontend_info *fe_info ); +void linuxdvb_frontend_add_network + ( linuxdvb_frontend_t *lfe, linuxdvb_network_t *net ); struct linuxdvb_network { @@ -157,7 +173,7 @@ struct linuxdvb_mux /* * Tuning information */ - dvb_mux_conf_t lm_tune_conf; + dvb_mux_conf_t lm_tuning; }; linuxdvb_mux_t *linuxdvb_mux_create0 diff --git a/src/prop.c b/src/prop.c index b025e6c9..899662b5 100644 --- a/src/prop.c +++ b/src/prop.c @@ -169,6 +169,8 @@ prop_seti(void *obj, const property_t *p, const char *value) int i32; const char *s; + if (p->rdonly) return 0; + void *val = obj + p->off; switch(p->type) {