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:
parent
963a0502d3
commit
fef5755fe7
24 changed files with 825 additions and 284 deletions
1
Makefile
1
Makefile
|
@ -63,6 +63,7 @@ endif
|
|||
# Core
|
||||
#
|
||||
SRCS = src/main.c \
|
||||
src/idnode.c \
|
||||
src/utils.c \
|
||||
src/wrappers.c \
|
||||
src/version.c \
|
||||
|
|
|
@ -26,5 +26,6 @@ void
|
|||
dvb_init(uint32_t adapter_mask, const char *rawfile)
|
||||
{
|
||||
dvb_charset_init();
|
||||
dvb_network_init();
|
||||
dvb_adapter_init(adapter_mask, rawfile);
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include <pthread.h>
|
||||
#include "htsmsg.h"
|
||||
#include "psi.h"
|
||||
#include "idnode.h"
|
||||
|
||||
struct service;
|
||||
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))
|
||||
|
||||
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);
|
||||
LIST_HEAD(th_dvb_mux_instance_list, th_dvb_mux_instance);
|
||||
TAILQ_HEAD(dvb_satconf_queue, dvb_satconf);
|
||||
|
@ -89,11 +90,14 @@ typedef struct dvb_mux_conf {
|
|||
*
|
||||
*/
|
||||
typedef struct dvb_network {
|
||||
idnode_t dn_id;
|
||||
|
||||
LIST_ENTRY(dvb_network) dn_global_link;
|
||||
|
||||
struct dvb_mux_queue dn_initial_scan_queue;
|
||||
int dn_initial_num_mux;
|
||||
struct dvb_mux_queue dn_initial_scan_pending_queue;
|
||||
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;
|
||||
|
||||
|
@ -101,13 +105,11 @@ typedef struct dvb_network {
|
|||
|
||||
struct dvb_mux_list dn_muxes;
|
||||
|
||||
gtimer_t dn_mux_scanner_timer;
|
||||
|
||||
uint32_t dn_disable_pmt_monitor;
|
||||
uint32_t dn_autodiscovery;
|
||||
uint32_t dn_nitoid;
|
||||
|
||||
char *dn_uuid;
|
||||
struct th_dvb_adapter_list dn_adapters;
|
||||
|
||||
} dvb_network_t;
|
||||
|
||||
|
@ -117,7 +119,7 @@ typedef struct dvb_network {
|
|||
*
|
||||
*/
|
||||
typedef struct dvb_mux {
|
||||
|
||||
idnode_t dm_id;
|
||||
LIST_ENTRY(dvb_mux) dm_network_link;
|
||||
dvb_network_t *dm_dn;
|
||||
|
||||
|
@ -132,14 +134,20 @@ typedef struct dvb_mux {
|
|||
|
||||
TAILQ_HEAD(, epggrab_ota_mux) dm_epg_grab;
|
||||
|
||||
gtimer_t dm_initial_scan_timeout;
|
||||
|
||||
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;
|
||||
int dm_num_tables;
|
||||
|
||||
TAILQ_HEAD(, th_dvb_table) dm_table_queue;
|
||||
int dm_table_initial;
|
||||
// int dm_table_initial;
|
||||
|
||||
struct th_dvb_mux_instance *dm_current_tdmi;
|
||||
|
||||
|
@ -148,8 +156,6 @@ typedef struct dvb_mux {
|
|||
// Derived from dm_conf (more or less)
|
||||
char *dm_local_identifier;
|
||||
|
||||
char *dm_uuid;
|
||||
|
||||
int dm_enabled;
|
||||
|
||||
} dvb_mux_t;
|
||||
|
@ -193,6 +199,8 @@ typedef struct th_dvb_mux_instance {
|
|||
int tdmi_tune_failed; // Adapter failed to tune this frequency
|
||||
// Don't try again
|
||||
|
||||
int tdmi_weight;
|
||||
|
||||
struct th_subscription_list tdmi_subscriptions;
|
||||
|
||||
} th_dvb_mux_instance_t;
|
||||
|
@ -226,6 +234,7 @@ typedef struct th_dvb_adapter {
|
|||
TAILQ_ENTRY(th_dvb_adapter) tda_global_link;
|
||||
|
||||
dvb_network_t *tda_dn;
|
||||
LIST_ENTRY(th_dvb_adapter) tda_network_link;
|
||||
|
||||
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);
|
||||
|
||||
|
||||
void dvb_mux_initial_scan_done(dvb_mux_t *dm);
|
||||
|
||||
/**
|
||||
* 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);
|
||||
|
||||
htsmsg_t *dvb_service_build_msg(struct service *t);
|
||||
|
||||
/**
|
||||
* 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);
|
||||
|
||||
|
||||
/**
|
||||
|
|
|
@ -46,7 +46,6 @@
|
|||
#include "diseqc.h"
|
||||
|
||||
struct th_dvb_adapter_queue dvb_adapters;
|
||||
struct th_dvb_mux_instance_tree dvb_muxes;
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
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);
|
||||
|
||||
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,
|
||||
tda->tda_fe_info->name);
|
||||
|
|
188
src/dvb/dvb_fe.c
188
src/dvb/dvb_fe.c
|
@ -107,6 +107,7 @@ dvb_fe_monitor(void *aux)
|
|||
/**
|
||||
* Read out front end status
|
||||
*/
|
||||
|
||||
if(ioctl(tda->tda_fe_fd, FE_READ_STATUS, &fe_status))
|
||||
fe_status = 0;
|
||||
|
||||
|
@ -254,6 +255,7 @@ dvb_fe_monitor(void *aux)
|
|||
}
|
||||
|
||||
|
||||
#if 0
|
||||
/**
|
||||
* Stop the given TDMI
|
||||
*/
|
||||
|
@ -266,16 +268,8 @@ dvb_fe_stop(th_dvb_adapter_t *tda, int retune)
|
|||
assert(tdmi != NULL);
|
||||
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);
|
||||
|
||||
assert(dm->dm_scan_queue == NULL);
|
||||
|
||||
epggrab_mux_stop(dm, 0);
|
||||
|
||||
#if 0 /// XXX(dvbreorg)
|
||||
|
@ -285,6 +279,9 @@ dvb_fe_stop(th_dvb_adapter_t *tda, int retune)
|
|||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#if DVB_API_VERSION >= 5
|
||||
|
||||
|
@ -342,9 +339,8 @@ static struct dtv_properties clear_cmdseq = {
|
|||
*
|
||||
*/
|
||||
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;
|
||||
int r;
|
||||
|
||||
|
@ -388,47 +384,151 @@ dvb_fe_tune_s2(th_dvb_mux_instance_t *tdmi, dvb_mux_conf_t *dmc)
|
|||
|
||||
#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
|
||||
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;
|
||||
|
||||
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
|
||||
dvb_mux_conf_t dmc = dm->dm_conf;
|
||||
dvb_frontend_parameters_t* p = &dmc.dmc_fe_params;
|
||||
|
||||
th_dvb_mux_instance_t *tdmi;
|
||||
|
||||
char buf[256];
|
||||
int r;
|
||||
|
||||
|
||||
assert(dm->dm_current_tdmi == NULL);
|
||||
|
||||
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);
|
||||
tda->tda_tune_reason = strdup(reason);
|
||||
|
||||
if(tda->tda_current_tdmi == tdmi) {
|
||||
dvb_adapter_notify(tda);
|
||||
return 0;
|
||||
}
|
||||
tdmi->tdmi_weight = weight;
|
||||
|
||||
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) {
|
||||
|
||||
|
||||
/* DVB-S */
|
||||
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_qam2str(dmc.dmc_fe_modulation), reason);
|
||||
|
||||
r = dvb_fe_tune_s2(tdmi, &dmc);
|
||||
r = dvb_fe_tune_s2(tda, &dmc);
|
||||
} else
|
||||
#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);
|
||||
}
|
||||
|
||||
|
@ -499,24 +599,26 @@ dvb_fe_tune(dvb_mux_t *dm, const char *reason)
|
|||
" -- Front configuration failed -- %s, frequency: %u",
|
||||
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 */
|
||||
tdmi->tdmi_tune_failed = 1;
|
||||
return SM_CODE_TUNING_FAILED;
|
||||
goto retry;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
|
||||
dvb_table_add_default(tdmi->tdmi_mux);
|
||||
epggrab_mux_start(tdmi->tdmi_mux);
|
||||
dvb_table_add_default(dm);
|
||||
epggrab_mux_start(dm);
|
||||
|
||||
dvb_adapter_notify(tda);
|
||||
return 0;
|
||||
|
|
|
@ -59,7 +59,7 @@ open_service(th_dvb_adapter_t *tda, service_t *s)
|
|||
st->es_demuxer_fd = -1;
|
||||
tvhlog(LOG_ERR, "dvb",
|
||||
"\"%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));
|
||||
continue;
|
||||
}
|
||||
|
@ -74,7 +74,7 @@ open_service(th_dvb_adapter_t *tda, service_t *s)
|
|||
if(ioctl(fd, DMX_SET_PES_FILTER, &dmx_param)) {
|
||||
tvhlog(LOG_ERR, "dvb",
|
||||
"\"%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));
|
||||
close(fd);
|
||||
fd = -1;
|
||||
|
|
|
@ -46,8 +46,6 @@
|
|||
#include "subscriptions.h"
|
||||
#include "epggrab.h"
|
||||
|
||||
struct th_dvb_mux_instance_tree dvb_muxes;
|
||||
|
||||
static struct strtab muxfestatustab[] = {
|
||||
{ "Unknown", TDMI_FE_UNKNOWN },
|
||||
{ "No signal", TDMI_FE_NO_SIGNAL },
|
||||
|
@ -58,18 +56,51 @@ static struct strtab muxfestatustab[] = {
|
|||
{ "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
|
||||
mux_link_initial(dvb_network_t *dn, dvb_mux_t *dm)
|
||||
{
|
||||
dm->dm_scan_queue = &dn->dn_initial_scan_queue;
|
||||
TAILQ_INSERT_TAIL(dm->dm_scan_queue, dm, dm_scan_link);
|
||||
assert(dm->dm_scan_status == DM_SCAN_DONE);
|
||||
|
||||
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
|
||||
*/
|
||||
|
@ -136,7 +167,7 @@ dcm_compare_conf(int adapter_type,
|
|||
dvb_mux_t *
|
||||
dvb_mux_create(dvb_network_t *dn, const struct dvb_mux_conf *dmc,
|
||||
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)
|
||||
{
|
||||
dvb_mux_t *dm;
|
||||
|
@ -186,16 +217,6 @@ dvb_mux_create(dvb_network_t *dn, const struct dvb_mux_conf *dmc,
|
|||
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) {
|
||||
char buf[128];
|
||||
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;
|
||||
LIST_INSERT_HEAD(&dn->dn_muxes, dm, dm_network_link);
|
||||
|
||||
idnode_insert(&dm->dm_id, uuid, &dvb_mux_class);
|
||||
|
||||
char identifier[128];
|
||||
snprintf(identifier, sizeof(identifier),
|
||||
"%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));
|
||||
|
||||
dm->dm_table_initial = initialscan;
|
||||
|
||||
if(source != NULL) {
|
||||
char buf[128];
|
||||
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);
|
||||
|
||||
if(enabled && dm->dm_table_initial) {
|
||||
dn->dn_initial_num_mux++;
|
||||
if(enabled && needscan) {
|
||||
dn->dn_initial_scan_num_mux++;
|
||||
mux_link_initial(dn, dm);
|
||||
}
|
||||
|
||||
|
@ -271,6 +292,7 @@ void
|
|||
dvb_mux_destroy(dvb_mux_t *dm)
|
||||
{
|
||||
th_dvb_mux_instance_t *tdmi;
|
||||
dvb_network_t *dn = dm->dm_dn;
|
||||
|
||||
lock_assert(&global_lock);
|
||||
|
||||
|
@ -279,16 +301,25 @@ dvb_mux_destroy(dvb_mux_t *dm)
|
|||
while((tdmi = LIST_FIRST(&dm->dm_tdmis)) != NULL)
|
||||
dvb_tdmi_destroy(tdmi);
|
||||
|
||||
if(dm->dm_scan_queue != NULL)
|
||||
TAILQ_REMOVE(dm->dm_scan_queue, dm, dm_scan_link);
|
||||
switch(dm->dm_scan_status) {
|
||||
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);
|
||||
|
||||
free(dm->dm_local_identifier);
|
||||
free(dm->dm_uuid);
|
||||
idnode_unlink(&dm->dm_id);
|
||||
free(dm);
|
||||
}
|
||||
|
||||
|
@ -492,7 +523,7 @@ dvb_mux_save(dvb_mux_t *dm)
|
|||
|
||||
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)
|
||||
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",
|
||||
dm->dm_dn->dn_uuid,
|
||||
idnode_uuid_as_str(&dm->dm_dn->dn_id),
|
||||
dm->dm_local_identifier);
|
||||
|
||||
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;
|
||||
const char *s;
|
||||
int r;
|
||||
unsigned int onid, tsid, enabled, initscan;
|
||||
unsigned int onid, tsid, enabled;
|
||||
|
||||
memset(&dmc, 0, sizeof(dmc));
|
||||
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))
|
||||
enabled = 1;
|
||||
|
||||
initscan = htsmsg_get_u32_or_default(m, "initialscan", 0);
|
||||
dm = dvb_mux_create(dn, &dmc,
|
||||
onid, tsid, htsmsg_get_str(m, "network"), NULL, enabled,
|
||||
initscan,
|
||||
htsmsg_get_u32_or_default(m, "needscan", 1),
|
||||
htsmsg_get_str(m, "uuid"));
|
||||
if(dm != NULL) {
|
||||
|
||||
|
@ -718,13 +748,16 @@ dvb_mux_load(dvb_network_t *dn)
|
|||
htsmsg_field_t *f;
|
||||
|
||||
if((l = hts_settings_load_r(1, "dvb/networks/%s/muxes",
|
||||
dn->dn_uuid)) == NULL)
|
||||
idnode_uuid_as_str(&dn->dn_id))) == NULL)
|
||||
return;
|
||||
|
||||
HTSMSG_FOREACH(f, l) {
|
||||
if((c = htsmsg_get_map_by_field(f)) == NULL)
|
||||
continue;
|
||||
|
||||
if((c = htsmsg_get_map(c, "config")) == NULL)
|
||||
continue;
|
||||
|
||||
dvb_mux_create_by_msg(dn, c, f->hmf_name);
|
||||
}
|
||||
htsmsg_destroy(l);
|
||||
|
@ -765,7 +798,7 @@ dvb_mux_set_tsid(dvb_mux_t *dm, uint16_t tsid)
|
|||
dvb_mux_save(dm);
|
||||
|
||||
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);
|
||||
notify_by_msg("dvbMux", m);
|
||||
}
|
||||
|
@ -783,7 +816,7 @@ dvb_mux_set_onid(dvb_mux_t *dm, uint16_t onid)
|
|||
dvb_mux_save(dm);
|
||||
|
||||
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);
|
||||
notify_by_msg("dvbMux", m);
|
||||
}
|
||||
|
@ -917,7 +950,7 @@ dvb_mux_build_msg(dvb_mux_t *dm)
|
|||
htsmsg_t *m = htsmsg_create_map();
|
||||
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_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;
|
||||
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);
|
||||
streaming_target_connect(&tda->tda_streaming_pad, &s->ths_input);
|
||||
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");
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -16,36 +16,129 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include "tvheadend.h"
|
||||
#include "packet.h"
|
||||
#include "dvb.h"
|
||||
#include "epggrab.h"
|
||||
#include "settings.h"
|
||||
#include "dvb_support.h"
|
||||
|
||||
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_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));
|
||||
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;
|
||||
TAILQ_INIT(&dn->dn_initial_scan_queue);
|
||||
gtimer_arm(&dn->dn_mux_scanner_timer, dvb_network_mux_scanner, dn, 1);
|
||||
TAILQ_INIT(&dn->dn_initial_scan_pending_queue);
|
||||
TAILQ_INIT(&dn->dn_initial_scan_current_queue);
|
||||
|
||||
dn->dn_autodiscovery = fe_type != FE_QPSK;
|
||||
LIST_INSERT_HEAD(&dvb_networks, dn, dn_global_link);
|
||||
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);
|
||||
|
||||
htsmsg_add_u32(m, "fetype", dn->dn_fe_type);
|
||||
htsmsg_add_u32(m, "autodiscovery", dn->dn_autodiscovery);
|
||||
htsmsg_add_u32(m, "nitoid", dn->dn_nitoid);
|
||||
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
|
||||
|
||||
|
||||
#if 0
|
||||
/**
|
||||
*
|
||||
|
@ -125,65 +223,82 @@ dvb_network_set_disable_pmt_monitor(th_dvb_network_t *dn, int on)
|
|||
#endif
|
||||
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
void
|
||||
dvb_network_mux_scanner(void *aux)
|
||||
static void
|
||||
dvb_network_initial_scan(void *aux)
|
||||
{
|
||||
dvb_network_t *dn = aux;
|
||||
dvb_mux_t *dm;
|
||||
|
||||
// default period
|
||||
gtimer_arm(&dn->dn_mux_scanner_timer, dvb_network_mux_scanner, dn, 20);
|
||||
|
||||
#if 0
|
||||
/* No muxes */
|
||||
if(LIST_FIRST(&dn->dn_mux_instances) == NULL) {
|
||||
dvb_adapter_poweroff(tda);
|
||||
return;
|
||||
while((dm = TAILQ_FIRST(&dn->dn_initial_scan_pending_queue)) != NULL) {
|
||||
assert(dm->dm_scan_status == DM_SCAN_PENDING);
|
||||
if(dvb_fe_tune(dm, "initial scan", 1))
|
||||
break;
|
||||
assert(dm->dm_scan_status == DM_SCAN_CURRENT);
|
||||
}
|
||||
#endif
|
||||
#if 0
|
||||
/* Someone is actively using */
|
||||
if(service_compute_weight(&tda->tda_transports) > 0)
|
||||
return;
|
||||
#endif
|
||||
#if 0
|
||||
if(tda->tda_mux_current != NULL &&
|
||||
LIST_FIRST(&tda->tda_mux_current->tdmi_subscriptions) != NULL)
|
||||
return; // Someone is doing full mux dump
|
||||
#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;
|
||||
}
|
||||
|
||||
/* Check EPG */
|
||||
if (dn->dn_mux_epg) {
|
||||
// timeout anything not complete
|
||||
epggrab_mux_stop(dn->dn_mux_epg, 1);
|
||||
dn->dn_mux_epg = NULL; // skip this time
|
||||
} else {
|
||||
dn->dn_mux_epg = epggrab_mux_next(dn);
|
||||
}
|
||||
|
||||
/* EPG */
|
||||
if (dn->dn_mux_epg) {
|
||||
int period = epggrab_mux_period(dn->dn_mux_epg);
|
||||
if (period > 20)
|
||||
gtimer_arm(&dn->dn_mux_scanner_timer,
|
||||
dvb_network_mux_scanner, dn, period);
|
||||
dvb_fe_tune(dn->dn_mux_epg, "EPG scan");
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* Ensure we stop current mux and power off (if required) */
|
||||
if (tda->tda_mux_current)
|
||||
dvb_fe_stop(tda->tda_mux_current, 0);
|
||||
#endif
|
||||
gtimer_arm(&dn->dn_initial_scan_timer, dvb_network_initial_scan, dn, 10);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
void
|
||||
dvb_network_schedule_initial_scan(dvb_network_t *dn)
|
||||
{
|
||||
gtimer_arm(&dn->dn_initial_scan_timer, dvb_network_initial_scan, dn, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
void
|
||||
dvb_network_init(void)
|
||||
{
|
||||
htsmsg_t *l, *c;
|
||||
htsmsg_field_t *f;
|
||||
|
||||
if(0) {
|
||||
dvb_network_save(dvb_network_create(FE_QAM, NULL));
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if((l = hts_settings_load_r(1, "dvb/networks")) == NULL)
|
||||
return;
|
||||
|
||||
|
||||
htsmsg_print(l);
|
||||
|
||||
HTSMSG_FOREACH(f, l) {
|
||||
if((c = htsmsg_get_map_by_field(f)) == NULL)
|
||||
continue;
|
||||
|
||||
if((c = htsmsg_get_map(c, "config")) == NULL)
|
||||
continue;
|
||||
|
||||
dvb_network_load(c, f->hmf_name);
|
||||
}
|
||||
htsmsg_destroy(l);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -44,15 +44,7 @@
|
|||
#include "dvb_support.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;
|
||||
#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;
|
||||
|
||||
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,
|
||||
t->s_dvb_service_id);
|
||||
|
||||
|
@ -217,7 +209,8 @@ dvb_service_load(dvb_mux_t *dm)
|
|||
lock_assert(&global_lock);
|
||||
|
||||
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)
|
||||
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_setsourceinfo = dvb_service_setsourceinfo;
|
||||
t->s_grace_period = dvb_grace_period;
|
||||
t->s_serialize = dvb_service_serialize;
|
||||
|
||||
t->s_dvb_mux = dm;
|
||||
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 *
|
||||
dvb_service_build_msg(service_t *t)
|
||||
static htsmsg_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();
|
||||
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_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, "id", idnode_uuid_as_str(&s->s_id));
|
||||
|
||||
htsmsg_add_str(m, "svcname", t->s_svcname ?: "");
|
||||
htsmsg_add_str(m, "provider", t->s_provider ?: "");
|
||||
snprintf(buf, sizeof(buf), "%s (0x%04x)",
|
||||
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 ?: "");
|
||||
|
||||
dvb_mux_nicefreq(buf, sizeof(buf), dm);
|
||||
htsmsg_add_str(m, "mux", buf);
|
||||
|
||||
if(t->s_ch != NULL)
|
||||
htsmsg_add_str(m, "channelname", t->s_ch->ch_name);
|
||||
if(s->s_ch != NULL)
|
||||
htsmsg_add_str(m, "channelname", s->s_ch->ch_name);
|
||||
|
||||
if(t->s_dvb_charset != NULL)
|
||||
htsmsg_add_str(m, "dvb_charset", t->s_dvb_charset);
|
||||
if(s->s_dvb_charset != NULL)
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -52,25 +52,21 @@ dvb_table_fastswitch(th_dvb_mux_instance_t *tdmi)
|
|||
th_dvb_table_t *tdt;
|
||||
th_dvb_adapter_t *tda = tdmi->tdmi_adapter;
|
||||
dvb_mux_t *dm = tdmi->tdmi_mux;
|
||||
dvb_network_t *dn = dm->dm_dn;
|
||||
char buf[100];
|
||||
|
||||
if(!dm->dm_table_initial)
|
||||
if(dm->dm_scan_status == DM_SCAN_DONE)
|
||||
return;
|
||||
|
||||
LIST_FOREACH(tdt, &dm->dm_tables, tdt_link)
|
||||
if((tdt->tdt_flags & TDT_QUICKREQ) && tdt->tdt_count == 0)
|
||||
return;
|
||||
|
||||
dm->dm_table_initial = 0;
|
||||
dn->dn_initial_num_mux--;
|
||||
dvb_mux_save(dm);
|
||||
|
||||
|
||||
dvb_mux_nicename(buf, sizeof(buf), dm);
|
||||
tvhlog(LOG_DEBUG, "dvb", "\"%s\" initial scan completed for \"%s\"",
|
||||
tda->tda_rootpath, buf);
|
||||
dvb_network_mux_scanner(dn);
|
||||
dvb_mux_initial_scan_done(dm);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -369,13 +369,14 @@ void epggrab_ota_complete ( epggrab_ota_mux_t *ota )
|
|||
TAILQ_FOREACH(ota, &dm->dm_epg_grab, dm_link) {
|
||||
if (ota->is_reg && ota->state == EPGGRAB_OTA_MUX_RUNNING) break;
|
||||
}
|
||||
|
||||
#if 0 // XXX(dvbreorg)
|
||||
/* All complete (bring timer forward) */
|
||||
if (!ota) {
|
||||
dvb_network_t *dn = dm->dm_dn;
|
||||
gtimer_arm(&dn->dn_mux_scanner_timer,
|
||||
dvb_network_mux_scanner, dn, 20);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -305,7 +305,7 @@ int fb_scandir ( const char *path, fb_dirent ***list )
|
|||
for (i = 0; i < ret; i++) {
|
||||
(*list)[i] = calloc(1, sizeof(fb_dirent));
|
||||
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);
|
||||
|
|
158
src/idnode.c
Normal file
158
src/idnode.c
Normal 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
29
src/idnode.h
Normal 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);
|
|
@ -227,7 +227,7 @@ iptv_service_start(service_t *t, unsigned int weight, int force_start)
|
|||
fd = tvh_socket(AF_INET6, SOCK_DGRAM, 0);
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -237,7 +237,7 @@ iptv_service_start(service_t *t, unsigned int weight, int force_start)
|
|||
ifr.ifr_name[IFNAMSIZ - 1] = 0;
|
||||
if(ioctl(fd, SIOCGIFINDEX, &ifr)) {
|
||||
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);
|
||||
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));
|
||||
if(bind(fd, (struct sockaddr *)&sin, sizeof(sin)) == -1) {
|
||||
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));
|
||||
close(fd);
|
||||
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,
|
||||
sizeof(struct ip_mreqn)) == -1) {
|
||||
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);
|
||||
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) {
|
||||
inet_ntop(AF_INET6, &sin6.sin6_addr, straddr, sizeof(straddr));
|
||||
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));
|
||||
close(fd);
|
||||
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,
|
||||
straddr, sizeof(straddr));
|
||||
tvhlog(LOG_ERR, "IPTV", "\"%s\" cannot join %s -- %s",
|
||||
t->s_uuid, straddr, strerror(errno));
|
||||
t->s_nicename, straddr, strerror(errno));
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
|
@ -312,7 +312,7 @@ iptv_service_start(service_t *t, unsigned int weight, int force_start)
|
|||
ev.data.fd = fd;
|
||||
if(epoll_ctl(iptv_epollfd, EPOLL_CTL_ADD, fd, &ev) == -1) {
|
||||
tvhlog(LOG_ERR, "IPTV", "\"%s\" cannot add to epoll set -- %s",
|
||||
t->s_uuid, strerror(errno));
|
||||
t->s_nicename, strerror(errno));
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
|
@ -356,7 +356,7 @@ iptv_service_stop(service_t *t)
|
|||
ifr.ifr_name[IFNAMSIZ - 1] = 0;
|
||||
if(ioctl(t->s_iptv_fd, SIOCGIFINDEX, &ifr)) {
|
||||
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) {
|
||||
|
@ -371,7 +371,7 @@ iptv_service_stop(service_t *t)
|
|||
if(setsockopt(t->s_iptv_fd, SOL_IP, IP_DROP_MEMBERSHIP, &m,
|
||||
sizeof(struct ip_mreqn)) == -1) {
|
||||
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 {
|
||||
char straddr[INET6_ADDRSTRLEN];
|
||||
|
@ -388,7 +388,7 @@ iptv_service_stop(service_t *t)
|
|||
straddr, sizeof(straddr));
|
||||
|
||||
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);
|
||||
pthread_mutex_unlock(&t->s_stream_mutex);
|
||||
|
||||
hts_settings_save(m, "iptvservices/%s",
|
||||
t->s_uuid);
|
||||
abort(); // XXX(dvbreorg);
|
||||
|
||||
// hts_settings_save(m, "iptvservices/%s", t->s_uuid);
|
||||
|
||||
htsmsg_destroy(m);
|
||||
}
|
||||
|
@ -484,7 +485,8 @@ iptv_grace_period(service_t *t)
|
|||
static void
|
||||
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;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -60,6 +60,7 @@
|
|||
#include "ffdecsa/FFdecsa.h"
|
||||
#include "muxes.h"
|
||||
#include "config2.h"
|
||||
#include "idnode.h"
|
||||
|
||||
int running;
|
||||
time_t dispatch_clock;
|
||||
|
@ -444,6 +445,9 @@ main(int argc, char **argv)
|
|||
access_init(createdefault);
|
||||
|
||||
tcp_server_init();
|
||||
|
||||
idnode_init();
|
||||
|
||||
#if ENABLE_LINUXDVB
|
||||
dvb_init(adapter_mask, dvb_rawts_input);
|
||||
#endif
|
||||
|
|
|
@ -49,12 +49,15 @@
|
|||
#include "htsp_server.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 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_hash_link);
|
||||
|
||||
|
||||
idnode_unlink(&t->s_id);
|
||||
|
||||
if(t->s_status != SERVICE_IDLE)
|
||||
service_stop(t);
|
||||
|
||||
t->s_status = SERVICE_ZOMBIE;
|
||||
|
||||
free(t->s_uuid);
|
||||
free(t->s_svcname);
|
||||
free(t->s_provider);
|
||||
free(t->s_dvb_charset);
|
||||
|
@ -429,14 +432,12 @@ service_destroy(service_t *t)
|
|||
service_t *
|
||||
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));
|
||||
|
||||
lock_assert(&global_lock);
|
||||
|
||||
pthread_mutex_init(&t->s_stream_mutex, NULL);
|
||||
pthread_cond_init(&t->s_tss_cond, NULL);
|
||||
t->s_uuid = strdup(uuid);
|
||||
t->s_source_type = source_type;
|
||||
t->s_refcount = 1;
|
||||
t->s_enabled = 1;
|
||||
|
@ -449,7 +450,8 @@ service_create(const char *uuid, int source_type)
|
|||
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -459,15 +461,8 @@ service_create(const char *uuid, int source_type)
|
|||
service_t *
|
||||
service_find_by_identifier(const char *identifier)
|
||||
{
|
||||
service_t *t;
|
||||
unsigned int hash = tvh_strhash(identifier, SERVICE_HASH_WIDTH);
|
||||
|
||||
lock_assert(&global_lock);
|
||||
|
||||
LIST_FOREACH(t, &servicehash[hash], s_hash_link)
|
||||
if(!strcmp(t->s_uuid, identifier))
|
||||
break;
|
||||
return t;
|
||||
idnode_t *id = idnode_find(identifier);
|
||||
return id->in_class == &service_class ? (service_t *)id : NULL;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1128,3 +1123,14 @@ htsmsg_t *servicetype_list ( void )
|
|||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
static htsmsg_t *
|
||||
service_serialize(struct idnode *self, int full)
|
||||
{
|
||||
service_t *s = (service_t *)self;
|
||||
return s->s_serialize(s, full);
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
#define PID_TELETEXT_BASE 0x2000
|
||||
|
||||
#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 {
|
||||
|
||||
LIST_ENTRY(service) s_hash_link;
|
||||
idnode_t s_id;
|
||||
|
||||
enum {
|
||||
/**
|
||||
|
@ -305,16 +304,13 @@ typedef struct service {
|
|||
|
||||
void (*s_dtor)(struct service *t);
|
||||
|
||||
htsmsg_t *(*s_serialize)(struct service *s, int full);
|
||||
|
||||
/*
|
||||
* Per source type structs
|
||||
*/
|
||||
struct dvb_mux *s_dvb_mux;
|
||||
|
||||
/**
|
||||
* Unique identifer
|
||||
*/
|
||||
char *s_uuid;
|
||||
|
||||
/**
|
||||
* Name usable for displaying to user
|
||||
*/
|
||||
|
|
|
@ -401,8 +401,8 @@ streaming_code2txt(int code)
|
|||
case SM_CODE_SUBSCRIPTION_OVERRIDDEN:
|
||||
return "Subscription overridden";
|
||||
|
||||
case SM_CODE_NO_HW_ATTACHED:
|
||||
return "No hardware present";
|
||||
case SM_CODE_NO_FREE_ADAPTER:
|
||||
return "No free adapter";
|
||||
case SM_CODE_MUX_NOT_ENABLED:
|
||||
return "Mux not enabled";
|
||||
case SM_CODE_NOT_FREE:
|
||||
|
|
|
@ -284,7 +284,7 @@ typedef enum {
|
|||
#define SM_CODE_SOURCE_DELETED 102
|
||||
#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_NOT_FREE 202
|
||||
#define SM_CODE_TUNING_FAILED 203
|
||||
|
|
|
@ -1669,7 +1669,7 @@ build_record_iptv(service_t *t)
|
|||
htsmsg_t *r = htsmsg_create_map();
|
||||
char abuf[INET_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, "interface", t->s_iptv_iface ?: "");
|
||||
|
@ -1828,7 +1828,7 @@ extjs_tvadapter(http_connection_t *hc, const char *remain, void *opaque)
|
|||
array = htsmsg_create_list();
|
||||
|
||||
#if ENABLE_LINUXDVB
|
||||
// extjs_list_dvb_adapters(array);
|
||||
extjs_list_dvb_adapters(array);
|
||||
#endif
|
||||
|
||||
#if ENABLE_V4L
|
||||
|
|
|
@ -43,7 +43,6 @@
|
|||
#include "dvb/dvb_preconf.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)
|
||||
return HTTP_STATUS_BAD_REQUEST;
|
||||
|
||||
|
||||
pthread_mutex_lock(&global_lock);
|
||||
|
||||
if(http_access_verify(hc, ACCESS_ADMIN)) {
|
||||
|
@ -85,6 +84,7 @@ extjs_dvblocations(http_connection_t *hc, const char *remain, void *opaque)
|
|||
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 *sibling = http_arg_get(&hc->hc_req_args, "sibling");
|
||||
const char *s;
|
||||
th_dvb_mux_instance_t *tdmi;
|
||||
service_t *t;
|
||||
|
||||
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, "device", tda->tda_rootpath ?: "No hardware attached");
|
||||
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, "idleclose", tda->tda_idleclose);
|
||||
htsmsg_add_u32(r, "skip_checksubscr", tda->tda_skip_checksubscr);
|
||||
htsmsg_add_u32(r, "qmon", tda->tda_qmon);
|
||||
htsmsg_add_u32(r, "poweroff", tda->tda_poweroff);
|
||||
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_str(r, "diseqcversion",
|
||||
((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)
|
||||
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");
|
||||
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");
|
||||
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");
|
||||
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(!strcmp(s, "DiSEqC 1.0 / 2.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");
|
||||
|
||||
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();
|
||||
htsmsg_add_u32(out, "success", 1);
|
||||
|
||||
#if 0
|
||||
} else if(!strcmp(op, "serviceprobe")) {
|
||||
|
||||
tvhlog(LOG_NOTICE, "web interface",
|
||||
|
@ -251,6 +237,7 @@ extjs_dvbadapter(http_connection_t *hc, const char *remain, void *opaque)
|
|||
|
||||
out = htsmsg_create_map();
|
||||
htsmsg_add_u32(out, "success", 1);
|
||||
#endif
|
||||
|
||||
} else {
|
||||
pthread_mutex_unlock(&global_lock);
|
||||
|
@ -265,6 +252,7 @@ extjs_dvbadapter(http_connection_t *hc, const char *remain, void *opaque)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -678,6 +666,8 @@ extjs_dvb_copymux(http_connection_t *hc, const char *remain, void *opaque)
|
|||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
@ -689,7 +679,6 @@ extjs_list_dvb_adapters(htsmsg_t *array)
|
|||
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;
|
||||
}
|
||||
|
||||
printf("s=%s\n", s);
|
||||
|
||||
out = htsmsg_create_list();
|
||||
if(!strcmp(s, "root")) {
|
||||
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);
|
||||
idnode_t **v;
|
||||
|
||||
n = htsmsg_create_map();
|
||||
htsmsg_add_str(n, "text", "Network2");
|
||||
htsmsg_add_str(n, "id", "net/2");
|
||||
htsmsg_add_str(n, "cls", "folder");
|
||||
htsmsg_add_msg(out, NULL, n);
|
||||
if(!strcmp(s, "root")) {
|
||||
v = dvb_network_root();
|
||||
} else {
|
||||
idnode_t *n = idnode_find(s);
|
||||
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);
|
||||
|
||||
free(v);
|
||||
|
||||
htsmsg_json_serialize(out, hq, 0);
|
||||
htsmsg_destroy(out);
|
||||
http_output_content(hc, "text/x-json; charset=UTF-8");
|
||||
|
@ -748,14 +739,14 @@ extjs_start_dvb(void)
|
|||
{
|
||||
http_path_add("/dvb/networks",
|
||||
NULL, extjs_dvbnetworks, ACCESS_WEB_INTERFACE);
|
||||
#if 0
|
||||
http_path_add("/dvb/locations",
|
||||
NULL, extjs_dvblocations, ACCESS_WEB_INTERFACE);
|
||||
|
||||
|
||||
http_path_add("/dvb/adapter",
|
||||
NULL, extjs_dvbadapter, ACCESS_ADMIN);
|
||||
|
||||
#if 0
|
||||
|
||||
http_path_add("/dvb/muxes",
|
||||
NULL, extjs_dvbmuxes, ACCESS_ADMIN);
|
||||
|
||||
|
|
25
src/webui/static/app/dvb_networks.js
Normal file
25
src/webui/static/app/dvb_networks.js
Normal 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;
|
||||
}
|
|
@ -606,7 +606,7 @@ http_stream_tdmi(http_connection_t *hc, th_dvb_mux_instance_t *tdmi)
|
|||
streaming_queue_init(&sq, SMT_PACKET);
|
||||
|
||||
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);
|
||||
http_stream_run(hc, &sq, name, MC_PASS);
|
||||
pthread_mutex_lock(&global_lock);
|
||||
|
|
Loading…
Add table
Reference in a new issue