dvbreorg WIP

Initial scan now works again

We have a new idnode system that can give an entity a UUID which then can
be looked up externally (webui, etc). Good when browsing stuff
The UUID is supposed to be persisted on on disk when saving enteties
This commit is contained in:
Andreas Öman 2013-01-17 16:21:55 +01:00
parent 963a0502d3
commit fef5755fe7
24 changed files with 825 additions and 284 deletions

View file

@ -63,6 +63,7 @@ endif
# Core # Core
# #
SRCS = src/main.c \ SRCS = src/main.c \
src/idnode.c \
src/utils.c \ src/utils.c \
src/wrappers.c \ src/wrappers.c \
src/version.c \ src/version.c \

View file

@ -26,5 +26,6 @@ void
dvb_init(uint32_t adapter_mask, const char *rawfile) dvb_init(uint32_t adapter_mask, const char *rawfile)
{ {
dvb_charset_init(); dvb_charset_init();
dvb_network_init();
dvb_adapter_init(adapter_mask, rawfile); dvb_adapter_init(adapter_mask, rawfile);
} }

View file

@ -24,6 +24,7 @@
#include <pthread.h> #include <pthread.h>
#include "htsmsg.h" #include "htsmsg.h"
#include "psi.h" #include "psi.h"
#include "idnode.h"
struct service; struct service;
struct th_dvb_table; struct th_dvb_table;
@ -35,7 +36,7 @@ struct th_dvb_mux_instance;
(DVB_VER_INT(DVB_API_VERSION, DVB_API_VERSION_MINOR) >= DVB_VER_INT(maj, min)) (DVB_VER_INT(DVB_API_VERSION, DVB_API_VERSION_MINOR) >= DVB_VER_INT(maj, min))
TAILQ_HEAD(th_dvb_adapter_queue, th_dvb_adapter); TAILQ_HEAD(th_dvb_adapter_queue, th_dvb_adapter);
RB_HEAD(th_dvb_mux_instance_tree, th_dvb_mux_instance); LIST_HEAD(th_dvb_adapter_list, th_dvb_adapter);
TAILQ_HEAD(th_dvb_mux_instance_queue, th_dvb_mux_instance); TAILQ_HEAD(th_dvb_mux_instance_queue, th_dvb_mux_instance);
LIST_HEAD(th_dvb_mux_instance_list, th_dvb_mux_instance); LIST_HEAD(th_dvb_mux_instance_list, th_dvb_mux_instance);
TAILQ_HEAD(dvb_satconf_queue, dvb_satconf); TAILQ_HEAD(dvb_satconf_queue, dvb_satconf);
@ -89,11 +90,14 @@ typedef struct dvb_mux_conf {
* *
*/ */
typedef struct dvb_network { typedef struct dvb_network {
idnode_t dn_id;
LIST_ENTRY(dvb_network) dn_global_link; LIST_ENTRY(dvb_network) dn_global_link;
struct dvb_mux_queue dn_initial_scan_queue; struct dvb_mux_queue dn_initial_scan_pending_queue;
int dn_initial_num_mux; struct dvb_mux_queue dn_initial_scan_current_queue;
int dn_initial_scan_num_mux;
gtimer_t dn_initial_scan_timer;
struct dvb_mux *dn_mux_epg; struct dvb_mux *dn_mux_epg;
@ -101,13 +105,11 @@ typedef struct dvb_network {
struct dvb_mux_list dn_muxes; struct dvb_mux_list dn_muxes;
gtimer_t dn_mux_scanner_timer;
uint32_t dn_disable_pmt_monitor; uint32_t dn_disable_pmt_monitor;
uint32_t dn_autodiscovery; uint32_t dn_autodiscovery;
uint32_t dn_nitoid; uint32_t dn_nitoid;
char *dn_uuid; struct th_dvb_adapter_list dn_adapters;
} dvb_network_t; } dvb_network_t;
@ -117,7 +119,7 @@ typedef struct dvb_network {
* *
*/ */
typedef struct dvb_mux { typedef struct dvb_mux {
idnode_t dm_id;
LIST_ENTRY(dvb_mux) dm_network_link; LIST_ENTRY(dvb_mux) dm_network_link;
dvb_network_t *dm_dn; dvb_network_t *dm_dn;
@ -132,14 +134,20 @@ typedef struct dvb_mux {
TAILQ_HEAD(, epggrab_ota_mux) dm_epg_grab; TAILQ_HEAD(, epggrab_ota_mux) dm_epg_grab;
gtimer_t dm_initial_scan_timeout;
TAILQ_ENTRY(dvb_mux) dm_scan_link; TAILQ_ENTRY(dvb_mux) dm_scan_link;
struct dvb_mux_queue *dm_scan_queue; enum {
DM_SCAN_DONE, // All done
DM_SCAN_PENDING, // Waiting to be tuned for initial scan
DM_SCAN_CURRENT, // Currently tuned for initial scan
} dm_scan_status;
LIST_HEAD(, th_dvb_table) dm_tables; LIST_HEAD(, th_dvb_table) dm_tables;
int dm_num_tables; int dm_num_tables;
TAILQ_HEAD(, th_dvb_table) dm_table_queue; TAILQ_HEAD(, th_dvb_table) dm_table_queue;
int dm_table_initial; // int dm_table_initial;
struct th_dvb_mux_instance *dm_current_tdmi; struct th_dvb_mux_instance *dm_current_tdmi;
@ -148,8 +156,6 @@ typedef struct dvb_mux {
// Derived from dm_conf (more or less) // Derived from dm_conf (more or less)
char *dm_local_identifier; char *dm_local_identifier;
char *dm_uuid;
int dm_enabled; int dm_enabled;
} dvb_mux_t; } dvb_mux_t;
@ -193,6 +199,8 @@ typedef struct th_dvb_mux_instance {
int tdmi_tune_failed; // Adapter failed to tune this frequency int tdmi_tune_failed; // Adapter failed to tune this frequency
// Don't try again // Don't try again
int tdmi_weight;
struct th_subscription_list tdmi_subscriptions; struct th_subscription_list tdmi_subscriptions;
} th_dvb_mux_instance_t; } th_dvb_mux_instance_t;
@ -226,6 +234,7 @@ typedef struct th_dvb_adapter {
TAILQ_ENTRY(th_dvb_adapter) tda_global_link; TAILQ_ENTRY(th_dvb_adapter) tda_global_link;
dvb_network_t *tda_dn; dvb_network_t *tda_dn;
LIST_ENTRY(th_dvb_adapter) tda_network_link;
struct th_dvb_mux_instance_list tda_tdmis; struct th_dvb_mux_instance_list tda_tdmis;
@ -479,6 +488,8 @@ dvb_mux_t *dvb_mux_find(dvb_network_t *dn, const char *netname, uint16_t onid,
uint16_t tsid, int enabled); uint16_t tsid, int enabled);
void dvb_mux_initial_scan_done(dvb_mux_t *dm);
/** /**
* DVB Transport (aka DVB service) * DVB Transport (aka DVB service)
*/ */
@ -507,14 +518,12 @@ void dvb_service_notify(struct service *t);
void dvb_service_notify_by_adapter(th_dvb_adapter_t *tda); void dvb_service_notify_by_adapter(th_dvb_adapter_t *tda);
htsmsg_t *dvb_service_build_msg(struct service *t);
/** /**
* DVB Frontend * DVB Frontend
*/ */
int dvb_fe_tune(dvb_mux_t *dm, const char *reason); int dvb_fe_tune(dvb_mux_t *dm, const char *reason, int weight);
void dvb_fe_stop(th_dvb_adapter_t *tda, int retune); //void dvb_fe_stop(th_dvb_adapter_t *tda, int retune);
/** /**
@ -551,9 +560,15 @@ void dvb_table_release(th_dvb_table_t *tdt);
/** /**
* *
*/ */
dvb_network_t *dvb_network_create(int fe_type); dvb_network_t *dvb_network_create(int fe_type, const char *uuid);
void dvb_network_mux_scanner(void *aux); //void dvb_network_mux_scanner(void *aux);
void dvb_network_init(void);
idnode_t **dvb_network_root(void);
void dvb_network_schedule_initial_scan(dvb_network_t *dn);
/** /**

View file

@ -46,7 +46,6 @@
#include "diseqc.h" #include "diseqc.h"
struct th_dvb_adapter_queue dvb_adapters; struct th_dvb_adapter_queue dvb_adapters;
struct th_dvb_mux_instance_tree dvb_muxes;
static void *dvb_adapter_input_dvr(void *aux); static void *dvb_adapter_input_dvr(void *aux);
@ -280,6 +279,20 @@ dvb_adapter_set_extrapriority(th_dvb_adapter_t *tda, int extrapriority)
tda_save(tda); tda_save(tda);
} }
/**
*
*/
static void
dvb_adapter_set_network(th_dvb_adapter_t *tda, const char *uuid)
{
dvb_network_t *dn = LIST_FIRST(&dvb_networks);
tda->tda_dn = dn;
LIST_INSERT_HEAD(&dn->dn_adapters, tda, tda_network_link);
}
/** /**
* *
*/ */
@ -402,7 +415,7 @@ tda_add(int adapter_num)
close(fe); close(fe);
tda->tda_fe_type = tda->tda_fe_info->type; tda->tda_fe_type = tda->tda_fe_info->type;
tda->tda_dn = dvb_network_create(tda->tda_fe_type); dvb_adapter_set_network(tda, NULL);
snprintf(buf, sizeof(buf), "%s_%s", tda->tda_rootpath, snprintf(buf, sizeof(buf), "%s_%s", tda->tda_rootpath,
tda->tda_fe_info->name); tda->tda_fe_info->name);

View file

@ -107,6 +107,7 @@ dvb_fe_monitor(void *aux)
/** /**
* Read out front end status * Read out front end status
*/ */
if(ioctl(tda->tda_fe_fd, FE_READ_STATUS, &fe_status)) if(ioctl(tda->tda_fe_fd, FE_READ_STATUS, &fe_status))
fe_status = 0; fe_status = 0;
@ -254,6 +255,7 @@ dvb_fe_monitor(void *aux)
} }
#if 0
/** /**
* Stop the given TDMI * Stop the given TDMI
*/ */
@ -266,16 +268,8 @@ dvb_fe_stop(th_dvb_adapter_t *tda, int retune)
assert(tdmi != NULL); assert(tdmi != NULL);
dvb_mux_t *dm = tdmi->tdmi_mux; dvb_mux_t *dm = tdmi->tdmi_mux;
if(dm->dm_table_initial) {
dm->dm_table_initial = 0;
dm->dm_dn->dn_initial_num_mux--;
dvb_mux_save(dm);
}
dvb_table_flush_all(dm); dvb_table_flush_all(dm);
assert(dm->dm_scan_queue == NULL);
epggrab_mux_stop(dm, 0); epggrab_mux_stop(dm, 0);
#if 0 /// XXX(dvbreorg) #if 0 /// XXX(dvbreorg)
@ -285,6 +279,9 @@ dvb_fe_stop(th_dvb_adapter_t *tda, int retune)
} }
#endif #endif
} }
#endif
#if DVB_API_VERSION >= 5 #if DVB_API_VERSION >= 5
@ -342,9 +339,8 @@ static struct dtv_properties clear_cmdseq = {
* *
*/ */
static int static int
dvb_fe_tune_s2(th_dvb_mux_instance_t *tdmi, dvb_mux_conf_t *dmc) dvb_fe_tune_s2(th_dvb_adapter_t *tda, dvb_mux_conf_t *dmc)
{ {
th_dvb_adapter_t *tda = tdmi->tdmi_adapter;
struct dvb_frontend_parameters *p = &dmc->dmc_fe_params; struct dvb_frontend_parameters *p = &dmc->dmc_fe_params;
int r; int r;
@ -388,47 +384,151 @@ dvb_fe_tune_s2(th_dvb_mux_instance_t *tdmi, dvb_mux_conf_t *dmc)
#endif #endif
/**
* These are created on the fly
*/
static void
dvb_create_tdmis(dvb_mux_t *dm)
{
th_dvb_mux_instance_t *tdmi;
dvb_network_t *dn = dm->dm_dn;
th_dvb_adapter_t *tda;
LIST_FOREACH(tda, &dn->dn_adapters, tda_network_link) {
LIST_FOREACH(tdmi, &dm->dm_tdmis, tdmi_mux_link) {
if(tdmi->tdmi_adapter != NULL)
break;
}
if(tdmi == NULL) {
tdmi = calloc(1, sizeof(th_dvb_mux_instance_t));
tdmi->tdmi_adapter = tda;
tdmi->tdmi_mux = dm;
LIST_INSERT_HEAD(&tda->tda_tdmis, tdmi, tdmi_adapter_link);
LIST_INSERT_HEAD(&dm->dm_tdmis, tdmi, tdmi_mux_link);
}
}
}
/**
*
*/
static void
dvb_mux_stop(th_dvb_mux_instance_t *tdmi)
{
dvb_mux_t *dm = tdmi->tdmi_mux;
th_dvb_adapter_t *tda = tdmi->tdmi_adapter;
assert(dm->dm_current_tdmi == tdmi);
assert(tda->tda_current_tdmi == tdmi);
dvb_table_flush_all(dm);
epggrab_mux_stop(dm, 0);
assert(dm->dm_scan_status == DM_SCAN_DONE);
dm->dm_current_tdmi = NULL;
tda->tda_current_tdmi = NULL;
printf("NEED TO TAKE CARE OF SERVICES in dvb_mux_stop\n");
}
/**
*
*/
static int
tdmi_compute_weight(const th_dvb_mux_instance_t *tdmi)
{
const dvb_mux_t *dm = tdmi->tdmi_mux;
if(dm->dm_scan_status == DM_SCAN_CURRENT)
return 1;
return 0;
}
/**
*
*/
static void
dvb_mux_initial_scan_timeout(void *aux)
{
dvb_mux_t *dm = aux;
char buf[100];
dvb_mux_nicename(buf, sizeof(buf), dm);
tvhlog(LOG_DEBUG, "dvb", "Initial scan timed out for \"%s\"", buf);
dvb_mux_initial_scan_done(dm);
}
/** /**
* *
*/ */
int int
dvb_fe_tune(dvb_mux_t *dm, const char *reason) dvb_fe_tune(dvb_mux_t *dm, const char *reason, int weight)
{ {
dvb_network_t *dn = dm->dm_dn; dvb_network_t *dn = dm->dm_dn;
th_dvb_mux_instance_t *tdmi = NULL; // dm->dm_tdmi;
th_dvb_adapter_t *tda = tdmi->tdmi_adapter;
// copy dmc, cause frequency may be change with FE_QPSK // copy dmc, cause frequency may be change with FE_QPSK
dvb_mux_conf_t dmc = dm->dm_conf; dvb_mux_conf_t dmc = dm->dm_conf;
dvb_frontend_parameters_t* p = &dmc.dmc_fe_params; dvb_frontend_parameters_t* p = &dmc.dmc_fe_params;
th_dvb_mux_instance_t *tdmi;
char buf[256]; char buf[256];
int r; int r;
assert(dm->dm_current_tdmi == NULL);
lock_assert(&global_lock); lock_assert(&global_lock);
dvb_create_tdmis(dm);
retry:
// Figure which adapter to use
LIST_FOREACH(tdmi, &dm->dm_tdmis, tdmi_mux_link)
if(!tdmi->tdmi_tune_failed && tdmi->tdmi_adapter->tda_current_tdmi == NULL)
break;
if(tdmi == NULL) {
// None available, need to strike one out
LIST_FOREACH(tdmi, &dm->dm_tdmis, tdmi_mux_link) {
if(tdmi->tdmi_tune_failed)
continue;
th_dvb_adapter_t *tda = tdmi->tdmi_adapter;
th_dvb_mux_instance_t *t2 = tda->tda_current_tdmi;
assert(t2 != NULL);
assert(t2 != tdmi);
if(tdmi_compute_weight(t2) < weight) {
dvb_mux_stop(t2);
break;
}
}
if(tdmi == NULL)
return SM_CODE_NO_FREE_ADAPTER;
}
th_dvb_adapter_t *tda = tdmi->tdmi_adapter;
dvb_adapter_start(tda);
assert(tda->tda_current_tdmi == NULL);
free(tda->tda_tune_reason); free(tda->tda_tune_reason);
tda->tda_tune_reason = strdup(reason); tda->tda_tune_reason = strdup(reason);
if(tda->tda_current_tdmi == tdmi) { tdmi->tdmi_weight = weight;
dvb_adapter_notify(tda);
return 0;
}
if(dm->dm_scan_queue != NULL) {
TAILQ_REMOVE(dm->dm_scan_queue, dm, dm_scan_link);
dm->dm_scan_queue = NULL;
}
if(tda->tda_current_tdmi != NULL)
dvb_fe_stop(tda, 1);
else
dvb_adapter_start(tda);
if(tda->tda_fe_type == FE_QPSK) { if(tda->tda_fe_type == FE_QPSK) {
/* DVB-S */ /* DVB-S */
int port, lowfreq, hifreq, switchfreq, hiband, pol, dbsbs; int port, lowfreq, hifreq, switchfreq, hiband, pol, dbsbs;
@ -486,11 +586,11 @@ dvb_fe_tune(dvb_mux_t *dm, const char *reason)
dvb_mux_fec2str(p->u.qpsk.fec_inner), dvb_mux_delsys2str(dmc.dmc_fe_delsys), dvb_mux_fec2str(p->u.qpsk.fec_inner), dvb_mux_delsys2str(dmc.dmc_fe_delsys),
dvb_mux_qam2str(dmc.dmc_fe_modulation), reason); dvb_mux_qam2str(dmc.dmc_fe_modulation), reason);
r = dvb_fe_tune_s2(tdmi, &dmc); r = dvb_fe_tune_s2(tda, &dmc);
} else } else
#endif #endif
{ {
tvhlog(LOG_DEBUG, "dvb", "\"%s\" tuning to \"%s\" (%s)", tda->tda_rootpath, buf, reason); tvhlog(LOG_DEBUG, "dvb", "\"%s\" tuning to \"%s\" (%s) fd:%d", tda->tda_rootpath, buf, reason, tda->tda_fe_fd);
r = ioctl(tda->tda_fe_fd, FE_SET_FRONTEND, p); r = ioctl(tda->tda_fe_fd, FE_SET_FRONTEND, p);
} }
@ -499,24 +599,26 @@ dvb_fe_tune(dvb_mux_t *dm, const char *reason)
" -- Front configuration failed -- %s, frequency: %u", " -- Front configuration failed -- %s, frequency: %u",
tda->tda_rootpath, buf, strerror(errno), p->frequency); tda->tda_rootpath, buf, strerror(errno), p->frequency);
/* Remove from initial scan set */
if(dm->dm_table_initial) {
dm->dm_table_initial = 0;
dn->dn_initial_num_mux--;
}
/* Mark as bad */ /* Mark as bad */
tdmi->tdmi_tune_failed = 1; tdmi->tdmi_tune_failed = 1;
return SM_CODE_TUNING_FAILED; goto retry;
} }
tda->tda_current_tdmi = tdmi; tda->tda_current_tdmi = tdmi;
dm->dm_current_tdmi = tdmi;
if(dm->dm_scan_status == DM_SCAN_PENDING) {
TAILQ_REMOVE(&dn->dn_initial_scan_pending_queue, dm, dm_scan_link);
dm->dm_scan_status = DM_SCAN_CURRENT;
TAILQ_INSERT_TAIL(&dn->dn_initial_scan_current_queue, dm, dm_scan_link);
gtimer_arm(&dm->dm_initial_scan_timeout, dvb_mux_initial_scan_timeout, dm, 10);
}
gtimer_arm(&tda->tda_fe_monitor_timer, dvb_fe_monitor, tda, 1); gtimer_arm(&tda->tda_fe_monitor_timer, dvb_fe_monitor, tda, 1);
dvb_table_add_default(dm);
dvb_table_add_default(tdmi->tdmi_mux); epggrab_mux_start(dm);
epggrab_mux_start(tdmi->tdmi_mux);
dvb_adapter_notify(tda); dvb_adapter_notify(tda);
return 0; return 0;

View file

@ -59,7 +59,7 @@ open_service(th_dvb_adapter_t *tda, service_t *s)
st->es_demuxer_fd = -1; st->es_demuxer_fd = -1;
tvhlog(LOG_ERR, "dvb", tvhlog(LOG_ERR, "dvb",
"\"%s\" unable to open demuxer \"%s\" for pid %d -- %s", "\"%s\" unable to open demuxer \"%s\" for pid %d -- %s",
s->s_uuid, tda->tda_demux_path, s->s_nicename, tda->tda_demux_path,
st->es_pid, strerror(errno)); st->es_pid, strerror(errno));
continue; continue;
} }
@ -74,7 +74,7 @@ open_service(th_dvb_adapter_t *tda, service_t *s)
if(ioctl(fd, DMX_SET_PES_FILTER, &dmx_param)) { if(ioctl(fd, DMX_SET_PES_FILTER, &dmx_param)) {
tvhlog(LOG_ERR, "dvb", tvhlog(LOG_ERR, "dvb",
"\"%s\" unable to configure demuxer \"%s\" for pid %d -- %s", "\"%s\" unable to configure demuxer \"%s\" for pid %d -- %s",
s->s_uuid, tda->tda_demux_path, s->s_nicename, tda->tda_demux_path,
st->es_pid, strerror(errno)); st->es_pid, strerror(errno));
close(fd); close(fd);
fd = -1; fd = -1;

View file

@ -46,8 +46,6 @@
#include "subscriptions.h" #include "subscriptions.h"
#include "epggrab.h" #include "epggrab.h"
struct th_dvb_mux_instance_tree dvb_muxes;
static struct strtab muxfestatustab[] = { static struct strtab muxfestatustab[] = {
{ "Unknown", TDMI_FE_UNKNOWN }, { "Unknown", TDMI_FE_UNKNOWN },
{ "No signal", TDMI_FE_NO_SIGNAL }, { "No signal", TDMI_FE_NO_SIGNAL },
@ -58,18 +56,51 @@ static struct strtab muxfestatustab[] = {
{ "OK", TDMI_FE_OK }, { "OK", TDMI_FE_OK },
}; };
static htsmsg_t *dvb_mux_serialize(struct idnode *self, int full);
static idnode_t **dvb_mux_get_childs(struct idnode *self);
static const idclass_t dvb_mux_class = {
.ic_class = "dvbmux",
.ic_serialize = dvb_mux_serialize,
.ic_get_childs = dvb_mux_get_childs,
};
/** /**
* *
*/ */
static void static void
mux_link_initial(dvb_network_t *dn, dvb_mux_t *dm) mux_link_initial(dvb_network_t *dn, dvb_mux_t *dm)
{ {
dm->dm_scan_queue = &dn->dn_initial_scan_queue; assert(dm->dm_scan_status == DM_SCAN_DONE);
TAILQ_INSERT_TAIL(dm->dm_scan_queue, dm, dm_scan_link);
gtimer_arm(&dn->dn_mux_scanner_timer, dvb_network_mux_scanner, dn, 0); dm->dm_scan_status = DM_SCAN_PENDING;
TAILQ_INSERT_TAIL(&dn->dn_initial_scan_pending_queue, dm, dm_scan_link);
dn->dn_initial_scan_num_mux++;
dvb_network_schedule_initial_scan(dn);
} }
/**
*
*/
void
dvb_mux_initial_scan_done(dvb_mux_t *dm)
{
dvb_network_t *dn = dm->dm_dn;
gtimer_disarm(&dm->dm_initial_scan_timeout);
assert(dm->dm_scan_status == DM_SCAN_CURRENT);
dn->dn_initial_scan_num_mux--;
dm->dm_scan_status = DM_SCAN_DONE;
TAILQ_REMOVE(&dn->dn_initial_scan_current_queue, dm, dm_scan_link);
dvb_network_schedule_initial_scan(dn);
dvb_mux_save(dm); // Save to dm_scan_status is persisted
}
/** /**
* Return a readable status text for the given mux * Return a readable status text for the given mux
*/ */
@ -136,7 +167,7 @@ dcm_compare_conf(int adapter_type,
dvb_mux_t * dvb_mux_t *
dvb_mux_create(dvb_network_t *dn, const struct dvb_mux_conf *dmc, dvb_mux_create(dvb_network_t *dn, const struct dvb_mux_conf *dmc,
uint16_t onid, uint16_t tsid, const char *network, uint16_t onid, uint16_t tsid, const char *network,
const char *source, int enabled, int initialscan, const char *source, int enabled, int needscan,
const char *uuid) const char *uuid)
{ {
dvb_mux_t *dm; dvb_mux_t *dm;
@ -186,16 +217,6 @@ dvb_mux_create(dvb_network_t *dn, const struct dvb_mux_conf *dmc,
save = 1; save = 1;
} }
#if 0 // XXX(dvbreorg)
/* HACK - load old transports and remove old mux config */
if(identifier) {
save = 1;
dvb_service_load(tdmi, identifier);
hts_settings_remove("dvbmuxes/%s/%s",
tda->tda_identifier, identifier);
}
#endif
if(save) { if(save) {
char buf[128]; char buf[128];
dvb_mux_save(dm); dvb_mux_save(dm);
@ -220,6 +241,8 @@ dvb_mux_create(dvb_network_t *dn, const struct dvb_mux_conf *dmc,
dm->dm_dn = dn; dm->dm_dn = dn;
LIST_INSERT_HEAD(&dn->dn_muxes, dm, dm_network_link); LIST_INSERT_HEAD(&dn->dn_muxes, dm, dm_network_link);
idnode_insert(&dm->dm_id, uuid, &dvb_mux_class);
char identifier[128]; char identifier[128];
snprintf(identifier, sizeof(identifier), snprintf(identifier, sizeof(identifier),
"%d%s", dmc->dmc_fe_params.frequency, "%d%s", dmc->dmc_fe_params.frequency,
@ -231,8 +254,6 @@ dvb_mux_create(dvb_network_t *dn, const struct dvb_mux_conf *dmc,
memcpy(&dm->dm_conf, dmc, sizeof(struct dvb_mux_conf)); memcpy(&dm->dm_conf, dmc, sizeof(struct dvb_mux_conf));
dm->dm_table_initial = initialscan;
if(source != NULL) { if(source != NULL) {
char buf[128]; char buf[128];
dvb_mux_nicename(buf, sizeof(buf), dm); dvb_mux_nicename(buf, sizeof(buf), dm);
@ -243,8 +264,8 @@ dvb_mux_create(dvb_network_t *dn, const struct dvb_mux_conf *dmc,
dvb_service_load(dm); dvb_service_load(dm);
if(enabled && dm->dm_table_initial) { if(enabled && needscan) {
dn->dn_initial_num_mux++; dn->dn_initial_scan_num_mux++;
mux_link_initial(dn, dm); mux_link_initial(dn, dm);
} }
@ -271,6 +292,7 @@ void
dvb_mux_destroy(dvb_mux_t *dm) dvb_mux_destroy(dvb_mux_t *dm)
{ {
th_dvb_mux_instance_t *tdmi; th_dvb_mux_instance_t *tdmi;
dvb_network_t *dn = dm->dm_dn;
lock_assert(&global_lock); lock_assert(&global_lock);
@ -279,16 +301,25 @@ dvb_mux_destroy(dvb_mux_t *dm)
while((tdmi = LIST_FIRST(&dm->dm_tdmis)) != NULL) while((tdmi = LIST_FIRST(&dm->dm_tdmis)) != NULL)
dvb_tdmi_destroy(tdmi); dvb_tdmi_destroy(tdmi);
if(dm->dm_scan_queue != NULL) switch(dm->dm_scan_status) {
TAILQ_REMOVE(dm->dm_scan_queue, dm, dm_scan_link); case DM_SCAN_DONE:
break;
case DM_SCAN_CURRENT:
TAILQ_REMOVE(&dn->dn_initial_scan_current_queue, dm, dm_scan_link);
gtimer_disarm(&dm->dm_initial_scan_timeout);
if(0) // Sorry but i can't resist these whenever i get an oppertunity // andoma
case DM_SCAN_PENDING:
TAILQ_REMOVE(&dn->dn_initial_scan_pending_queue, dm, dm_scan_link);
dn->dn_initial_scan_num_mux--;
dvb_network_schedule_initial_scan(dn);
break;
}
if(dm->dm_table_initial)
dm->dm_dn->dn_initial_num_mux--;
epggrab_mux_delete(dm); epggrab_mux_delete(dm);
free(dm->dm_local_identifier); free(dm->dm_local_identifier);
free(dm->dm_uuid); idnode_unlink(&dm->dm_id);
free(dm); free(dm);
} }
@ -492,7 +523,7 @@ dvb_mux_save(dvb_mux_t *dm)
htsmsg_add_u32(m, "frequency", f->frequency); htsmsg_add_u32(m, "frequency", f->frequency);
htsmsg_add_u32(m, "initialscan", dm->dm_table_initial); htsmsg_add_u32(m, "needscan", dm->dm_scan_status != DM_SCAN_DONE);
if(dm->dm_default_authority) if(dm->dm_default_authority)
htsmsg_add_str(m, "default_authority", dm->dm_default_authority); htsmsg_add_str(m, "default_authority", dm->dm_default_authority);
@ -559,7 +590,7 @@ dvb_mux_save(dvb_mux_t *dm)
} }
hts_settings_save(m, "dvb/networks/%s/muxes/%s/config", hts_settings_save(m, "dvb/networks/%s/muxes/%s/config",
dm->dm_dn->dn_uuid, idnode_uuid_as_str(&dm->dm_dn->dn_id),
dm->dm_local_identifier); dm->dm_local_identifier);
htsmsg_destroy(m); htsmsg_destroy(m);
@ -575,7 +606,7 @@ dvb_mux_create_by_msg(dvb_network_t *dn, htsmsg_t *m, const char *fname)
struct dvb_mux_conf dmc; struct dvb_mux_conf dmc;
const char *s; const char *s;
int r; int r;
unsigned int onid, tsid, enabled, initscan; unsigned int onid, tsid, enabled;
memset(&dmc, 0, sizeof(dmc)); memset(&dmc, 0, sizeof(dmc));
dmc.dmc_fe_params.inversion = INVERSION_AUTO; dmc.dmc_fe_params.inversion = INVERSION_AUTO;
@ -694,10 +725,9 @@ dvb_mux_create_by_msg(dvb_network_t *dn, htsmsg_t *m, const char *fname)
if(htsmsg_get_u32(m, "enabled", &enabled)) if(htsmsg_get_u32(m, "enabled", &enabled))
enabled = 1; enabled = 1;
initscan = htsmsg_get_u32_or_default(m, "initialscan", 0);
dm = dvb_mux_create(dn, &dmc, dm = dvb_mux_create(dn, &dmc,
onid, tsid, htsmsg_get_str(m, "network"), NULL, enabled, onid, tsid, htsmsg_get_str(m, "network"), NULL, enabled,
initscan, htsmsg_get_u32_or_default(m, "needscan", 1),
htsmsg_get_str(m, "uuid")); htsmsg_get_str(m, "uuid"));
if(dm != NULL) { if(dm != NULL) {
@ -718,13 +748,16 @@ dvb_mux_load(dvb_network_t *dn)
htsmsg_field_t *f; htsmsg_field_t *f;
if((l = hts_settings_load_r(1, "dvb/networks/%s/muxes", if((l = hts_settings_load_r(1, "dvb/networks/%s/muxes",
dn->dn_uuid)) == NULL) idnode_uuid_as_str(&dn->dn_id))) == NULL)
return; return;
HTSMSG_FOREACH(f, l) { HTSMSG_FOREACH(f, l) {
if((c = htsmsg_get_map_by_field(f)) == NULL) if((c = htsmsg_get_map_by_field(f)) == NULL)
continue; continue;
if((c = htsmsg_get_map(c, "config")) == NULL)
continue;
dvb_mux_create_by_msg(dn, c, f->hmf_name); dvb_mux_create_by_msg(dn, c, f->hmf_name);
} }
htsmsg_destroy(l); htsmsg_destroy(l);
@ -765,7 +798,7 @@ dvb_mux_set_tsid(dvb_mux_t *dm, uint16_t tsid)
dvb_mux_save(dm); dvb_mux_save(dm);
m = htsmsg_create_map(); m = htsmsg_create_map();
htsmsg_add_str(m, "uuid", dm->dm_uuid); htsmsg_add_str(m, "uuid", idnode_uuid_as_str(&dm->dm_id));
htsmsg_add_u32(m, "muxid", dm->dm_transport_stream_id); htsmsg_add_u32(m, "muxid", dm->dm_transport_stream_id);
notify_by_msg("dvbMux", m); notify_by_msg("dvbMux", m);
} }
@ -783,7 +816,7 @@ dvb_mux_set_onid(dvb_mux_t *dm, uint16_t onid)
dvb_mux_save(dm); dvb_mux_save(dm);
m = htsmsg_create_map(); m = htsmsg_create_map();
htsmsg_add_str(m, "uuid", dm->dm_uuid); htsmsg_add_str(m, "uuid", idnode_uuid_as_str(&dm->dm_id));
htsmsg_add_u32(m, "onid", dm->dm_network_id); htsmsg_add_u32(m, "onid", dm->dm_network_id);
notify_by_msg("dvbMux", m); notify_by_msg("dvbMux", m);
} }
@ -917,7 +950,7 @@ dvb_mux_build_msg(dvb_mux_t *dm)
htsmsg_t *m = htsmsg_create_map(); htsmsg_t *m = htsmsg_create_map();
char buf[100]; char buf[100];
htsmsg_add_str(m, "uuid", dm->dm_uuid); htsmsg_add_str(m, "uuid", idnode_uuid_as_str(&dm->dm_id));
htsmsg_add_u32(m, "enabled", dm->dm_enabled); htsmsg_add_u32(m, "enabled", dm->dm_enabled);
htsmsg_add_str(m, "network", dm->dm_network_name ?: ""); htsmsg_add_str(m, "network", dm->dm_network_name ?: "");
@ -1200,8 +1233,8 @@ dvb_subscription_create_from_tdmi(th_dvb_mux_instance_t *tdmi,
s->ths_tdmi = tdmi; s->ths_tdmi = tdmi;
LIST_INSERT_HEAD(&tdmi->tdmi_subscriptions, s, ths_tdmi_link); LIST_INSERT_HEAD(&tdmi->tdmi_subscriptions, s, ths_tdmi_link);
dvb_fe_tune(tdmi->tdmi_mux, "Full mux subscription"); dvb_fe_tune(tdmi->tdmi_mux, "Full mux subscription", 99999);
abort();
pthread_mutex_lock(&tda->tda_delivery_mutex); pthread_mutex_lock(&tda->tda_delivery_mutex);
streaming_target_connect(&tda->tda_streaming_pad, &s->ths_input); streaming_target_connect(&tda->tda_streaming_pad, &s->ths_input);
pthread_mutex_unlock(&tda->tda_delivery_mutex); pthread_mutex_unlock(&tda->tda_delivery_mutex);
@ -1209,3 +1242,56 @@ dvb_subscription_create_from_tdmi(th_dvb_mux_instance_t *tdmi,
notify_reload("subscriptions"); notify_reload("subscriptions");
return s; return s;
} }
/**
*
*/
static htsmsg_t *
dvb_mux_serialize(struct idnode *self, int full)
{
dvb_mux_t *dm = (dvb_mux_t *)self;
htsmsg_t *m = htsmsg_create_map();
htsmsg_add_str(m, "id", idnode_uuid_as_str(&dm->dm_id));
char buf[256];
dvb_mux_nicename(buf, sizeof(buf), dm);
htsmsg_add_str(m, "text", buf);
return m;
}
/**
*
*/
static int
svcsortcmp(const void *A, const void *B)
{
const service_t *a = *(service_t **)A;
const service_t *b = *(service_t **)B;
return (int)a->s_dvb_service_id - (int)b->s_dvb_service_id;
}
/**
*
*/
static idnode_t **
dvb_mux_get_childs(struct idnode *self)
{
dvb_mux_t *dm = (dvb_mux_t *)self;
service_t *s;
int cnt = 1;
LIST_FOREACH(s, &dm->dm_services, s_group_link)
cnt++;
idnode_t **v = malloc(sizeof(idnode_t *) * cnt);
cnt = 0;
LIST_FOREACH(s, &dm->dm_services, s_group_link)
v[cnt++] = (idnode_t *)s;
qsort(v, cnt, sizeof(idnode_t *), svcsortcmp);
v[cnt] = NULL;
return v;
}

View file

@ -16,36 +16,129 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <assert.h>
#include "tvheadend.h" #include "tvheadend.h"
#include "packet.h" #include "packet.h"
#include "dvb.h" #include "dvb.h"
#include "epggrab.h" #include "epggrab.h"
#include "settings.h"
#include "dvb_support.h"
struct dvb_network_list dvb_networks; struct dvb_network_list dvb_networks;
static htsmsg_t *dvb_network_serialize(struct idnode *self, int full);
static idnode_t **dvb_network_get_childs(struct idnode *self);
static const idclass_t dvb_network_class = {
.ic_class = "dvbnetwork",
.ic_serialize = dvb_network_serialize,
.ic_get_childs = dvb_network_get_childs,
};
/** /**
* *
*/ */
dvb_network_t * dvb_network_t *
dvb_network_create(int fe_type) dvb_network_create(int fe_type, const char *uuid)
{ {
printf("Creating network %s\n", uuid);
dvb_network_t *dn = calloc(1, sizeof(dvb_network_t)); dvb_network_t *dn = calloc(1, sizeof(dvb_network_t));
if(idnode_insert(&dn->dn_id, uuid, &dvb_network_class)) {
free(dn);
return NULL;
}
printf("Added network %s\n", idnode_uuid_as_str(&dn->dn_id));
dn->dn_fe_type = fe_type; dn->dn_fe_type = fe_type;
TAILQ_INIT(&dn->dn_initial_scan_queue); TAILQ_INIT(&dn->dn_initial_scan_pending_queue);
gtimer_arm(&dn->dn_mux_scanner_timer, dvb_network_mux_scanner, dn, 1); TAILQ_INIT(&dn->dn_initial_scan_current_queue);
dn->dn_autodiscovery = fe_type != FE_QPSK; dn->dn_autodiscovery = fe_type != FE_QPSK;
LIST_INSERT_HEAD(&dvb_networks, dn, dn_global_link); LIST_INSERT_HEAD(&dvb_networks, dn, dn_global_link);
return dn; return dn;
} }
#if 0
htsmsg_get_u32(c, "autodiscovery", &tda->tda_autodiscovery);
htsmsg_get_u32(c, "nitoid", &tda->tda_nitoid);
htsmsg_get_u32(c, "disable_pmt_monitor", &tda->tda_disable_pmt_monitor);
#endif
#if 0
/**
*
*/
static htsmsg_t *
dvb_network_serialize(struct idnode *self, int full)
{
dvb_network_t *dn = (dvb_network_t *)self;
htsmsg_t *m = htsmsg_create_map();
htsmsg_add_str(m, "id", idnode_uuid_as_str(&dn->dn_id));
htsmsg_add_str(m, "text", idnode_uuid_as_str(&dn->dn_id));
return m;
}
/**
*
*/
static int
muxsortcmp(const void *A, const void *B)
{
const dvb_mux_t *a = *(dvb_mux_t **)A;
const dvb_mux_t *b = *(dvb_mux_t **)B;
if(a->dm_conf.dmc_fe_params.frequency < b->dm_conf.dmc_fe_params.frequency)
return -1;
if(a->dm_conf.dmc_fe_params.frequency > b->dm_conf.dmc_fe_params.frequency)
return 1;
return a->dm_conf.dmc_polarisation - b->dm_conf.dmc_polarisation;
}
/**
*
*/
static idnode_t **
dvb_network_get_childs(struct idnode *self)
{
dvb_network_t *dn = (dvb_network_t *)self;
dvb_mux_t *dm;
int cnt = 1;
LIST_FOREACH(dm, &dn->dn_muxes, dm_network_link)
cnt++;
idnode_t **v = malloc(sizeof(idnode_t *) * cnt);
cnt = 0;
LIST_FOREACH(dm, &dn->dn_muxes, dm_network_link)
v[cnt++] = (idnode_t *)dm;
qsort(v, cnt, sizeof(idnode_t *), muxsortcmp);
v[cnt] = NULL;
return v;
}
/**
*
*/
static void
dvb_network_load(htsmsg_t *m, const char *uuid)
{
uint32_t fetype;
if(htsmsg_get_u32(m, "fetype", &fetype))
return;
dvb_network_t *dn = dvb_network_create(fetype, uuid);
if(dn == NULL)
return;
htsmsg_get_u32(m, "autodiscovery", &dn->dn_autodiscovery);
htsmsg_get_u32(m, "nitoid", &dn->dn_nitoid);
htsmsg_get_u32(m, "disable_pmt_monitor", &dn->dn_disable_pmt_monitor);
dvb_mux_load(dn);
dvb_network_schedule_initial_scan(dn);
}
#if 1
/** /**
* *
*/ */
@ -56,13 +149,18 @@ dvb_network_save(dvb_network_t *dn)
lock_assert(&global_lock); lock_assert(&global_lock);
htsmsg_add_u32(m, "fetype", dn->dn_fe_type);
htsmsg_add_u32(m, "autodiscovery", dn->dn_autodiscovery); htsmsg_add_u32(m, "autodiscovery", dn->dn_autodiscovery);
htsmsg_add_u32(m, "nitoid", dn->dn_nitoid); htsmsg_add_u32(m, "nitoid", dn->dn_nitoid);
htsmsg_add_u32(m, "disable_pmt_monitor", dn->dn_disable_pmt_monitor); htsmsg_add_u32(m, "disable_pmt_monitor", dn->dn_disable_pmt_monitor);
abort();
hts_settings_save(m, "dvb/networks/%s/config",
idnode_uuid_as_str(&dn->dn_id));
htsmsg_destroy(m);
} }
#endif #endif
#if 0 #if 0
/** /**
* *
@ -125,65 +223,82 @@ dvb_network_set_disable_pmt_monitor(th_dvb_network_t *dn, int on)
#endif #endif
/** /**
* *
*/ */
void static void
dvb_network_mux_scanner(void *aux) dvb_network_initial_scan(void *aux)
{ {
dvb_network_t *dn = aux; dvb_network_t *dn = aux;
dvb_mux_t *dm; dvb_mux_t *dm;
// default period while((dm = TAILQ_FIRST(&dn->dn_initial_scan_pending_queue)) != NULL) {
gtimer_arm(&dn->dn_mux_scanner_timer, dvb_network_mux_scanner, dn, 20); assert(dm->dm_scan_status == DM_SCAN_PENDING);
if(dvb_fe_tune(dm, "initial scan", 1))
#if 0 break;
/* No muxes */ assert(dm->dm_scan_status == DM_SCAN_CURRENT);
if(LIST_FIRST(&dn->dn_mux_instances) == NULL) {
dvb_adapter_poweroff(tda);
return;
} }
#endif gtimer_arm(&dn->dn_initial_scan_timer, dvb_network_initial_scan, dn, 10);
#if 0 }
/* Someone is actively using */
if(service_compute_weight(&tda->tda_transports) > 0) /**
return; *
#endif */
#if 0 void
if(tda->tda_mux_current != NULL && dvb_network_schedule_initial_scan(dvb_network_t *dn)
LIST_FIRST(&tda->tda_mux_current->tdmi_subscriptions) != NULL) {
return; // Someone is doing full mux dump gtimer_arm(&dn->dn_initial_scan_timer, dvb_network_initial_scan, dn, 0);
#endif }
/* Check if we have muxes pending for quickscan, if so, choose them */ /**
if((dm = TAILQ_FIRST(&dn->dn_initial_scan_queue)) != NULL) { *
dvb_fe_tune(dm, "Initial autoscan"); */
return; void
} dvb_network_init(void)
{
/* Check EPG */ htsmsg_t *l, *c;
if (dn->dn_mux_epg) { htsmsg_field_t *f;
// timeout anything not complete
epggrab_mux_stop(dn->dn_mux_epg, 1); if(0) {
dn->dn_mux_epg = NULL; // skip this time dvb_network_save(dvb_network_create(FE_QAM, NULL));
} else { exit(0);
dn->dn_mux_epg = epggrab_mux_next(dn); }
}
if((l = hts_settings_load_r(1, "dvb/networks")) == NULL)
/* EPG */ return;
if (dn->dn_mux_epg) {
int period = epggrab_mux_period(dn->dn_mux_epg);
if (period > 20) htsmsg_print(l);
gtimer_arm(&dn->dn_mux_scanner_timer,
dvb_network_mux_scanner, dn, period); HTSMSG_FOREACH(f, l) {
dvb_fe_tune(dn->dn_mux_epg, "EPG scan"); if((c = htsmsg_get_map_by_field(f)) == NULL)
return; continue;
} if((c = htsmsg_get_map(c, "config")) == NULL)
continue;
#if 0
/* Ensure we stop current mux and power off (if required) */ dvb_network_load(c, f->hmf_name);
if (tda->tda_mux_current) }
dvb_fe_stop(tda->tda_mux_current, 0); htsmsg_destroy(l);
#endif }
/**
*
*/
idnode_t **
dvb_network_root(void)
{
dvb_network_t *dn;
int cnt = 1;
LIST_FOREACH(dn, &dvb_networks, dn_global_link)
cnt++;
idnode_t **v = malloc(sizeof(idnode_t *) * cnt);
cnt = 0;
LIST_FOREACH(dn, &dvb_networks, dn_global_link)
v[cnt++] = &dn->dn_id;
v[cnt] = NULL;
return v;
} }

View file

@ -44,15 +44,7 @@
#include "dvb_support.h" #include "dvb_support.h"
#include "notify.h" #include "notify.h"
static htsmsg_t *dvb_service_serialize(service_t *s, int full);
/**
*
*/
/** /**
@ -110,7 +102,7 @@ dvb_service_start(service_t *t, unsigned int weight, int force_start)
return r; return r;
#endif #endif
return SM_CODE_NO_HW_ATTACHED; return SM_CODE_NO_FREE_ADAPTER;
} }
@ -193,7 +185,7 @@ dvb_service_save(service_t *t)
dvb_mux_t *dm = t->s_dvb_mux; dvb_mux_t *dm = t->s_dvb_mux;
hts_settings_save(m, "dvb/networks/%s/muxes/%s/services/%04x", hts_settings_save(m, "dvb/networks/%s/muxes/%s/services/%04x",
dm->dm_dn->dn_uuid, idnode_uuid_as_str(&dm->dm_dn->dn_id),
dm->dm_local_identifier, dm->dm_local_identifier,
t->s_dvb_service_id); t->s_dvb_service_id);
@ -217,7 +209,8 @@ dvb_service_load(dvb_mux_t *dm)
lock_assert(&global_lock); lock_assert(&global_lock);
l = hts_settings_load("dvb/networks/%s/muxes/%s/services", l = hts_settings_load("dvb/networks/%s/muxes/%s/services",
dm->dm_dn->dn_uuid, dm->dm_local_identifier); idnode_uuid_as_str(&dm->dm_dn->dn_id),
dm->dm_local_identifier);
if(l == NULL) if(l == NULL)
return; return;
@ -398,6 +391,7 @@ dvb_service_find2(dvb_mux_t *dm, uint16_t sid, int pmt_pid,
t->s_config_save = dvb_service_save; t->s_config_save = dvb_service_save;
t->s_setsourceinfo = dvb_service_setsourceinfo; t->s_setsourceinfo = dvb_service_setsourceinfo;
t->s_grace_period = dvb_grace_period; t->s_grace_period = dvb_grace_period;
t->s_serialize = dvb_service_serialize;
t->s_dvb_mux = dm; t->s_dvb_mux = dm;
LIST_INSERT_HEAD(&dm->dm_services, t, s_group_link); LIST_INSERT_HEAD(&dm->dm_services, t, s_group_link);
@ -412,38 +406,44 @@ dvb_service_find2(dvb_mux_t *dm, uint16_t sid, int pmt_pid,
/** /**
* *
*/ */
htsmsg_t * static htsmsg_t *
dvb_service_build_msg(service_t *t) dvb_service_serialize(service_t *s, int full)
{ {
dvb_mux_t *dm = t->s_dvb_mux; dvb_mux_t *dm = s->s_dvb_mux;
htsmsg_t *m = htsmsg_create_map(); htsmsg_t *m = htsmsg_create_map();
char buf[100]; char buf[100];
htsmsg_add_str(m, "uuid", t->s_uuid);
htsmsg_add_u32(m, "enabled", t->s_enabled);
htsmsg_add_u32(m, "channel", t->s_channel_number);
htsmsg_add_u32(m, "sid", t->s_dvb_service_id); htsmsg_add_str(m, "id", idnode_uuid_as_str(&s->s_id));
htsmsg_add_u32(m, "pmt", t->s_pmt_pid);
htsmsg_add_u32(m, "pcr", t->s_pcr_pid);
htsmsg_add_str(m, "type", service_servicetype_txt(t));
htsmsg_add_str(m, "svcname", t->s_svcname ?: ""); snprintf(buf, sizeof(buf), "%s (0x%04x)",
htsmsg_add_str(m, "provider", t->s_provider ?: ""); s->s_svcname ?: "<noname>", s->s_dvb_service_id);
htsmsg_add_str(m, "text", buf);
htsmsg_add_u32(m, "enabled", s->s_enabled);
htsmsg_add_u32(m, "channel", s->s_channel_number);
htsmsg_add_u32(m, "sid", s->s_dvb_service_id);
htsmsg_add_u32(m, "pmt", s->s_pmt_pid);
htsmsg_add_u32(m, "pcr", s->s_pcr_pid);
htsmsg_add_str(m, "type", service_servicetype_txt(s));
htsmsg_add_str(m, "svcname", s->s_svcname ?: "");
htsmsg_add_str(m, "provider", s->s_provider ?: "");
htsmsg_add_str(m, "network", dm->dm_network_name ?: ""); htsmsg_add_str(m, "network", dm->dm_network_name ?: "");
dvb_mux_nicefreq(buf, sizeof(buf), dm); dvb_mux_nicefreq(buf, sizeof(buf), dm);
htsmsg_add_str(m, "mux", buf); htsmsg_add_str(m, "mux", buf);
if(t->s_ch != NULL) if(s->s_ch != NULL)
htsmsg_add_str(m, "channelname", t->s_ch->ch_name); htsmsg_add_str(m, "channelname", s->s_ch->ch_name);
if(t->s_dvb_charset != NULL) if(s->s_dvb_charset != NULL)
htsmsg_add_str(m, "dvb_charset", t->s_dvb_charset); htsmsg_add_str(m, "dvb_charset", s->s_dvb_charset);
htsmsg_add_u32(m, "dvb_eit_enable", t->s_dvb_eit_enable); htsmsg_add_u32(m, "dvb_eit_enable", s->s_dvb_eit_enable);
return m; return m;
} }

View file

@ -52,25 +52,21 @@ dvb_table_fastswitch(th_dvb_mux_instance_t *tdmi)
th_dvb_table_t *tdt; th_dvb_table_t *tdt;
th_dvb_adapter_t *tda = tdmi->tdmi_adapter; th_dvb_adapter_t *tda = tdmi->tdmi_adapter;
dvb_mux_t *dm = tdmi->tdmi_mux; dvb_mux_t *dm = tdmi->tdmi_mux;
dvb_network_t *dn = dm->dm_dn;
char buf[100]; char buf[100];
if(!dm->dm_table_initial) if(dm->dm_scan_status == DM_SCAN_DONE)
return; return;
LIST_FOREACH(tdt, &dm->dm_tables, tdt_link) LIST_FOREACH(tdt, &dm->dm_tables, tdt_link)
if((tdt->tdt_flags & TDT_QUICKREQ) && tdt->tdt_count == 0) if((tdt->tdt_flags & TDT_QUICKREQ) && tdt->tdt_count == 0)
return; return;
dm->dm_table_initial = 0;
dn->dn_initial_num_mux--;
dvb_mux_save(dm); dvb_mux_save(dm);
dvb_mux_nicename(buf, sizeof(buf), dm); dvb_mux_nicename(buf, sizeof(buf), dm);
tvhlog(LOG_DEBUG, "dvb", "\"%s\" initial scan completed for \"%s\"", tvhlog(LOG_DEBUG, "dvb", "\"%s\" initial scan completed for \"%s\"",
tda->tda_rootpath, buf); tda->tda_rootpath, buf);
dvb_network_mux_scanner(dn); dvb_mux_initial_scan_done(dm);
} }

View file

@ -369,13 +369,14 @@ void epggrab_ota_complete ( epggrab_ota_mux_t *ota )
TAILQ_FOREACH(ota, &dm->dm_epg_grab, dm_link) { TAILQ_FOREACH(ota, &dm->dm_epg_grab, dm_link) {
if (ota->is_reg && ota->state == EPGGRAB_OTA_MUX_RUNNING) break; if (ota->is_reg && ota->state == EPGGRAB_OTA_MUX_RUNNING) break;
} }
#if 0 // XXX(dvbreorg)
/* All complete (bring timer forward) */ /* All complete (bring timer forward) */
if (!ota) { if (!ota) {
dvb_network_t *dn = dm->dm_dn; dvb_network_t *dn = dm->dm_dn;
gtimer_arm(&dn->dn_mux_scanner_timer, gtimer_arm(&dn->dn_mux_scanner_timer,
dvb_network_mux_scanner, dn, 20); dvb_network_mux_scanner, dn, 20);
} }
#endif
} }
} }

View file

@ -305,7 +305,7 @@ int fb_scandir ( const char *path, fb_dirent ***list )
for (i = 0; i < ret; i++) { for (i = 0; i < ret; i++) {
(*list)[i] = calloc(1, sizeof(fb_dirent)); (*list)[i] = calloc(1, sizeof(fb_dirent));
strcpy((*list)[i]->name, de[i]->d_name); strcpy((*list)[i]->name, de[i]->d_name);
(*list)[i]->type = FB_DIRECT; (*list)[i]->type = de[i]->d_type == DT_DIR ? FB_DIR : FB_FILE;
free(de[i]); free(de[i]);
} }
free(de); free(de);

158
src/idnode.c Normal file
View file

@ -0,0 +1,158 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <unistd.h>
#include "idnode.h"
static int randfd = 0;
RB_HEAD(idnode_tree, idnode);
static struct idnode_tree idnodes;
/**
*
*/
static int
hexnibble(char c)
{
switch(c) {
case '0' ... '9': return c - '0';
case 'a' ... 'f': return c - 'a' + 10;
case 'A' ... 'F': return c - 'A' + 10;
default:
return -1;
}
}
/**
*
*/
static int
hex2bin(uint8_t *buf, size_t buflen, const char *str)
{
int hi, lo;
while(*str) {
if(buflen == 0)
return -1;
if((hi = hexnibble(*str++)) == -1)
return -1;
if((lo = hexnibble(*str++)) == -1)
return -1;
*buf++ = hi << 4 | lo;
buflen--;
}
return 0;
}
/**
*
*/
static void
bin2hex(char *dst, size_t dstlen, const uint8_t *src, size_t srclen)
{
while(dstlen > 2 && srclen > 0) {
*dst++ = "0123456789abcdef"[*src >> 4];
*dst++ = "0123456789abcdef"[*src & 0xf];
src++;
srclen--;
dstlen -= 2;
}
*dst = 0;
}
/**
*
*/
void
idnode_init(void)
{
randfd = open("/dev/urandom", O_RDONLY);
if(randfd == -1)
exit(1);
}
/**
*
*/
static int
in_cmp(const idnode_t *a, const idnode_t *b)
{
return memcmp(a->in_uuid, b->in_uuid, 16);
}
/**
*
*/
int
idnode_insert(idnode_t *in, const char *uuid, const idclass_t *class)
{
idnode_t *c;
if(uuid == NULL) {
if(read(randfd, in->in_uuid, 16) != 16) {
perror("read(random for uuid)");
exit(1);
}
} else {
if(hex2bin(in->in_uuid, 16, uuid))
return -1;
}
in->in_class = class;
c = RB_INSERT_SORTED(&idnodes, in, in_link, in_cmp);
if(c != NULL) {
fprintf(stderr, "Id node collision\n");
abort();
}
return 0;
}
/**
*
*/
const char *
idnode_uuid_as_str(const idnode_t *in)
{
static char ret[16][33];
static int p;
char *b = ret[p];
bin2hex(b, 33, in->in_uuid, 16);
p = (p + 1) & 15;
return b;
}
/**
*
*/
idnode_t *
idnode_find(const char *uuid)
{
idnode_t skel, *r;
if(hex2bin(skel.in_uuid, 16, uuid))
return NULL;
r = RB_FIND(&idnodes, &skel, in_link, in_cmp);
return r;
}
/**
*
*/
void
idnode_unlink(idnode_t *in)
{
RB_REMOVE(&idnodes, in, in_link);
}

29
src/idnode.h Normal file
View file

@ -0,0 +1,29 @@
#pragma once
#include "tvheadend.h"
struct htsmsg;
struct idnode;
typedef struct idclass {
const char *ic_class;
struct htsmsg *(*ic_serialize)(struct idnode *self, int full);
struct idnode **(*ic_get_childs)(struct idnode *self);
} idclass_t;
typedef struct idnode {
uint8_t in_uuid[16];
RB_ENTRY(idnode) in_link;
const idclass_t *in_class;
} idnode_t;
void idnode_init(void);
int idnode_insert(idnode_t *in, const char *uuid, const idclass_t *class);
const char *idnode_uuid_as_str(const idnode_t *in);
idnode_t *idnode_find(const char *uuid);
void idnode_unlink(idnode_t *in);

View file

@ -227,7 +227,7 @@ iptv_service_start(service_t *t, unsigned int weight, int force_start)
fd = tvh_socket(AF_INET6, SOCK_DGRAM, 0); fd = tvh_socket(AF_INET6, SOCK_DGRAM, 0);
} }
if(fd == -1) { if(fd == -1) {
tvhlog(LOG_ERR, "IPTV", "\"%s\" cannot open socket", t->s_uuid); tvhlog(LOG_ERR, "IPTV", "\"%s\" cannot open socket", t->s_nicename);
return -1; return -1;
} }
@ -237,7 +237,7 @@ iptv_service_start(service_t *t, unsigned int weight, int force_start)
ifr.ifr_name[IFNAMSIZ - 1] = 0; ifr.ifr_name[IFNAMSIZ - 1] = 0;
if(ioctl(fd, SIOCGIFINDEX, &ifr)) { if(ioctl(fd, SIOCGIFINDEX, &ifr)) {
tvhlog(LOG_ERR, "IPTV", "\"%s\" cannot find interface %s", tvhlog(LOG_ERR, "IPTV", "\"%s\" cannot find interface %s",
t->s_uuid, t->s_iptv_iface); t->s_nicename, t->s_iptv_iface);
close(fd); close(fd);
return -1; return -1;
} }
@ -251,7 +251,7 @@ iptv_service_start(service_t *t, unsigned int weight, int force_start)
setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &m, sizeof(struct ip_mreqn)); setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &m, sizeof(struct ip_mreqn));
if(bind(fd, (struct sockaddr *)&sin, sizeof(sin)) == -1) { if(bind(fd, (struct sockaddr *)&sin, sizeof(sin)) == -1) {
tvhlog(LOG_ERR, "IPTV", "\"%s\" cannot bind %s:%d -- %s", tvhlog(LOG_ERR, "IPTV", "\"%s\" cannot bind %s:%d -- %s",
t->s_uuid, inet_ntoa(sin.sin_addr), t->s_iptv_port, t->s_nicename, inet_ntoa(sin.sin_addr), t->s_iptv_port,
strerror(errno)); strerror(errno));
close(fd); close(fd);
return -1; return -1;
@ -265,7 +265,7 @@ iptv_service_start(service_t *t, unsigned int weight, int force_start)
if(setsockopt(fd, SOL_IP, IP_ADD_MEMBERSHIP, &m, if(setsockopt(fd, SOL_IP, IP_ADD_MEMBERSHIP, &m,
sizeof(struct ip_mreqn)) == -1) { sizeof(struct ip_mreqn)) == -1) {
tvhlog(LOG_ERR, "IPTV", "\"%s\" cannot join %s -- %s", tvhlog(LOG_ERR, "IPTV", "\"%s\" cannot join %s -- %s",
t->s_uuid, inet_ntoa(m.imr_multiaddr), strerror(errno)); t->s_nicename, inet_ntoa(m.imr_multiaddr), strerror(errno));
close(fd); close(fd);
return -1; return -1;
} }
@ -279,7 +279,7 @@ iptv_service_start(service_t *t, unsigned int weight, int force_start)
if(bind(fd, (struct sockaddr *)&sin6, sizeof(sin6)) == -1) { if(bind(fd, (struct sockaddr *)&sin6, sizeof(sin6)) == -1) {
inet_ntop(AF_INET6, &sin6.sin6_addr, straddr, sizeof(straddr)); inet_ntop(AF_INET6, &sin6.sin6_addr, straddr, sizeof(straddr));
tvhlog(LOG_ERR, "IPTV", "\"%s\" cannot bind %s:%d -- %s", tvhlog(LOG_ERR, "IPTV", "\"%s\" cannot bind %s:%d -- %s",
t->s_uuid, straddr, t->s_iptv_port, t->s_nicename, straddr, t->s_iptv_port,
strerror(errno)); strerror(errno));
close(fd); close(fd);
return -1; return -1;
@ -294,7 +294,7 @@ iptv_service_start(service_t *t, unsigned int weight, int force_start)
inet_ntop(AF_INET6, m6.ipv6mr_multiaddr.s6_addr, inet_ntop(AF_INET6, m6.ipv6mr_multiaddr.s6_addr,
straddr, sizeof(straddr)); straddr, sizeof(straddr));
tvhlog(LOG_ERR, "IPTV", "\"%s\" cannot join %s -- %s", tvhlog(LOG_ERR, "IPTV", "\"%s\" cannot join %s -- %s",
t->s_uuid, straddr, strerror(errno)); t->s_nicename, straddr, strerror(errno));
close(fd); close(fd);
return -1; return -1;
} }
@ -312,7 +312,7 @@ iptv_service_start(service_t *t, unsigned int weight, int force_start)
ev.data.fd = fd; ev.data.fd = fd;
if(epoll_ctl(iptv_epollfd, EPOLL_CTL_ADD, fd, &ev) == -1) { if(epoll_ctl(iptv_epollfd, EPOLL_CTL_ADD, fd, &ev) == -1) {
tvhlog(LOG_ERR, "IPTV", "\"%s\" cannot add to epoll set -- %s", tvhlog(LOG_ERR, "IPTV", "\"%s\" cannot add to epoll set -- %s",
t->s_uuid, strerror(errno)); t->s_nicename, strerror(errno));
close(fd); close(fd);
return -1; return -1;
} }
@ -356,7 +356,7 @@ iptv_service_stop(service_t *t)
ifr.ifr_name[IFNAMSIZ - 1] = 0; ifr.ifr_name[IFNAMSIZ - 1] = 0;
if(ioctl(t->s_iptv_fd, SIOCGIFINDEX, &ifr)) { if(ioctl(t->s_iptv_fd, SIOCGIFINDEX, &ifr)) {
tvhlog(LOG_ERR, "IPTV", "\"%s\" cannot find interface %s", tvhlog(LOG_ERR, "IPTV", "\"%s\" cannot find interface %s",
t->s_uuid, t->s_iptv_iface); t->s_nicename, t->s_iptv_iface);
} }
if(t->s_iptv_group.s_addr != 0) { if(t->s_iptv_group.s_addr != 0) {
@ -371,7 +371,7 @@ iptv_service_stop(service_t *t)
if(setsockopt(t->s_iptv_fd, SOL_IP, IP_DROP_MEMBERSHIP, &m, if(setsockopt(t->s_iptv_fd, SOL_IP, IP_DROP_MEMBERSHIP, &m,
sizeof(struct ip_mreqn)) == -1) { sizeof(struct ip_mreqn)) == -1) {
tvhlog(LOG_ERR, "IPTV", "\"%s\" cannot leave %s -- %s", tvhlog(LOG_ERR, "IPTV", "\"%s\" cannot leave %s -- %s",
t->s_uuid, inet_ntoa(m.imr_multiaddr), strerror(errno)); t->s_nicename, inet_ntoa(m.imr_multiaddr), strerror(errno));
} }
} else { } else {
char straddr[INET6_ADDRSTRLEN]; char straddr[INET6_ADDRSTRLEN];
@ -388,7 +388,7 @@ iptv_service_stop(service_t *t)
straddr, sizeof(straddr)); straddr, sizeof(straddr));
tvhlog(LOG_ERR, "IPTV", "\"%s\" cannot leave %s -- %s", tvhlog(LOG_ERR, "IPTV", "\"%s\" cannot leave %s -- %s",
t->s_uuid, straddr, strerror(errno)); t->s_nicename, straddr, strerror(errno));
} }
@ -440,8 +440,9 @@ iptv_service_save(service_t *t)
psi_save_service_settings(m, t); psi_save_service_settings(m, t);
pthread_mutex_unlock(&t->s_stream_mutex); pthread_mutex_unlock(&t->s_stream_mutex);
hts_settings_save(m, "iptvservices/%s", abort(); // XXX(dvbreorg);
t->s_uuid);
// hts_settings_save(m, "iptvservices/%s", t->s_uuid);
htsmsg_destroy(m); htsmsg_destroy(m);
} }
@ -484,7 +485,8 @@ iptv_grace_period(service_t *t)
static void static void
iptv_service_dtor(service_t *t) iptv_service_dtor(service_t *t)
{ {
hts_settings_remove("iptvservices/%s", t->s_uuid); abort(); // XXX(dvbreorg);
// hts_settings_remove("iptvservices/%s", t->s_uuid);
} }
@ -504,7 +506,7 @@ iptv_service_find(const char *id, int create)
return NULL; return NULL;
LIST_FOREACH(t, &iptv_all_services, s_group_link) LIST_FOREACH(t, &iptv_all_services, s_group_link)
if(!strcmp(t->s_uuid, id)) if(!strcmp(t->s_nicename, id)) // XXX(dvbreorg)
return t; return t;
} }

View file

@ -60,6 +60,7 @@
#include "ffdecsa/FFdecsa.h" #include "ffdecsa/FFdecsa.h"
#include "muxes.h" #include "muxes.h"
#include "config2.h" #include "config2.h"
#include "idnode.h"
int running; int running;
time_t dispatch_clock; time_t dispatch_clock;
@ -444,6 +445,9 @@ main(int argc, char **argv)
access_init(createdefault); access_init(createdefault);
tcp_server_init(); tcp_server_init();
idnode_init();
#if ENABLE_LINUXDVB #if ENABLE_LINUXDVB
dvb_init(adapter_mask, dvb_rawts_input); dvb_init(adapter_mask, dvb_rawts_input);
#endif #endif

View file

@ -49,12 +49,15 @@
#include "htsp_server.h" #include "htsp_server.h"
#include "lang_codes.h" #include "lang_codes.h"
#define SERVICE_HASH_WIDTH 101
static struct service_list servicehash[SERVICE_HASH_WIDTH];
static void service_data_timeout(void *aux); static void service_data_timeout(void *aux);
static htsmsg_t *service_serialize(struct idnode *self, int full);
static const idclass_t service_class = {
.ic_class = "service",
.ic_serialize = service_serialize,
};
/** /**
* *
*/ */
@ -391,14 +394,14 @@ service_destroy(service_t *t)
} }
LIST_REMOVE(t, s_group_link); LIST_REMOVE(t, s_group_link);
LIST_REMOVE(t, s_hash_link);
idnode_unlink(&t->s_id);
if(t->s_status != SERVICE_IDLE) if(t->s_status != SERVICE_IDLE)
service_stop(t); service_stop(t);
t->s_status = SERVICE_ZOMBIE; t->s_status = SERVICE_ZOMBIE;
free(t->s_uuid);
free(t->s_svcname); free(t->s_svcname);
free(t->s_provider); free(t->s_provider);
free(t->s_dvb_charset); free(t->s_dvb_charset);
@ -429,14 +432,12 @@ service_destroy(service_t *t)
service_t * service_t *
service_create(const char *uuid, int source_type) service_create(const char *uuid, int source_type)
{ {
unsigned int hash = tvh_strhash(uuid, SERVICE_HASH_WIDTH);
service_t *t = calloc(1, sizeof(service_t)); service_t *t = calloc(1, sizeof(service_t));
lock_assert(&global_lock); lock_assert(&global_lock);
pthread_mutex_init(&t->s_stream_mutex, NULL); pthread_mutex_init(&t->s_stream_mutex, NULL);
pthread_cond_init(&t->s_tss_cond, NULL); pthread_cond_init(&t->s_tss_cond, NULL);
t->s_uuid = strdup(uuid);
t->s_source_type = source_type; t->s_source_type = source_type;
t->s_refcount = 1; t->s_refcount = 1;
t->s_enabled = 1; t->s_enabled = 1;
@ -449,7 +450,8 @@ service_create(const char *uuid, int source_type)
streaming_pad_init(&t->s_streaming_pad); streaming_pad_init(&t->s_streaming_pad);
LIST_INSERT_HEAD(&servicehash[hash], t, s_hash_link); idnode_insert(&t->s_id, uuid, &service_class);
return t; return t;
} }
@ -459,15 +461,8 @@ service_create(const char *uuid, int source_type)
service_t * service_t *
service_find_by_identifier(const char *identifier) service_find_by_identifier(const char *identifier)
{ {
service_t *t; idnode_t *id = idnode_find(identifier);
unsigned int hash = tvh_strhash(identifier, SERVICE_HASH_WIDTH); return id->in_class == &service_class ? (service_t *)id : NULL;
lock_assert(&global_lock);
LIST_FOREACH(t, &servicehash[hash], s_hash_link)
if(!strcmp(t->s_uuid, identifier))
break;
return t;
} }
@ -1128,3 +1123,14 @@ htsmsg_t *servicetype_list ( void )
} }
return ret; return ret;
} }
/**
*
*/
static htsmsg_t *
service_serialize(struct idnode *self, int full)
{
service_t *s = (service_t *)self;
return s->s_serialize(s, full);
}

View file

@ -22,7 +22,7 @@
#define PID_TELETEXT_BASE 0x2000 #define PID_TELETEXT_BASE 0x2000
#include "htsmsg.h" #include "htsmsg.h"
#include "idnode.h"
/** /**
@ -201,8 +201,7 @@ service_start_cand_t *service_find_cand(struct service_start_cand_list *sscl,
* *
*/ */
typedef struct service { typedef struct service {
idnode_t s_id;
LIST_ENTRY(service) s_hash_link;
enum { enum {
/** /**
@ -305,16 +304,13 @@ typedef struct service {
void (*s_dtor)(struct service *t); void (*s_dtor)(struct service *t);
htsmsg_t *(*s_serialize)(struct service *s, int full);
/* /*
* Per source type structs * Per source type structs
*/ */
struct dvb_mux *s_dvb_mux; struct dvb_mux *s_dvb_mux;
/**
* Unique identifer
*/
char *s_uuid;
/** /**
* Name usable for displaying to user * Name usable for displaying to user
*/ */

View file

@ -401,8 +401,8 @@ streaming_code2txt(int code)
case SM_CODE_SUBSCRIPTION_OVERRIDDEN: case SM_CODE_SUBSCRIPTION_OVERRIDDEN:
return "Subscription overridden"; return "Subscription overridden";
case SM_CODE_NO_HW_ATTACHED: case SM_CODE_NO_FREE_ADAPTER:
return "No hardware present"; return "No free adapter";
case SM_CODE_MUX_NOT_ENABLED: case SM_CODE_MUX_NOT_ENABLED:
return "Mux not enabled"; return "Mux not enabled";
case SM_CODE_NOT_FREE: case SM_CODE_NOT_FREE:

View file

@ -284,7 +284,7 @@ typedef enum {
#define SM_CODE_SOURCE_DELETED 102 #define SM_CODE_SOURCE_DELETED 102
#define SM_CODE_SUBSCRIPTION_OVERRIDDEN 103 #define SM_CODE_SUBSCRIPTION_OVERRIDDEN 103
#define SM_CODE_NO_HW_ATTACHED 200 #define SM_CODE_NO_FREE_ADAPTER 200
#define SM_CODE_MUX_NOT_ENABLED 201 #define SM_CODE_MUX_NOT_ENABLED 201
#define SM_CODE_NOT_FREE 202 #define SM_CODE_NOT_FREE 202
#define SM_CODE_TUNING_FAILED 203 #define SM_CODE_TUNING_FAILED 203

View file

@ -1669,7 +1669,7 @@ build_record_iptv(service_t *t)
htsmsg_t *r = htsmsg_create_map(); htsmsg_t *r = htsmsg_create_map();
char abuf[INET_ADDRSTRLEN]; char abuf[INET_ADDRSTRLEN];
char abuf6[INET6_ADDRSTRLEN]; char abuf6[INET6_ADDRSTRLEN];
htsmsg_add_str(r, "id", t->s_uuid); // htsmsg_add_str(r, "id", t->s_uuid); // XXX(dvbreorg)
htsmsg_add_str(r, "channelname", t->s_ch ? t->s_ch->ch_name : ""); htsmsg_add_str(r, "channelname", t->s_ch ? t->s_ch->ch_name : "");
htsmsg_add_str(r, "interface", t->s_iptv_iface ?: ""); htsmsg_add_str(r, "interface", t->s_iptv_iface ?: "");
@ -1828,7 +1828,7 @@ extjs_tvadapter(http_connection_t *hc, const char *remain, void *opaque)
array = htsmsg_create_list(); array = htsmsg_create_list();
#if ENABLE_LINUXDVB #if ENABLE_LINUXDVB
// extjs_list_dvb_adapters(array); extjs_list_dvb_adapters(array);
#endif #endif
#if ENABLE_V4L #if ENABLE_V4L

View file

@ -43,7 +43,6 @@
#include "dvb/dvb_preconf.h" #include "dvb/dvb_preconf.h"
#include "dvr/dvr.h" #include "dvr/dvr.h"
#if 0
@ -61,7 +60,7 @@ extjs_dvblocations(http_connection_t *hc, const char *remain, void *opaque)
if(s == NULL || a == NULL) if(s == NULL || a == NULL)
return HTTP_STATUS_BAD_REQUEST; return HTTP_STATUS_BAD_REQUEST;
pthread_mutex_lock(&global_lock); pthread_mutex_lock(&global_lock);
if(http_access_verify(hc, ACCESS_ADMIN)) { if(http_access_verify(hc, ACCESS_ADMIN)) {
@ -85,6 +84,7 @@ extjs_dvblocations(http_connection_t *hc, const char *remain, void *opaque)
return 0; return 0;
} }
/** /**
* *
*/ */
@ -115,8 +115,6 @@ extjs_dvbadapter(http_connection_t *hc, const char *remain, void *opaque)
const char *op = http_arg_get(&hc->hc_req_args, "op"); const char *op = http_arg_get(&hc->hc_req_args, "op");
const char *sibling = http_arg_get(&hc->hc_req_args, "sibling"); const char *sibling = http_arg_get(&hc->hc_req_args, "sibling");
const char *s; const char *s;
th_dvb_mux_instance_t *tdmi;
service_t *t;
pthread_mutex_lock(&global_lock); pthread_mutex_lock(&global_lock);
@ -151,15 +149,12 @@ extjs_dvbadapter(http_connection_t *hc, const char *remain, void *opaque)
htsmsg_add_str(r, "id", tda->tda_identifier); htsmsg_add_str(r, "id", tda->tda_identifier);
htsmsg_add_str(r, "device", tda->tda_rootpath ?: "No hardware attached"); htsmsg_add_str(r, "device", tda->tda_rootpath ?: "No hardware attached");
htsmsg_add_str(r, "name", tda->tda_displayname); htsmsg_add_str(r, "name", tda->tda_displayname);
htsmsg_add_u32(r, "automux", tda->tda_autodiscovery);
htsmsg_add_u32(r, "skip_initialscan", tda->tda_skip_initialscan); htsmsg_add_u32(r, "skip_initialscan", tda->tda_skip_initialscan);
htsmsg_add_u32(r, "idleclose", tda->tda_idleclose); htsmsg_add_u32(r, "idleclose", tda->tda_idleclose);
htsmsg_add_u32(r, "skip_checksubscr", tda->tda_skip_checksubscr); htsmsg_add_u32(r, "skip_checksubscr", tda->tda_skip_checksubscr);
htsmsg_add_u32(r, "qmon", tda->tda_qmon); htsmsg_add_u32(r, "qmon", tda->tda_qmon);
htsmsg_add_u32(r, "poweroff", tda->tda_poweroff); htsmsg_add_u32(r, "poweroff", tda->tda_poweroff);
htsmsg_add_u32(r, "sidtochan", tda->tda_sidtochan); htsmsg_add_u32(r, "sidtochan", tda->tda_sidtochan);
htsmsg_add_u32(r, "nitoid", tda->tda_nitoid);
htsmsg_add_u32(r, "disable_pmt_monitor", tda->tda_disable_pmt_monitor);
htsmsg_add_u32(r, "full_mux_rx", tda->tda_full_mux_rx+1); htsmsg_add_u32(r, "full_mux_rx", tda->tda_full_mux_rx+1);
htsmsg_add_str(r, "diseqcversion", htsmsg_add_str(r, "diseqcversion",
((const char *[]){"DiSEqC 1.0 / 2.0", ((const char *[]){"DiSEqC 1.0 / 2.0",
@ -176,9 +171,6 @@ extjs_dvbadapter(http_connection_t *hc, const char *remain, void *opaque)
if((s = http_arg_get(&hc->hc_req_args, "name")) != NULL) if((s = http_arg_get(&hc->hc_req_args, "name")) != NULL)
dvb_adapter_set_displayname(tda, s); dvb_adapter_set_displayname(tda, s);
s = http_arg_get(&hc->hc_req_args, "automux");
dvb_adapter_set_auto_discovery(tda, !!s);
s = http_arg_get(&hc->hc_req_args, "skip_initialscan"); s = http_arg_get(&hc->hc_req_args, "skip_initialscan");
dvb_adapter_set_skip_initialscan(tda, !!s); dvb_adapter_set_skip_initialscan(tda, !!s);
@ -197,15 +189,9 @@ extjs_dvbadapter(http_connection_t *hc, const char *remain, void *opaque)
s = http_arg_get(&hc->hc_req_args, "sidtochan"); s = http_arg_get(&hc->hc_req_args, "sidtochan");
dvb_adapter_set_sidtochan(tda, !!s); dvb_adapter_set_sidtochan(tda, !!s);
s = http_arg_get(&hc->hc_req_args, "disable_pmt_monitor");
dvb_adapter_set_disable_pmt_monitor(tda, !!s);
s = http_arg_get(&hc->hc_req_args, "full_mux_rx"); s = http_arg_get(&hc->hc_req_args, "full_mux_rx");
dvb_adapter_set_full_mux_rx(tda, atoi(s)-1); dvb_adapter_set_full_mux_rx(tda, atoi(s)-1);
if((s = http_arg_get(&hc->hc_req_args, "nitoid")) != NULL)
dvb_adapter_set_nitoid(tda, atoi(s));
if((s = http_arg_get(&hc->hc_req_args, "diseqcversion")) != NULL) { if((s = http_arg_get(&hc->hc_req_args, "diseqcversion")) != NULL) {
if(!strcmp(s, "DiSEqC 1.0 / 2.0")) if(!strcmp(s, "DiSEqC 1.0 / 2.0"))
dvb_adapter_set_diseqc_version(tda, 0); dvb_adapter_set_diseqc_version(tda, 0);
@ -231,11 +217,11 @@ extjs_dvbadapter(http_connection_t *hc, const char *remain, void *opaque)
// sc = http_arg_get(&hc->hc_req_args, "satconf"); // sc = http_arg_get(&hc->hc_req_args, "satconf");
if((s = http_arg_get(&hc->hc_req_args, "network")) != NULL) if((s = http_arg_get(&hc->hc_req_args, "network")) != NULL)
dvb_mux_preconf_add_network(tda, s); dvb_mux_preconf_add_network(tda->tda_dn, s);
out = htsmsg_create_map(); out = htsmsg_create_map();
htsmsg_add_u32(out, "success", 1); htsmsg_add_u32(out, "success", 1);
#if 0
} else if(!strcmp(op, "serviceprobe")) { } else if(!strcmp(op, "serviceprobe")) {
tvhlog(LOG_NOTICE, "web interface", tvhlog(LOG_NOTICE, "web interface",
@ -251,6 +237,7 @@ extjs_dvbadapter(http_connection_t *hc, const char *remain, void *opaque)
out = htsmsg_create_map(); out = htsmsg_create_map();
htsmsg_add_u32(out, "success", 1); htsmsg_add_u32(out, "success", 1);
#endif
} else { } else {
pthread_mutex_unlock(&global_lock); pthread_mutex_unlock(&global_lock);
@ -265,6 +252,7 @@ extjs_dvbadapter(http_connection_t *hc, const char *remain, void *opaque)
return 0; return 0;
} }
#if 0
/** /**
* *
@ -678,6 +666,8 @@ extjs_dvb_copymux(http_connection_t *hc, const char *remain, void *opaque)
} }
#endif #endif
#endif
/** /**
* *
*/ */
@ -689,7 +679,6 @@ extjs_list_dvb_adapters(htsmsg_t *array)
htsmsg_add_msg(array, NULL, dvb_adapter_build_msg(tda)); htsmsg_add_msg(array, NULL, dvb_adapter_build_msg(tda));
} }
#endif
/** /**
* *
@ -711,27 +700,29 @@ extjs_dvbnetworks(http_connection_t *hc, const char *remain, void *opaque)
return HTTP_STATUS_UNAUTHORIZED; return HTTP_STATUS_UNAUTHORIZED;
} }
printf("s=%s\n", s);
out = htsmsg_create_list(); out = htsmsg_create_list();
if(!strcmp(s, "root")) { idnode_t **v;
htsmsg_t *n = htsmsg_create_map();
htsmsg_add_str(n, "text", "Network1");
htsmsg_add_str(n, "id", "net/1");
htsmsg_add_str(n, "cls", "folder");
htsmsg_add_str(n, "iconCls", "iptv");
htsmsg_add_msg(out, NULL, n);
n = htsmsg_create_map(); if(!strcmp(s, "root")) {
htsmsg_add_str(n, "text", "Network2"); v = dvb_network_root();
htsmsg_add_str(n, "id", "net/2"); } else {
htsmsg_add_str(n, "cls", "folder"); idnode_t *n = idnode_find(s);
htsmsg_add_msg(out, NULL, n); v = n != NULL && n->in_class->ic_get_childs != NULL ?
n->in_class->ic_get_childs(n) : NULL;
} }
int i;
for(i = 0; v[i] != NULL; i++) {
htsmsg_t *m = v[i]->in_class->ic_serialize(v[i], 0);
if(v[i]->in_class->ic_get_childs == NULL)
htsmsg_add_u32(m, "leaf", 1);
htsmsg_add_msg(out, NULL, m);
}
pthread_mutex_unlock(&global_lock); pthread_mutex_unlock(&global_lock);
free(v);
htsmsg_json_serialize(out, hq, 0); htsmsg_json_serialize(out, hq, 0);
htsmsg_destroy(out); htsmsg_destroy(out);
http_output_content(hc, "text/x-json; charset=UTF-8"); http_output_content(hc, "text/x-json; charset=UTF-8");
@ -748,14 +739,14 @@ extjs_start_dvb(void)
{ {
http_path_add("/dvb/networks", http_path_add("/dvb/networks",
NULL, extjs_dvbnetworks, ACCESS_WEB_INTERFACE); NULL, extjs_dvbnetworks, ACCESS_WEB_INTERFACE);
#if 0
http_path_add("/dvb/locations", http_path_add("/dvb/locations",
NULL, extjs_dvblocations, ACCESS_WEB_INTERFACE); NULL, extjs_dvblocations, ACCESS_WEB_INTERFACE);
http_path_add("/dvb/adapter", http_path_add("/dvb/adapter",
NULL, extjs_dvbadapter, ACCESS_ADMIN); NULL, extjs_dvbadapter, ACCESS_ADMIN);
#if 0
http_path_add("/dvb/muxes", http_path_add("/dvb/muxes",
NULL, extjs_dvbmuxes, ACCESS_ADMIN); NULL, extjs_dvbmuxes, ACCESS_ADMIN);

View file

@ -0,0 +1,25 @@
/**
*
*/
tvheadend.dvb_networks = function() {
var loader = new Ext.tree.TreeLoader({
dataUrl: 'dvb/networks'
});
var tree = new Ext.tree.TreePanel({
title: 'DVB Networks',
loader: loader,
root : new Ext.tree.AsyncTreeNode({
id : 'root',
text: 'DVB Networks'
})
});
tree.on('render', function() {
tree.getRootNode().expand();
});
return tree;
}

View file

@ -606,7 +606,7 @@ http_stream_tdmi(http_connection_t *hc, th_dvb_mux_instance_t *tdmi)
streaming_queue_init(&sq, SMT_PACKET); streaming_queue_init(&sq, SMT_PACKET);
s = dvb_subscription_create_from_tdmi(tdmi, "HTTP", &sq.sq_st); s = dvb_subscription_create_from_tdmi(tdmi, "HTTP", &sq.sq_st);
name = strdupa(tdmi->tdmi_mux->dm_uuid); name = "foo"; // strdupa(tdmi->tdmi_mux->dm_uuid); XXX(dvbreorg)
pthread_mutex_unlock(&global_lock); pthread_mutex_unlock(&global_lock);
http_stream_run(hc, &sq, name, MC_PASS); http_stream_run(hc, &sq, name, MC_PASS);
pthread_mutex_lock(&global_lock); pthread_mutex_lock(&global_lock);