Moved almost everything out from tdmi

This commit is contained in:
Andreas Öman 2012-12-07 13:43:32 +01:00
parent f991e1376e
commit 963a0502d3
29 changed files with 624 additions and 770 deletions

View file

@ -629,7 +629,7 @@ capmt_table_input(struct th_descrambler *td, struct service *t,
{
capmt_service_t *ct = (capmt_service_t *)td;
capmt_t *capmt = ct->ct_capmt;
int adapter_num = t->s_dvb_mux_instance->tdmi_adapter->tda_adapter_num;
int adapter_num = t->s_dvb_mux->dm_current_tdmi->tdmi_adapter->tda_adapter_num;
int total_caids = 0, current_caid = 0;
int i;
@ -893,7 +893,7 @@ capmt_service_start(service_t *t)
tvhlog(LOG_INFO, "capmt",
"Starting capmt server for service \"%s\" on tuner %d",
t->s_svcname,
t->s_dvb_mux_instance->tdmi_adapter->tda_adapter_num);
t->s_dvb_mux->dm_current_tdmi->tdmi_adapter->tda_adapter_num);
elementary_stream_t *st;

View file

@ -41,6 +41,7 @@ LIST_HEAD(th_dvb_mux_instance_list, th_dvb_mux_instance);
TAILQ_HEAD(dvb_satconf_queue, dvb_satconf);
LIST_HEAD(dvb_mux_list, dvb_mux);
TAILQ_HEAD(dvb_mux_queue, dvb_mux);
LIST_HEAD(dvb_network_list, dvb_network);
/**
* Satconf
@ -89,7 +90,7 @@ typedef struct dvb_mux_conf {
*/
typedef struct dvb_network {
struct th_dvb_mux_instance_list dn_mux_instances; // Should go away
LIST_ENTRY(dvb_network) dn_global_link;
struct dvb_mux_queue dn_initial_scan_queue;
int dn_initial_num_mux;
@ -102,6 +103,12 @@ typedef struct dvb_network {
gtimer_t dn_mux_scanner_timer;
uint32_t dn_disable_pmt_monitor;
uint32_t dn_autodiscovery;
uint32_t dn_nitoid;
char *dn_uuid;
} dvb_network_t;
@ -125,8 +132,6 @@ typedef struct dvb_mux {
TAILQ_HEAD(, epggrab_ota_mux) dm_epg_grab;
struct th_dvb_mux_instance *dm_tdmi; // wrong
TAILQ_ENTRY(dvb_mux) dm_scan_link;
struct dvb_mux_queue *dm_scan_queue;
@ -138,6 +143,15 @@ typedef struct dvb_mux {
struct th_dvb_mux_instance *dm_current_tdmi;
struct th_dvb_mux_instance_list dm_tdmis;
// Derived from dm_conf (more or less)
char *dm_local_identifier;
char *dm_uuid;
int dm_enabled;
} dvb_mux_t;
@ -149,12 +163,11 @@ typedef struct dvb_mux {
typedef struct th_dvb_mux_instance {
dvb_mux_t *tdmi_mux;
RB_ENTRY(th_dvb_mux_instance) tdmi_global_link;
LIST_ENTRY(th_dvb_mux_instance) tdmi_adapter_link; // wrong
LIST_ENTRY(th_dvb_mux_instance) tdmi_mux_link;
struct th_dvb_adapter *tdmi_adapter;
LIST_ENTRY(th_dvb_mux_instance) tdmi_adapter_link;
uint16_t tdmi_snr, tdmi_signal;
uint32_t tdmi_ber, tdmi_unc;
@ -177,10 +190,8 @@ typedef struct th_dvb_mux_instance {
int tdmi_quality;
int tdmi_enabled;
char *tdmi_identifier;
int tdmi_tune_failed; // Adapter failed to tune this frequency
// Don't try again
struct th_subscription_list tdmi_subscriptions;
@ -216,6 +227,8 @@ typedef struct th_dvb_adapter {
dvb_network_t *tda_dn;
struct th_dvb_mux_instance_list tda_tdmis;
th_dvb_mux_instance_t *tda_current_tdmi;
char *tda_tune_reason; // Reason for last tune
@ -223,17 +236,14 @@ typedef struct th_dvb_adapter {
const char *tda_rootpath;
char *tda_identifier;
uint32_t tda_autodiscovery;
uint32_t tda_idleclose;
uint32_t tda_skip_initialscan;
uint32_t tda_skip_checksubscr;
uint32_t tda_qmon;
uint32_t tda_poweroff;
uint32_t tda_sidtochan;
uint32_t tda_nitoid;
uint32_t tda_diseqc_version;
uint32_t tda_diseqc_repeats;
uint32_t tda_disable_pmt_monitor;
int32_t tda_full_mux_rx;
char *tda_displayname;
@ -340,8 +350,9 @@ typedef struct th_dvb_table {
} th_dvb_table_t;
extern struct dvb_network_list dvb_networks;
extern struct th_dvb_adapter_queue dvb_adapters;
extern struct th_dvb_mux_instance_tree dvb_muxes;
//extern struct th_dvb_mux_instance_tree dvb_muxes;
void dvb_init(uint32_t adapter_mask, const char *rawfile);
@ -418,17 +429,17 @@ int dvb_mux_str2mode(const char *str);
int dvb_mux_str2guard(const char *str);
int dvb_mux_str2hier(const char *str);
void dvb_mux_save(th_dvb_mux_instance_t *tdmi);
void dvb_mux_save(dvb_mux_t *dm);
void dvb_mux_load(th_dvb_adapter_t *tda);
void dvb_mux_load(dvb_network_t *dn);
void dvb_mux_destroy(th_dvb_mux_instance_t *tdmi);
void dvb_mux_destroy(dvb_mux_t *dm);
th_dvb_mux_instance_t *dvb_mux_create(th_dvb_adapter_t *tda,
const struct dvb_mux_conf *dmc,
uint16_t onid, uint16_t tsid, const char *network,
const char *logprefix, int enabled,
int initialscan, const char *identifier);
dvb_mux_t *dvb_mux_create(dvb_network_t *tda,
const struct dvb_mux_conf *dmc,
uint16_t onid, uint16_t tsid, const char *network,
const char *logprefix, int enabled,
int initialscan, const char *uuid);
void dvb_mux_set_networkname(dvb_mux_t *dm, const char *name);
@ -441,11 +452,11 @@ void dvb_mux_set_enable(th_dvb_mux_instance_t *tdmi, int enabled);
void dvb_mux_set_satconf(th_dvb_mux_instance_t *tdmi, const char *scid,
int save);
htsmsg_t *dvb_mux_build_msg(th_dvb_mux_instance_t *tdmi);
htsmsg_t *dvb_mux_build_msg(dvb_mux_t *dm);
void dvb_mux_notify(th_dvb_mux_instance_t *tdmi);
void dvb_mux_notify(dvb_mux_t *dm);
const char *dvb_mux_add_by_params(th_dvb_adapter_t *tda,
const char *dvb_mux_add_by_params(dvb_network_t *dn,
int freq,
int symrate,
int bw,
@ -464,27 +475,33 @@ int dvb_mux_copy(th_dvb_adapter_t *dst, th_dvb_mux_instance_t *tdmi_src,
dvb_satconf_t *satconf);
#endif
th_dvb_mux_instance_t *dvb_mux_find
(th_dvb_adapter_t *tda, const char *netname, uint16_t onid, uint16_t tsid,
int enabled );
dvb_mux_t *dvb_mux_find(dvb_network_t *dn, const char *netname, uint16_t onid,
uint16_t tsid, int enabled);
/**
* DVB Transport (aka DVB service)
*/
void dvb_service_load(th_dvb_mux_instance_t *tdmi, const char *tdmi_identifier);
void dvb_tdmi_destroy(th_dvb_mux_instance_t *tdmi);
struct service *dvb_service_find(th_dvb_mux_instance_t *tdmi,
uint16_t sid, int pmt_pid,
const char *identifier);
/**
* DVB Transport (aka DVB service)
*/
void dvb_service_load(dvb_mux_t *dm);
struct service *dvb_service_find2(th_dvb_mux_instance_t *tdmi,
uint16_t sid, int pmt_pid,
const char *identifier, int *save);
struct service *dvb_service_find(dvb_mux_t *dm,
uint16_t sid, int pmt_pid,
const char *identifier);
struct service *dvb_service_find3
(th_dvb_adapter_t *tda, th_dvb_mux_instance_t *tdmi,
const char *netname, uint16_t onid, uint16_t tsid, uint16_t sid,
int enabled, int epgprimary);
struct service *dvb_service_find2(dvb_mux_t *dm,
uint16_t sid, int pmt_pid,
const char *identifier, int *save);
struct service *dvb_service_find3(dvb_network_t *dn,
dvb_mux_t *dm,
const char *netname, uint16_t onid,
uint16_t tsid, uint16_t sid,
int enabled, int epgprimary);
void dvb_service_notify(struct service *t);

View file

@ -76,18 +76,15 @@ tda_save(th_dvb_adapter_t *tda)
htsmsg_add_str(m, "type", dvb_adaptertype_to_str(tda->tda_fe_type));
htsmsg_add_str(m, "displayname", tda->tda_displayname);
htsmsg_add_u32(m, "autodiscovery", tda->tda_autodiscovery);
htsmsg_add_u32(m, "idleclose", tda->tda_idleclose);
htsmsg_add_u32(m, "skip_checksubscr", tda->tda_skip_checksubscr);
htsmsg_add_u32(m, "sidtochan", tda->tda_sidtochan);
htsmsg_add_u32(m, "qmon", tda->tda_qmon);
htsmsg_add_u32(m, "poweroff", tda->tda_poweroff);
htsmsg_add_u32(m, "nitoid", tda->tda_nitoid);
htsmsg_add_u32(m, "diseqc_version", tda->tda_diseqc_version);
htsmsg_add_u32(m, "diseqc_repeats", tda->tda_diseqc_repeats);
htsmsg_add_u32(m, "extrapriority", tda->tda_extrapriority);
htsmsg_add_u32(m, "skip_initialscan", tda->tda_skip_initialscan);
htsmsg_add_u32(m, "disable_pmt_monitor", tda->tda_disable_pmt_monitor);
htsmsg_add_s32(m, "full_mux_rx", tda->tda_full_mux_rx);
hts_settings_save(m, "dvbadapters/%s", tda->tda_identifier);
htsmsg_destroy(m);
@ -117,25 +114,6 @@ dvb_adapter_set_displayname(th_dvb_adapter_t *tda, const char *s)
}
/**
*
*/
void
dvb_adapter_set_auto_discovery(th_dvb_adapter_t *tda, int on)
{
if(tda->tda_autodiscovery == on)
return;
lock_assert(&global_lock);
tvhlog(LOG_NOTICE, "dvb", "Adapter \"%s\" mux autodiscovery set to: %s",
tda->tda_displayname, on ? "On" : "Off");
tda->tda_autodiscovery = on;
tda_save(tda);
}
/**
*
*/
@ -247,26 +225,6 @@ dvb_adapter_set_poweroff(th_dvb_adapter_t *tda, int on)
}
/**
*
*/
void
dvb_adapter_set_nitoid(th_dvb_adapter_t *tda, int nitoid)
{
lock_assert(&global_lock);
if(tda->tda_nitoid == nitoid)
return;
tvhlog(LOG_NOTICE, "dvb", "NIT-o network id \"%d\" changed to \"%d\"",
tda->tda_nitoid, nitoid);
tda->tda_nitoid = nitoid;
tda_save(tda);
}
/**
*
@ -322,25 +280,6 @@ dvb_adapter_set_extrapriority(th_dvb_adapter_t *tda, int extrapriority)
tda_save(tda);
}
/**
*
*/
void
dvb_adapter_set_disable_pmt_monitor(th_dvb_adapter_t *tda, int on)
{
if(tda->tda_disable_pmt_monitor == on)
return;
lock_assert(&global_lock);
tvhlog(LOG_NOTICE, "dvb", "Adapter \"%s\" disabled PMT monitoring set to: %s",
tda->tda_displayname, on ? "On" : "Off");
tda->tda_disable_pmt_monitor = on;
tda_save(tda);
}
/**
*
*/
@ -475,8 +414,6 @@ tda_add(int adapter_num)
tda->tda_identifier = strdup(buf);
tda->tda_autodiscovery = tda->tda_fe_type != FE_QPSK;
tda->tda_sat = tda->tda_fe_type == FE_QPSK;
/* Come up with an initial displayname, user can change it and it will
@ -521,11 +458,7 @@ tda_add_from_file(const char *filename)
buf[i] = '_';
tda->tda_identifier = strdup(buf);
tda->tda_autodiscovery = 0;
tda->tda_sat = 0;
tda->tda_full_mux_rx = 1;
/* Come up with an initial displayname, user can change it and it will
@ -661,18 +594,15 @@ dvb_adapter_init(uint32_t adapter_mask, const char *rawfile)
free(tda->tda_displayname);
tda->tda_displayname = strdup(name);
htsmsg_get_u32(c, "autodiscovery", &tda->tda_autodiscovery);
htsmsg_get_u32(c, "idleclose", &tda->tda_idleclose);
htsmsg_get_u32(c, "skip_checksubscr", &tda->tda_skip_checksubscr);
htsmsg_get_u32(c, "sidtochan", &tda->tda_sidtochan);
htsmsg_get_u32(c, "qmon", &tda->tda_qmon);
htsmsg_get_u32(c, "poweroff", &tda->tda_poweroff);
htsmsg_get_u32(c, "nitoid", &tda->tda_nitoid);
htsmsg_get_u32(c, "diseqc_version", &tda->tda_diseqc_version);
htsmsg_get_u32(c, "diseqc_repeats", &tda->tda_diseqc_repeats);
htsmsg_get_u32(c, "extrapriority", &tda->tda_extrapriority);
htsmsg_get_u32(c, "skip_initialscan", &tda->tda_skip_initialscan);
htsmsg_get_u32(c, "disable_pmt_monitor", &tda->tda_disable_pmt_monitor);
if (htsmsg_get_s32(c, "full_mux_rx", &tda->tda_full_mux_rx))
if (!htsmsg_get_u32(c, "disable_full_mux_rx", &u32) && u32)
tda->tda_full_mux_rx = 0;
@ -685,8 +615,6 @@ dvb_adapter_init(uint32_t adapter_mask, const char *rawfile)
if(tda->tda_sat)
dvb_satconf_init(tda);
dvb_mux_load(tda);
}
}
@ -776,6 +704,7 @@ dvb_adapter_clone(th_dvb_adapter_t *dst, th_dvb_adapter_t *src)
/**
*
*/
#if 0
int
dvb_adapter_destroy(th_dvb_adapter_t *tda)
{
@ -788,8 +717,8 @@ dvb_adapter_destroy(th_dvb_adapter_t *tda)
hts_settings_remove("dvbadapters/%s", tda->tda_identifier);
while((tdmi = LIST_FIRST(&tda->tda_dn->dn_mux_instances)) != NULL)
dvb_mux_destroy(tdmi);
while((tdmi = LIST_FIRST(&tda->tda_tdmis)) != NULL)
dvb_tdmi_destroy(tdmi);
TAILQ_REMOVE(&dvb_adapters, tda, tda_global_link);
@ -801,6 +730,7 @@ dvb_adapter_destroy(th_dvb_adapter_t *tda)
return 0;
}
#endif
/**
@ -940,8 +870,7 @@ dvb_adapter_input_dvr(void *aux)
}
} else {
LIST_FOREACH(t, &tda->tda_transports, s_active_link)
if(t->s_dvb_mux_instance == tda->tda_current_tdmi)
ts_recv_packet1(t, tsb + i, NULL);
ts_recv_packet1(t, tsb + i, NULL);
}
i += 188;
@ -981,33 +910,17 @@ dvb_adapter_build_msg(th_dvb_adapter_t *tda)
{
char buf[100];
htsmsg_t *m = htsmsg_create_map();
th_dvb_mux_instance_t *tdmi;
service_t *t;
int nummux = 0;
int numsvc = 0;
int fdiv;
htsmsg_add_str(m, "identifier", tda->tda_identifier);
htsmsg_add_str(m, "name", tda->tda_displayname);
// XXX: bad bad bad slow slow slow
LIST_FOREACH(tdmi, &tda->tda_dn->dn_mux_instances, tdmi_adapter_link) {
nummux++;
LIST_FOREACH(t, &tdmi->tdmi_mux->dm_services, s_group_link) {
numsvc++;
}
}
htsmsg_add_str(m, "type", "dvb");
htsmsg_add_u32(m, "services", numsvc);
htsmsg_add_u32(m, "muxes", nummux);
htsmsg_add_u32(m, "initialMuxes", tda->tda_dn->dn_initial_num_mux);
if(tda->tda_current_tdmi != NULL) {
th_dvb_mux_instance_t *tdmi = tda->tda_current_tdmi;
dvb_mux_nicename(buf, sizeof(buf), tda->tda_current_tdmi);
dvb_mux_nicename(buf, sizeof(buf), tda->tda_current_tdmi->tdmi_mux);
htsmsg_add_str(m, "currentMux", buf);
htsmsg_add_u32(m, "signal", MIN(tdmi->tdmi_signal * 100 / 65535, 100));

View file

@ -97,7 +97,6 @@ dvb_fe_monitor(void *aux)
streaming_message_t sm;
struct service *t;
int store = 0;
int notify = 0;
gtimer_arm(&tda->tda_fe_monitor_timer, dvb_fe_monitor, tda, 1);
@ -191,11 +190,10 @@ dvb_fe_monitor(void *aux)
if(status != tdmi->tdmi_fe_status) {
tdmi->tdmi_fe_status = status;
dvb_mux_nicename(buf, sizeof(buf), tdmi);
dvb_mux_nicename(buf, sizeof(buf), tdmi->tdmi_mux);
tvhlog(LOG_DEBUG,
"dvb", "\"%s\" on adapter \"%s\", status changed to %s",
buf, tda->tda_displayname, dvb_mux_status(tdmi));
store = 1;
notify = 1;
}
@ -208,12 +206,13 @@ dvb_fe_monitor(void *aux)
}
if(q != tdmi->tdmi_quality) {
tdmi->tdmi_quality = q;
store = 1;
notify = 1;
}
}
if(notify) {
#if 0 // XXX(dvbreorg)
htsmsg_t *m = htsmsg_create_map();
htsmsg_add_str(m, "id", tdmi->tdmi_identifier);
htsmsg_add_u32(m, "quality", tdmi->tdmi_quality);
@ -222,8 +221,9 @@ dvb_fe_monitor(void *aux)
htsmsg_add_u32(m, "ber", tdmi->tdmi_ber);
htsmsg_add_u32(m, "unc", tdmi->tdmi_unc);
notify_by_msg("dvbMux", m);
#endif
m = htsmsg_create_map();
htsmsg_t *m = htsmsg_create_map();
htsmsg_add_str(m, "identifier", tda->tda_identifier);
htsmsg_add_u32(m, "signal", MIN(tdmi->tdmi_signal * 100 / 65535, 100));
htsmsg_add_u32(m, "snr", tdmi->tdmi_snr);
@ -233,8 +233,10 @@ dvb_fe_monitor(void *aux)
notify_by_msg("tvAdapter", m);
}
#if 0 // XXX(dvbreorg)
if(store)
dvb_mux_save(tdmi);
#endif
/* Streaming message */
sigstat.status_text = dvb_mux_status(tdmi);
@ -244,14 +246,11 @@ dvb_fe_monitor(void *aux)
sigstat.unc = tdmi->tdmi_unc;
sm.sm_type = SMT_SIGNAL_STATUS;
sm.sm_data = &sigstat;
LIST_FOREACH(t, &tda->tda_transports, s_active_link)
if(t->s_dvb_mux_instance == tda->tda_current_tdmi &&
t->s_status == SERVICE_RUNNING ) {
pthread_mutex_lock(&t->s_stream_mutex);
streaming_pad_deliver(&t->s_streaming_pad, &sm);
pthread_mutex_unlock(&t->s_stream_mutex);
}
LIST_FOREACH(t, &tda->tda_transports, s_active_link) {
pthread_mutex_lock(&t->s_stream_mutex);
streaming_pad_deliver(&t->s_streaming_pad, &sm);
pthread_mutex_unlock(&t->s_stream_mutex);
}
}
@ -270,7 +269,7 @@ dvb_fe_stop(th_dvb_adapter_t *tda, int retune)
if(dm->dm_table_initial) {
dm->dm_table_initial = 0;
dm->dm_dn->dn_initial_num_mux--;
dvb_mux_save(dm->dm_tdmi);
dvb_mux_save(dm);
}
dvb_table_flush_all(dm);
@ -395,10 +394,10 @@ dvb_fe_tune_s2(th_dvb_mux_instance_t *tdmi, dvb_mux_conf_t *dmc)
int
dvb_fe_tune(dvb_mux_t *dm, const char *reason)
{
th_dvb_adapter_t *tda = dm->dm_tdmi->tdmi_adapter;
dvb_network_t *dn = dm->dm_dn;
th_dvb_mux_instance_t *tdmi = dm->dm_tdmi;
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;
@ -475,7 +474,7 @@ dvb_fe_tune(dvb_mux_t *dm, const char *reason)
tvhlog(LOG_ERR, "dvb", "diseqc setup failed %d\n", r);
}
dvb_mux_nicename(buf, sizeof(buf), tdmi);
dvb_mux_nicename(buf, sizeof(buf), tdmi->tdmi_mux);
tda->tda_fe_monitor_hold = 4;
@ -507,9 +506,9 @@ dvb_fe_tune(dvb_mux_t *dm, const char *reason)
}
/* Mark as bad */
dvb_mux_set_enable(tdmi, 0);
tdmi->tdmi_tune_failed = 1;
return SM_CODE_TUNING_FAILED;
}
}
tda->tda_current_tdmi = tdmi;

View file

@ -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_identifier, tda->tda_demux_path,
s->s_uuid, 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_identifier, tda->tda_demux_path,
s->s_uuid, tda->tda_demux_path,
st->es_pid, strerror(errno));
close(fd);
fd = -1;

View file

@ -58,9 +58,6 @@ static struct strtab muxfestatustab[] = {
{ "OK", TDMI_FE_OK },
};
static void tdmi_set_enable(th_dvb_mux_instance_t *tdmi, int enabled);
/**
*
*/
@ -87,18 +84,8 @@ dvb_mux_status(th_dvb_mux_instance_t *tdmi)
*
*/
static int
tdmi_global_cmp(th_dvb_mux_instance_t *a, th_dvb_mux_instance_t *b)
{
return strcmp(a->tdmi_identifier, b->tdmi_identifier);
}
/**
*
*/
static int
tdmi_compare_key(const struct dvb_mux_conf *a,
const struct dvb_mux_conf *b)
dmc_compare_key(const struct dvb_mux_conf *a,
const struct dvb_mux_conf *b)
{
int32_t fd = (int32_t)a->dmc_fe_params.frequency
- (int32_t)b->dmc_fe_params.frequency;
@ -112,9 +99,9 @@ tdmi_compare_key(const struct dvb_mux_conf *a,
* Return 0 if configuration does not differ. return 1 if it does
*/
static int
tdmi_compare_conf(int adapter_type,
const struct dvb_mux_conf *a,
const struct dvb_mux_conf *b)
dcm_compare_conf(int adapter_type,
const struct dvb_mux_conf *a,
const struct dvb_mux_conf *b)
{
switch(adapter_type) {
case FE_OFDM:
@ -146,60 +133,60 @@ tdmi_compare_conf(int adapter_type,
/**
* Create a new mux on the given adapter, return NULL if it already exists
*/
th_dvb_mux_instance_t *
dvb_mux_create(th_dvb_adapter_t *tda, const struct dvb_mux_conf *dmc,
uint16_t onid, uint16_t tsid, const char *network, const char *source,
int enabled, int initialscan, const char *identifier)
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 *uuid)
{
dvb_network_t *dn = tda->tda_dn;
th_dvb_mux_instance_t *tdmi, *c;
char buf[200];
dvb_mux_t *dm;
lock_assert(&global_lock);
/* HACK - we hash/compare based on 2KHz spacing and compare on +/-500Hz */
LIST_FOREACH(tdmi, &tda->tda_dn->dn_mux_instances, tdmi_adapter_link) {
if(tdmi_compare_key(&tdmi->tdmi_mux->dm_conf, dmc))
LIST_FOREACH(dm, &dn->dn_muxes, dm_network_link) {
if(dmc_compare_key(&dm->dm_conf, dmc))
break; /* Mux already exist */
}
if(tdmi != NULL) {
if(dm != NULL) {
/* Update stuff ... */
int save = 0;
char buf2[1024];
buf2[0] = 0;
if(tdmi_compare_conf(tda->tda_fe_type, &tdmi->tdmi_mux->dm_conf, dmc)) {
if(dcm_compare_conf(dn->dn_fe_type, &dm->dm_conf, dmc)) {
#if DVB_API_VERSION >= 5
snprintf(buf2, sizeof(buf2), " (");
if (tdmi->tdmi_mux->dm_conf.dmc_fe_modulation != dmc->dmc_fe_modulation)
if (dm->dm_conf.dmc_fe_modulation != dmc->dmc_fe_modulation)
sprintf(buf2, "%s %s->%s, ", buf2,
dvb_mux_qam2str(tdmi->tdmi_mux->dm_conf.dmc_fe_modulation),
dvb_mux_qam2str(dm->dm_conf.dmc_fe_modulation),
dvb_mux_qam2str(dmc->dmc_fe_modulation));
if (tdmi->tdmi_mux->dm_conf.dmc_fe_delsys != dmc->dmc_fe_delsys)
if (dm->dm_conf.dmc_fe_delsys != dmc->dmc_fe_delsys)
sprintf(buf2, "%s %s->%s, ", buf2,
dvb_mux_delsys2str(tdmi->tdmi_mux->dm_conf.dmc_fe_delsys),
dvb_mux_delsys2str(dm->dm_conf.dmc_fe_delsys),
dvb_mux_delsys2str(dmc->dmc_fe_delsys));
if (tdmi->tdmi_mux->dm_conf.dmc_fe_rolloff != dmc->dmc_fe_rolloff)
if (dm->dm_conf.dmc_fe_rolloff != dmc->dmc_fe_rolloff)
sprintf(buf2, "%s %s->%s, ", buf2,
dvb_mux_rolloff2str(tdmi->tdmi_mux->dm_conf.dmc_fe_rolloff),
dvb_mux_rolloff2str(dm->dm_conf.dmc_fe_rolloff),
dvb_mux_rolloff2str(dmc->dmc_fe_rolloff));
sprintf(buf2, "%s)", buf2);
#endif
memcpy(&tdmi->tdmi_mux->dm_conf, dmc, sizeof(struct dvb_mux_conf));
memcpy(&dm->dm_conf, dmc, sizeof(struct dvb_mux_conf));
save = 1;
}
if(tsid != 0xFFFF && tdmi->tdmi_mux->dm_transport_stream_id != tsid) {
tdmi->tdmi_mux->dm_transport_stream_id = tsid;
if(tsid != 0xFFFF && dm->dm_transport_stream_id != tsid) {
dm->dm_transport_stream_id = tsid;
save = 1;
}
if(onid && tdmi->tdmi_mux->dm_network_id != onid) {
tdmi->tdmi_mux->dm_network_id = onid;
if(onid && dm->dm_network_id != onid) {
dm->dm_network_id = onid;
save = 1;
}
#if 0 // XXX(dvbreorg)
/* HACK - load old transports and remove old mux config */
if(identifier) {
save = 1;
@ -207,20 +194,22 @@ dvb_mux_create(th_dvb_adapter_t *tda, const struct dvb_mux_conf *dmc,
hts_settings_remove("dvbmuxes/%s/%s",
tda->tda_identifier, identifier);
}
#endif
if(save) {
dvb_mux_save(tdmi);
dvb_mux_nicename(buf, sizeof(buf), tdmi);
char buf[128];
dvb_mux_save(dm);
dvb_mux_nicename(buf, sizeof(buf), dm);
tvhlog(LOG_DEBUG, "dvb",
"Configuration for mux \"%s\" updated by %s%s",
buf, source, buf2);
dvb_mux_notify(tdmi);
dvb_mux_notify(dm);
}
return NULL;
}
dvb_mux_t *dm = calloc(1, sizeof(dvb_mux_t));
dm = calloc(1, sizeof(dvb_mux_t));
dm->dm_network_id = onid;
dm->dm_transport_stream_id = tsid;
@ -228,103 +217,67 @@ dvb_mux_create(th_dvb_adapter_t *tda, const struct dvb_mux_conf *dmc,
TAILQ_INIT(&dm->dm_epg_grab);
TAILQ_INIT(&dm->dm_table_queue);
dm->dm_dn = tda->tda_dn;
LIST_INSERT_HEAD(&tda->tda_dn->dn_muxes, dm, dm_network_link);
dm->dm_dn = dn;
LIST_INSERT_HEAD(&dn->dn_muxes, dm, dm_network_link);
tdmi = calloc(1, sizeof(th_dvb_mux_instance_t));
tdmi->tdmi_mux = dm;
dm->dm_tdmi = tdmi;
char identifier[128];
snprintf(identifier, sizeof(identifier),
"%d%s", dmc->dmc_fe_params.frequency,
dn->dn_fe_type == FE_QPSK ?
dvb_polarisation_to_str(dmc->dmc_polarisation) : "");
dm->dm_local_identifier = strdup(identifier);
if(identifier == NULL) {
char qpsktxt[20];
if(tda->tda_sat)
snprintf(qpsktxt, sizeof(qpsktxt), "_%s",
dvb_polarisation_to_str(dmc->dmc_polarisation));
else
qpsktxt[0] = 0;
snprintf(buf, sizeof(buf), "%s%d%s",
tda->tda_identifier, dmc->dmc_fe_params.frequency, qpsktxt);
tdmi->tdmi_identifier = strdup(buf);
} else {
tdmi->tdmi_identifier = strdup(identifier);
}
dm->dm_enabled = enabled;
c = RB_INSERT_SORTED(&dvb_muxes, tdmi, tdmi_global_link, tdmi_global_cmp);
memcpy(&dm->dm_conf, dmc, sizeof(struct dvb_mux_conf));
if(c != NULL) {
/* Global identifier collision, not good, not good at all */
tvhlog(LOG_ERR, "dvb",
"Multiple DVB multiplexes with same identifier \"%s\" "
"one is skipped", tdmi->tdmi_identifier);
free(tdmi->tdmi_identifier);
free(tdmi);
return NULL;
}
tdmi->tdmi_enabled = enabled;
tdmi->tdmi_adapter = tda;
tdmi->tdmi_quality = 100;
memcpy(&tdmi->tdmi_mux->dm_conf, dmc, sizeof(struct dvb_mux_conf));
LIST_INSERT_HEAD(&tda->tda_dn->dn_mux_instances, tdmi, tdmi_adapter_link);
dm->dm_table_initial = initialscan;
if(source != NULL) {
dvb_mux_nicename(buf, sizeof(buf), tdmi);
char buf[128];
dvb_mux_nicename(buf, sizeof(buf), dm);
tvhlog(LOG_NOTICE, "dvb", "New mux \"%s\" created by %s", buf, source);
dvb_mux_save(tdmi);
dvb_adapter_notify(tda);
dvb_mux_save(dm);
}
dvb_service_load(tdmi, identifier);
dvb_mux_notify(tdmi);
dvb_service_load(dm);
if(enabled && dm->dm_table_initial) {
dn->dn_initial_num_mux++;
mux_link_initial(dn, dm);
}
return tdmi;
return dm;
}
/**
*
*/
void
dvb_tdmi_destroy(th_dvb_mux_instance_t *tdmi)
{
LIST_REMOVE(tdmi, tdmi_mux_link);
LIST_REMOVE(tdmi, tdmi_adapter_link);
free(tdmi);
}
/**
* Destroy a DVB mux (it might come back by itself very soon though :)
*/
void
dvb_mux_destroy(th_dvb_mux_instance_t *tdmi)
dvb_mux_destroy(dvb_mux_t *dm)
{
th_dvb_adapter_t *tda = tdmi->tdmi_adapter;
dvb_mux_t *dm = tdmi->tdmi_mux;
service_t *t;
th_dvb_mux_instance_t *tdmi;
lock_assert(&global_lock);
hts_settings_remove("dvbmuxes/%s/%s",
tda->tda_identifier, tdmi->tdmi_identifier);
while((t = LIST_FIRST(&tdmi->tdmi_mux->dm_services)) != NULL) {
hts_settings_remove("dvbtransports/%s/%s",
t->s_dvb_mux_instance->tdmi_identifier,
t->s_identifier);
service_destroy(t);
}
LIST_REMOVE(dm, dm_network_link);
dvb_service_notify_by_adapter(tda);
if(tda->tda_current_tdmi == tdmi)
dvb_fe_stop(tda, 0);
RB_REMOVE(&dvb_muxes, tdmi, tdmi_global_link);
LIST_REMOVE(tdmi, tdmi_adapter_link);
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);
@ -334,28 +287,9 @@ dvb_mux_destroy(th_dvb_mux_instance_t *tdmi)
epggrab_mux_delete(dm);
hts_settings_remove("dvbmuxes/%s", tdmi->tdmi_identifier);
// free(tdmi->tdmi_network_name); // XXX(dvbreorg)
free(tdmi->tdmi_identifier);
free(tdmi);
dvb_adapter_notify(tda);
}
/**
*
*/
th_dvb_mux_instance_t *
dvb_mux_find_by_identifier(const char *identifier)
{
th_dvb_mux_instance_t skel;
lock_assert(&global_lock);
skel.tdmi_identifier = (char *)identifier;
return RB_FIND(&dvb_muxes, &skel, tdmi_global_link, tdmi_global_cmp);
free(dm->dm_local_identifier);
free(dm->dm_uuid);
free(dm);
}
@ -542,30 +476,28 @@ int dvb_mux_str2hier(const char *str)
*
*/
void
dvb_mux_save(th_dvb_mux_instance_t *tdmi)
dvb_mux_save(dvb_mux_t *dm)
{
const dvb_mux_conf_t *dmc = &tdmi->tdmi_mux->dm_conf;
const dvb_mux_conf_t *dmc = &dm->dm_conf;
const struct dvb_frontend_parameters *f = &dmc->dmc_fe_params;
htsmsg_t *m = htsmsg_create_map();
htsmsg_add_u32(m, "quality", tdmi->tdmi_adapter->tda_qmon ? tdmi->tdmi_quality : 100);
htsmsg_add_u32(m, "enabled", tdmi->tdmi_enabled);
htsmsg_add_str(m, "status", dvb_mux_status(tdmi));
htsmsg_add_u32(m, "enabled", dm->dm_enabled);
htsmsg_add_u32(m, "transportstreamid", tdmi->tdmi_mux->dm_transport_stream_id);
htsmsg_add_u32(m, "originalnetworkid", tdmi->tdmi_mux->dm_network_id);
if(tdmi->tdmi_mux->dm_network_name != NULL)
htsmsg_add_str(m, "network", tdmi->tdmi_mux->dm_network_name);
htsmsg_add_u32(m, "transportstreamid", dm->dm_transport_stream_id);
htsmsg_add_u32(m, "originalnetworkid", dm->dm_network_id);
if(dm->dm_network_name != NULL)
htsmsg_add_str(m, "network", dm->dm_network_name);
htsmsg_add_u32(m, "frequency", f->frequency);
htsmsg_add_u32(m, "initialscan", tdmi->tdmi_mux->dm_table_initial);
htsmsg_add_u32(m, "initialscan", dm->dm_table_initial);
if(tdmi->tdmi_mux->dm_default_authority)
htsmsg_add_str(m, "default_authority", tdmi->tdmi_mux->dm_default_authority);
if(dm->dm_default_authority)
htsmsg_add_str(m, "default_authority", dm->dm_default_authority);
switch(tdmi->tdmi_adapter->tda_fe_type) {
switch(dm->dm_dn->dn_fe_type) {
case FE_OFDM:
htsmsg_add_str(m, "bandwidth",
val2str(f->u.ofdm.bandwidth, bwtab));
@ -626,31 +558,30 @@ dvb_mux_save(th_dvb_mux_instance_t *tdmi)
break;
}
hts_settings_save(m, "dvbmuxes/%s/%s",
tdmi->tdmi_adapter->tda_identifier, tdmi->tdmi_identifier);
hts_settings_save(m, "dvb/networks/%s/muxes/%s/config",
dm->dm_dn->dn_uuid,
dm->dm_local_identifier);
htsmsg_destroy(m);
}
/**
*
*/
static const char *
tdmi_create_by_msg(th_dvb_adapter_t *tda, htsmsg_t *m, const char *identifier)
dvb_mux_create_by_msg(dvb_network_t *dn, htsmsg_t *m, const char *fname)
{
th_dvb_mux_instance_t *tdmi;
dvb_mux_t *dm;
struct dvb_mux_conf dmc;
const char *s;
int r;
unsigned int onid, tsid, u32, enabled, initscan;
unsigned int onid, tsid, enabled, initscan;
memset(&dmc, 0, sizeof(dmc));
dmc.dmc_fe_params.inversion = INVERSION_AUTO;
htsmsg_get_u32(m, "frequency", &dmc.dmc_fe_params.frequency);
switch(tda->tda_fe_type) {
switch(dn->dn_fe_type) {
case FE_OFDM:
s = htsmsg_get_str(m, "bandwidth");
if(s == NULL || (r = str2val(s, bwtab)) < 0)
@ -764,48 +695,43 @@ tdmi_create_by_msg(th_dvb_adapter_t *tda, htsmsg_t *m, const char *identifier)
enabled = 1;
initscan = htsmsg_get_u32_or_default(m, "initialscan", 0);
tdmi = dvb_mux_create(tda, &dmc,
onid, tsid, htsmsg_get_str(m, "network"), NULL, enabled,
initscan,
identifier);
if(tdmi != NULL) {
if((s = htsmsg_get_str(m, "status")) != NULL)
tdmi->tdmi_fe_status = str2val(s, muxfestatustab);
if(tda->tda_qmon && !htsmsg_get_u32(m, "quality", &u32))
tdmi->tdmi_quality = u32;
dm = dvb_mux_create(dn, &dmc,
onid, tsid, htsmsg_get_str(m, "network"), NULL, enabled,
initscan,
htsmsg_get_str(m, "uuid"));
if(dm != NULL) {
if((s = htsmsg_get_str(m, "default_authority")))
tdmi->tdmi_mux->dm_default_authority = strdup(s);
dm->dm_default_authority = strdup(s);
}
return NULL;
}
/**
*
*/
void
dvb_mux_load(th_dvb_adapter_t *tda)
dvb_mux_load(dvb_network_t *dn)
{
htsmsg_t *l, *c;
htsmsg_field_t *f;
if((l = hts_settings_load("dvbmuxes/%s", tda->tda_identifier)) == NULL)
if((l = hts_settings_load_r(1, "dvb/networks/%s/muxes",
dn->dn_uuid)) == NULL)
return;
HTSMSG_FOREACH(f, l) {
if((c = htsmsg_get_map_by_field(f)) == NULL)
continue;
tdmi_create_by_msg(tda, c, f->hmf_name);
dvb_mux_create_by_msg(dn, c, f->hmf_name);
}
htsmsg_destroy(l);
}
/**
*
*/
@ -817,13 +743,11 @@ dvb_mux_set_networkname(dvb_mux_t *dm, const char *networkname)
free(dm->dm_network_name);
dm->dm_network_name = strdup(networkname);
th_dvb_mux_instance_t *tdmi = dm->dm_tdmi;
dvb_mux_save(tdmi);
dvb_mux_save(dm);
m = htsmsg_create_map();
htsmsg_add_str(m, "id", tdmi->tdmi_identifier);
htsmsg_add_str(m, "network", tdmi->tdmi_mux->dm_network_name ?: "");
htsmsg_add_str(m, "id", dm->dm_local_identifier);
htsmsg_add_str(m, "network", dm->dm_network_name ?: "");
notify_by_msg("dvbMux", m);
}
@ -838,13 +762,11 @@ dvb_mux_set_tsid(dvb_mux_t *dm, uint16_t tsid)
dm->dm_transport_stream_id = tsid;
th_dvb_mux_instance_t *tdmi = dm->dm_tdmi;
dvb_mux_save(tdmi);
dvb_mux_save(dm);
m = htsmsg_create_map();
htsmsg_add_str(m, "id", tdmi->tdmi_identifier);
htsmsg_add_u32(m, "muxid", tdmi->tdmi_mux->dm_transport_stream_id);
htsmsg_add_str(m, "uuid", dm->dm_uuid);
htsmsg_add_u32(m, "muxid", dm->dm_transport_stream_id);
notify_by_msg("dvbMux", m);
}
@ -858,17 +780,15 @@ dvb_mux_set_onid(dvb_mux_t *dm, uint16_t onid)
dm->dm_network_id = onid;
th_dvb_mux_instance_t *tdmi = dm->dm_tdmi;
dvb_mux_save(tdmi);
dvb_mux_save(dm);
m = htsmsg_create_map();
htsmsg_add_str(m, "id", tdmi->tdmi_identifier);
htsmsg_add_u32(m, "onid", tdmi->tdmi_mux->dm_network_id);
htsmsg_add_str(m, "uuid", dm->dm_uuid);
htsmsg_add_u32(m, "onid", dm->dm_network_id);
notify_by_msg("dvbMux", m);
}
#if 0
/**
*
*/
@ -909,8 +829,9 @@ dvb_mux_set_enable(th_dvb_mux_instance_t *tdmi, int enabled)
tdmi_set_enable(tdmi, enabled);
dvb_mux_save(tdmi);
}
#endif
#if 0
/**
*
*/
@ -942,17 +863,18 @@ dvb_mux_fe_status(char *buf, size_t size, th_dvb_mux_instance_t *tdmi)
break;
}
}
#endif
/**
*
*/
static void
dvb_mux_modulation(char *buf, size_t size, th_dvb_mux_instance_t *tdmi)
dvb_mux_modulation(char *buf, size_t size, const dvb_mux_t *dm)
{
const dvb_mux_conf_t *dmc = &tdmi->tdmi_mux->dm_conf;
const dvb_mux_conf_t *dmc = &dm->dm_conf;
const struct dvb_frontend_parameters *f = &dmc->dmc_fe_params;
switch(tdmi->tdmi_adapter->tda_fe_type) {
switch(dm->dm_dn->dn_fe_type) {
case FE_OFDM:
snprintf(buf, size, "%s, %s, %s-mode",
val2str(f->u.ofdm.constellation, qamtab),
@ -990,37 +912,32 @@ dvb_mux_modulation(char *buf, size_t size, th_dvb_mux_instance_t *tdmi)
*
*/
htsmsg_t *
dvb_mux_build_msg(th_dvb_mux_instance_t *tdmi)
dvb_mux_build_msg(dvb_mux_t *dm)
{
htsmsg_t *m = htsmsg_create_map();
char buf[100];
htsmsg_add_str(m, "id", tdmi->tdmi_identifier);
htsmsg_add_u32(m, "enabled", tdmi->tdmi_enabled);
htsmsg_add_str(m, "network", tdmi->tdmi_mux->dm_network_name ?: "");
htsmsg_add_str(m, "uuid", dm->dm_uuid);
htsmsg_add_u32(m, "enabled", dm->dm_enabled);
htsmsg_add_str(m, "network", dm->dm_network_name ?: "");
dvb_mux_nicefreq(buf, sizeof(buf), tdmi->tdmi_mux);
dvb_mux_nicefreq(buf, sizeof(buf), dm);
htsmsg_add_str(m, "freq", buf);
dvb_mux_modulation(buf, sizeof(buf), tdmi);
dvb_mux_modulation(buf, sizeof(buf), dm);
htsmsg_add_str(m, "mod", buf);
dvb_mux_fe_status(buf, sizeof(buf), tdmi);
htsmsg_add_str(m, "fe_status", buf);
const dvb_mux_conf_t *dmc = &dm->dm_conf;
const dvb_mux_conf_t *dmc = &tdmi->tdmi_mux->dm_conf;
htsmsg_add_str(m, "pol",
htsmsg_add_str(m, "pol",
dvb_polarisation_to_str_long(dmc->dmc_polarisation));
if(tdmi->tdmi_mux->dm_transport_stream_id != 0xffff)
htsmsg_add_u32(m, "muxid", tdmi->tdmi_mux->dm_transport_stream_id);
if(dm->dm_transport_stream_id != 0xffff)
htsmsg_add_u32(m, "muxid", dm->dm_transport_stream_id);
if(tdmi->tdmi_mux->dm_network_id)
htsmsg_add_u32(m, "onid", tdmi->tdmi_mux->dm_network_id);
if(dm->dm_network_id)
htsmsg_add_u32(m, "onid", dm->dm_network_id);
htsmsg_add_u32(m, "quality", tdmi->tdmi_quality);
return m;
}
@ -1029,9 +946,9 @@ dvb_mux_build_msg(th_dvb_mux_instance_t *tdmi)
*
*/
void
dvb_mux_notify(th_dvb_mux_instance_t *tdmi)
dvb_mux_notify(dvb_mux_t *dm)
{
notify_by_msg("dvbMux", dvb_mux_build_msg(tdmi));
// notify_by_msg("dvbMux", dvb_mux_build_msg(tdmi));
}
@ -1039,7 +956,7 @@ dvb_mux_notify(th_dvb_mux_instance_t *tdmi)
*
*/
const char *
dvb_mux_add_by_params(th_dvb_adapter_t *tda,
dvb_mux_add_by_params(dvb_network_t *dn,
int freq,
int symrate,
int bw,
@ -1054,13 +971,12 @@ dvb_mux_add_by_params(th_dvb_adapter_t *tda,
int polarisation,
const char *satconf)
{
th_dvb_mux_instance_t *tdmi;
struct dvb_mux_conf dmc;
memset(&dmc, 0, sizeof(dmc));
dmc.dmc_fe_params.inversion = INVERSION_AUTO;
switch(tda->tda_fe_type) {
switch(dn->dn_fe_type) {
case FE_OFDM:
dmc.dmc_fe_params.frequency = freq * 1000;
if(!val2str(bw, bwtab))
@ -1146,14 +1062,14 @@ dvb_mux_add_by_params(th_dvb_adapter_t *tda,
dmc.dmc_polarisation = polarisation;
tdmi = dvb_mux_create(tda, &dmc, 0, 0xffff, NULL, NULL, 1, 1, NULL);
dvb_mux_t *dm = dvb_mux_create(dn, &dmc, 0, 0xffff, NULL, NULL, 1, 1, NULL);
if(tdmi == NULL)
if(dm == NULL)
return "Mux already exist";
return NULL;
}
#if 0
/**
*
@ -1234,23 +1150,33 @@ dvb_mux_copy(th_dvb_adapter_t *dst, th_dvb_mux_instance_t *tdmi_src,
}
#endif
th_dvb_mux_instance_t *dvb_mux_find
( th_dvb_adapter_t *tda, const char *netname, uint16_t onid, uint16_t tsid,
int enabled )
dvb_mux_t *
dvb_mux_find(dvb_network_t *dn, const char *netname, uint16_t onid,
uint16_t tsid, int enabled)
{
th_dvb_mux_instance_t *tdmi;
if (tda) {
LIST_FOREACH(tdmi, &tda->tda_dn->dn_mux_instances, tdmi_adapter_link) {
if (enabled && !tdmi->tdmi_enabled) continue;
if (onid && onid != tdmi->tdmi_mux->dm_network_id) continue;
if (tsid && tsid != tdmi->tdmi_mux->dm_transport_stream_id) continue;
if (netname && strcmp(netname, tdmi->tdmi_mux->dm_network_name ?: "")) continue;
return tdmi;
dvb_mux_t *dm;
if(dn != NULL) {
LIST_FOREACH(dm, &dn->dn_muxes, dm_network_link) {
if (enabled && !dm->dm_enabled)
continue;
if (onid && onid != dm->dm_network_id)
continue;
if (tsid && tsid != dm->dm_transport_stream_id)
continue;
if (netname && strcmp(netname, dm->dm_network_name ?: ""))
continue;
return dm;
}
} else {
TAILQ_FOREACH(tda, &dvb_adapters, tda_global_link)
if ((tdmi = dvb_mux_find(tda, netname, onid, tsid, enabled)))
return tdmi;
dvb_network_t *dn;
LIST_FOREACH(dn, &dvb_networks, dn_global_link)
if ((dm = dvb_mux_find(dn, netname, onid, tsid, enabled)))
return dm;
}
return NULL;
}

View file

@ -21,7 +21,7 @@
#include "dvb.h"
#include "epggrab.h"
struct dvb_network_list dvb_networks;
/**
*
@ -33,9 +33,96 @@ dvb_network_create(int fe_type)
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);
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 void
dvb_network_save(dvb_network_t *dn)
{
htsmsg_t *m = htsmsg_create_map();
lock_assert(&global_lock);
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();
}
#endif
#if 0
/**
*
*/
void
dvb_network_set_auto_discovery(dvb_network_t *dn, int on)
{
if(dn->dn_autodiscovery == on)
return;
lock_assert(&global_lock);
tvhlog(LOG_NOTICE, "dvb", "Network \"%s\" mux autodiscovery set to: %s",
dn->dn_displayname, on ? "On" : "Off");
dn->dn_autodiscovery = on;
dvb_network_save(dn);
}
/**
*
*/
void
dvb_network_set_nitoid(dvb_network_t *dn, int nitoid)
{
lock_assert(&global_lock);
if(dn->dn_nitoid == nitoid)
return;
tvhlog(LOG_NOTICE, "dvb", "NIT-o network id \"%d\" changed to \"%d\"",
dn->dn_nitoid, nitoid);
dn->dn_nitoid = nitoid;
dvb_network_save(dn);
}
/**
*
*/
void
dvb_network_set_disable_pmt_monitor(th_dvb_network_t *dn, int on)
{
if(dn->dn_disable_pmt_monitor == on)
return;
lock_assert(&global_lock);
tvhlog(LOG_NOTICE, "dvb", "Network \"%s\" disabled PMT monitoring set to: %s",
dn->dn_displayname, on ? "On" : "Off");
dn->dn_disable_pmt_monitor = on;
dvb_network_save(dn);
}
#endif
/**

View file

@ -35,7 +35,7 @@
*
*/
static void
dvb_mux_preconf_add(th_dvb_adapter_t *tda, const network_t *net,
dvb_mux_preconf_add(dvb_network_t *dn, const network_t *net,
const char *source)
{
const mux_t *m;
@ -48,7 +48,7 @@ dvb_mux_preconf_add(th_dvb_adapter_t *tda, const network_t *net,
dmc.dmc_fe_params.inversion = INVERSION_AUTO;
dmc.dmc_fe_params.frequency = m->freq;
switch(tda->tda_fe_type) {
switch(dn->dn_fe_type) {
case FE_OFDM:
dmc.dmc_fe_params.u.ofdm.bandwidth = m->bw;
dmc.dmc_fe_params.u.ofdm.constellation = m->constellation;
@ -96,7 +96,7 @@ dvb_mux_preconf_add(th_dvb_adapter_t *tda, const network_t *net,
break;
}
dvb_mux_create(tda, &dmc, 0, 0xffff, NULL, source, 1, 1, NULL);
dvb_mux_create(dn, &dmc, 0, 0xffff, NULL, source, 1, 1, NULL);
}
}
@ -105,7 +105,7 @@ dvb_mux_preconf_add(th_dvb_adapter_t *tda, const network_t *net,
*
*/
int
dvb_mux_preconf_add_network(th_dvb_adapter_t *tda, const char *id)
dvb_mux_preconf_add_network(dvb_network_t *dn, const char *id)
{
region_list_t *list;
const region_t *r;
@ -114,7 +114,7 @@ dvb_mux_preconf_add_network(th_dvb_adapter_t *tda, const char *id)
snprintf(source, sizeof(source), "built-in configuration from \"%s\"", id);
switch(tda->tda_fe_type) {
switch(dn->dn_fe_type) {
case FE_QAM:
list = &regions_DVBC;
break;
@ -134,7 +134,7 @@ dvb_mux_preconf_add_network(th_dvb_adapter_t *tda, const char *id)
LIST_FOREACH(r, list, link) {
LIST_FOREACH(n, &r->networks, link) {
if(!strcmp(n->id, id)) {
dvb_mux_preconf_add(tda, n, source);
dvb_mux_preconf_add(dn, n, source);
break;
}
}

View file

@ -23,6 +23,6 @@
htsmsg_t *dvb_mux_preconf_get_node(int fetype, const char *node);
int dvb_mux_preconf_add_network(th_dvb_adapter_t *tda, const char *id);
int dvb_mux_preconf_add_network(dvb_network_t *dn, const char *id);
#endif /* DVB_MUXCONFIG_H */

View file

@ -46,6 +46,14 @@
/**
*
*/
/**
* Switch the adapter (which is implicitly tied to our transport)
@ -57,6 +65,7 @@
static int
dvb_service_start(service_t *t, unsigned int weight, int force_start)
{
#if 0
int w, r;
th_dvb_adapter_t *tda = t->s_dvb_mux_instance->tdmi_adapter;
th_dvb_mux_instance_t *tdmi = tda->tda_current_tdmi;
@ -100,6 +109,8 @@ dvb_service_start(service_t *t, unsigned int weight, int force_start)
dvb_table_add_pmt(t->s_dvb_mux_instance->tdmi_mux, t->s_pmt_pid);
return r;
#endif
return SM_CODE_NO_HW_ATTACHED;
}
@ -109,6 +120,7 @@ dvb_service_start(service_t *t, unsigned int weight, int force_start)
static void
dvb_service_stop(service_t *t)
{
#if 0
th_dvb_adapter_t *tda = t->s_dvb_mux_instance->tdmi_adapter;
lock_assert(&global_lock);
@ -120,6 +132,7 @@ dvb_service_stop(service_t *t)
tda->tda_close_service(tda, t);
t->s_status = SERVICE_IDLE;
#endif
}
@ -129,10 +142,12 @@ dvb_service_stop(service_t *t)
static void
dvb_service_refresh(service_t *t)
{
#if 0
th_dvb_adapter_t *tda = t->s_dvb_mux_instance->tdmi_adapter;
lock_assert(&global_lock);
tda->tda_open_service(tda, t);
#endif
}
@ -165,7 +180,7 @@ dvb_service_save(service_t *t)
if(t->s_dvb_charset != NULL)
htsmsg_add_str(m, "dvb_charset", t->s_dvb_charset);
htsmsg_add_u32(m, "dvb_eit_enable", t->s_dvb_eit_enable);
if(t->s_default_authority)
@ -174,13 +189,15 @@ dvb_service_save(service_t *t)
pthread_mutex_lock(&t->s_stream_mutex);
psi_save_service_settings(m, t);
pthread_mutex_unlock(&t->s_stream_mutex);
hts_settings_save(m, "dvbtransports/%s/%s",
t->s_dvb_mux_instance->tdmi_identifier,
t->s_identifier);
dvb_mux_t *dm = t->s_dvb_mux;
hts_settings_save(m, "dvb/networks/%s/muxes/%s/services/%04x",
dm->dm_dn->dn_uuid,
dm->dm_local_identifier,
t->s_dvb_service_id);
htsmsg_destroy(m);
dvb_service_notify(t);
}
@ -188,7 +205,7 @@ dvb_service_save(service_t *t)
* Load config for the given mux
*/
void
dvb_service_load(th_dvb_mux_instance_t *tdmi, const char *tdmi_identifier)
dvb_service_load(dvb_mux_t *dm)
{
htsmsg_t *l, *c;
htsmsg_field_t *f;
@ -196,19 +213,14 @@ dvb_service_load(th_dvb_mux_instance_t *tdmi, const char *tdmi_identifier)
const char *s;
unsigned int u32;
service_t *t;
int old;
lock_assert(&global_lock);
/* HACK - use provided identifier to load config incase we've migrated
* mux freq */
if (!tdmi_identifier)
tdmi_identifier = tdmi->tdmi_identifier;
old = strcmp(tdmi_identifier, tdmi->tdmi_identifier);
if((l = hts_settings_load("dvbtransports/%s", tdmi_identifier)) == NULL)
l = hts_settings_load("dvb/networks/%s/muxes/%s/services",
dm->dm_dn->dn_uuid, dm->dm_local_identifier);
if(l == NULL)
return;
HTSMSG_FOREACH(f, l) {
if((c = htsmsg_get_map_by_field(f)) == NULL)
continue;
@ -218,8 +230,8 @@ dvb_service_load(th_dvb_mux_instance_t *tdmi, const char *tdmi_identifier)
if(htsmsg_get_u32(c, "pmt", &pmt))
continue;
t = dvb_service_find(tdmi, sid, pmt, f->hmf_name);
t = dvb_service_find(dm, sid, pmt, f->hmf_name);
htsmsg_get_u32(c, "stype", &t->s_servicetype);
if(htsmsg_get_u32(c, "scrambled", &u32))
@ -258,39 +270,11 @@ dvb_service_load(th_dvb_mux_instance_t *tdmi, const char *tdmi_identifier)
if(s && u32)
service_map_channel(t, channel_find_by_name(s, 1, 0), 0);
/* HACK - force save for old config */
if(old)
dvb_service_save(t);
}
/* HACK - remove old settings */
if(old) {
HTSMSG_FOREACH(f, l)
hts_settings_remove("dvbtransports/%s/%s", tdmi_identifier, f->hmf_name);
hts_settings_remove("dvbtransports/%s", tdmi_identifier);
}
htsmsg_destroy(l);
}
/**
* Called to get quality for the given transport
*
* We keep track of this for the entire mux (if we see errors), soo..
* return that value
*/
static int
dvb_service_quality(service_t *t)
{
th_dvb_mux_instance_t *tdmi = t->s_dvb_mux_instance;
lock_assert(&global_lock);
return tdmi->tdmi_adapter->tda_qmon ? tdmi->tdmi_quality : 100;
}
/**
* Generate a descriptive name for the source
@ -298,7 +282,7 @@ dvb_service_quality(service_t *t)
static void
dvb_service_setsourceinfo(service_t *t, struct source_info *si)
{
th_dvb_mux_instance_t *tdmi = t->s_dvb_mux_instance;
dvb_mux_t *dm = t->s_dvb_mux;
char buf[100];
memset(si, 0, sizeof(struct source_info));
@ -307,15 +291,10 @@ dvb_service_setsourceinfo(service_t *t, struct source_info *si)
si->si_type = S_MPEG_TS;
if(tdmi->tdmi_adapter->tda_rootpath != NULL)
si->si_device = strdup(tdmi->tdmi_adapter->tda_rootpath);
if(dm->dm_network_name != NULL)
si->si_network = strdup(dm->dm_network_name);
si->si_adapter = strdup(tdmi->tdmi_adapter->tda_displayname);
if(tdmi->tdmi_mux->dm_network_name != NULL)
si->si_network = strdup(tdmi->tdmi_mux->dm_network_name);
dvb_mux_nicename(buf, sizeof(buf), tdmi);
dvb_mux_nicename(buf, sizeof(buf), dm);
si->si_mux = strdup(buf);
if(t->s_provider != NULL)
@ -335,36 +314,37 @@ dvb_grace_period(service_t *t)
return 10;
}
/*
* Find transport based on the DVB identification
*/
service_t *
dvb_service_find3
(th_dvb_adapter_t *tda, th_dvb_mux_instance_t *tdmi,
const char *netname, uint16_t onid, uint16_t tsid, uint16_t sid,
int enabled, int epgprimary)
dvb_service_find3(dvb_network_t *dn, dvb_mux_t *dm,
const char *netname, uint16_t onid, uint16_t tsid,
uint16_t sid, int enabled, int epgprimary)
{
service_t *svc;
if (tdmi) {
LIST_FOREACH(svc, &tdmi->tdmi_mux->dm_services, s_group_link) {
if (dm != NULL) {
LIST_FOREACH(svc, &dm->dm_services, s_group_link) {
if (enabled && !svc->s_enabled) continue;
if (epgprimary && !service_is_primary_epg(svc)) continue;
if (sid == svc->s_dvb_service_id) return svc;
}
} else if (tda) {
LIST_FOREACH(tdmi, &tda->tda_dn->dn_mux_instances, tdmi_adapter_link) {
if (enabled && !tdmi->tdmi_enabled) continue;
if (onid && onid != tdmi->tdmi_mux->dm_network_id) continue;
if (tsid && tsid != tdmi->tdmi_mux->dm_transport_stream_id) continue;
if (netname && strcmp(netname, tdmi->tdmi_mux->dm_network_name ?: "")) continue;
if ((svc = dvb_service_find3(tda, tdmi, NULL, 0, 0, sid,
enabled, epgprimary)))
} else if (dn) {
LIST_FOREACH(dm, &dn->dn_muxes, dm_network_link) {
if (enabled && !dm->dm_enabled) continue;
if (onid && onid != dm->dm_network_id) continue;
if (tsid && tsid != dm->dm_transport_stream_id) continue;
if (netname && strcmp(netname, dm->dm_network_name ?: "")) continue;
if ((svc = dvb_service_find3(dn, dm, NULL, 0, 0, sid,
enabled, epgprimary)))
return svc;
}
} else {
TAILQ_FOREACH(tda, &dvb_adapters, tda_global_link)
if ((svc = dvb_service_find3(tda, NULL, netname, onid, tsid,
sid, enabled, epgprimary)))
LIST_FOREACH(dn, &dvb_networks, dn_global_link)
if ((svc = dvb_service_find3(dn, NULL, netname, onid, tsid,
sid, enabled, epgprimary)))
return svc;
}
return NULL;
@ -377,39 +357,36 @@ dvb_service_find3
* If it cannot be found we create it if 'pmt_pid' is also set
*/
service_t *
dvb_service_find(th_dvb_mux_instance_t *tdmi, uint16_t sid, int pmt_pid,
const char *identifier)
dvb_service_find(dvb_mux_t *dm, uint16_t sid, int pmt_pid, const char *uuid)
{
return dvb_service_find2(tdmi, sid, pmt_pid, identifier, NULL);
return dvb_service_find2(dm, sid, pmt_pid, uuid, NULL);
}
/**
*
*/
service_t *
dvb_service_find2(th_dvb_mux_instance_t *tdmi, uint16_t sid, int pmt_pid,
const char *identifier, int *save)
dvb_service_find2(dvb_mux_t *dm, uint16_t sid, int pmt_pid,
const char *uuid, int *save)
{
service_t *t;
char tmp[200];
char buf[200];
lock_assert(&global_lock);
LIST_FOREACH(t, &tdmi->tdmi_mux->dm_services, s_group_link) {
LIST_FOREACH(t, &dm->dm_services, s_group_link) {
if(t->s_dvb_service_id == sid)
return t;
}
if(pmt_pid == 0)
return NULL;
if(identifier == NULL) {
snprintf(tmp, sizeof(tmp), "%s_%04x", tdmi->tdmi_identifier, sid);
identifier = tmp;
}
dvb_mux_nicename(buf, sizeof(buf), dm);
tvhlog(LOG_DEBUG, "dvb", "Add service \"0x%x\" on \"%s\"", sid, buf);
dvb_mux_nicename(buf, sizeof(buf), tdmi);
tvhlog(LOG_DEBUG, "dvb", "Add service \"%s\" on \"%s\"", identifier, buf);
t = service_create(identifier, SERVICE_TYPE_DVB, S_MPEG_TS);
t = service_create(uuid, S_MPEG_TS);
if (save) *save = 1;
t->s_dvb_service_id = sid;
@ -420,17 +397,14 @@ dvb_service_find2(th_dvb_mux_instance_t *tdmi, uint16_t sid, int pmt_pid,
t->s_stop_feed = dvb_service_stop;
t->s_config_save = dvb_service_save;
t->s_setsourceinfo = dvb_service_setsourceinfo;
t->s_quality_index = dvb_service_quality;
t->s_grace_period = dvb_grace_period;
t->s_dvb_mux_instance = tdmi;
LIST_INSERT_HEAD(&tdmi->tdmi_mux->dm_services, t, s_group_link);
t->s_dvb_mux = dm;
LIST_INSERT_HEAD(&dm->dm_services, t, s_group_link);
pthread_mutex_lock(&t->s_stream_mutex);
service_make_nicename(t);
pthread_mutex_unlock(&t->s_stream_mutex);
dvb_adapter_notify(tdmi->tdmi_adapter);
return t;
}
@ -441,11 +415,11 @@ dvb_service_find2(th_dvb_mux_instance_t *tdmi, uint16_t sid, int pmt_pid,
htsmsg_t *
dvb_service_build_msg(service_t *t)
{
th_dvb_mux_instance_t *tdmi = t->s_dvb_mux_instance;
dvb_mux_t *dm = t->s_dvb_mux;
htsmsg_t *m = htsmsg_create_map();
char buf[100];
htsmsg_add_str(m, "id", t->s_identifier);
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);
@ -458,9 +432,9 @@ dvb_service_build_msg(service_t *t)
htsmsg_add_str(m, "svcname", t->s_svcname ?: "");
htsmsg_add_str(m, "provider", t->s_provider ?: "");
htsmsg_add_str(m, "network", tdmi->tdmi_mux->dm_network_name ?: "");
htsmsg_add_str(m, "network", dm->dm_network_name ?: "");
dvb_mux_nicefreq(buf, sizeof(buf), tdmi->tdmi_mux);
dvb_mux_nicefreq(buf, sizeof(buf), dm);
htsmsg_add_str(m, "mux", buf);
if(t->s_ch != NULL)
@ -486,16 +460,3 @@ dvb_service_notify_by_adapter(th_dvb_adapter_t *tda)
notify_by_msg("dvbService", m);
}
/**
*
*/
void
dvb_service_notify(service_t *t)
{
th_dvb_mux_instance_t *tdmi = t->s_dvb_mux_instance;
htsmsg_t *m = htsmsg_create_map();
htsmsg_add_str(m, "adapterId", tdmi->tdmi_adapter->tda_identifier);
notify_by_msg("dvbService", m);
}

View file

@ -485,13 +485,12 @@ dvb_mux_nicefreq(char *buf, size_t size, const dvb_mux_t *dm)
*
*/
void
dvb_mux_nicename(char *buf, size_t size, th_dvb_mux_instance_t *tdmi)
dvb_mux_nicename(char *buf, size_t size, dvb_mux_t *dm)
{
char freq[50];
const dvb_mux_t *dm = tdmi->tdmi_mux;
const char *n = dm->dm_network_name;
if(tdmi->tdmi_adapter->tda_fe_type == FE_QPSK) {
if(dm->dm_dn->dn_fe_type == FE_QPSK) {
nicenum(freq, sizeof(freq), dm->dm_conf.dmc_fe_params.frequency);
snprintf(buf, size, "%s%s%s kHz %s",
n?:"", n ? ": ":"", freq,

View file

@ -79,7 +79,7 @@ const char *dvb_polarisation_to_str(int pol);
const char *dvb_polarisation_to_str_long(int pol);
th_dvb_adapter_t *dvb_adapter_find_by_identifier(const char *identifier);
th_dvb_mux_instance_t *dvb_mux_find_by_identifier(const char *identifier);
void dvb_mux_nicename(char *buf, size_t size, th_dvb_mux_instance_t *tdmi);
void dvb_mux_nicename(char *buf, size_t size, dvb_mux_t *tdmi);
int dvb_mux_badness(th_dvb_mux_instance_t *tdmi);
const char *dvb_mux_status(th_dvb_mux_instance_t *tdmi);
void dvb_mux_nicefreq(char *buf, size_t size, const dvb_mux_t *dm);

View file

@ -64,10 +64,10 @@ dvb_table_fastswitch(th_dvb_mux_instance_t *tdmi)
dm->dm_table_initial = 0;
dn->dn_initial_num_mux--;
dvb_mux_save(tdmi);
dvb_mux_save(dm);
dvb_mux_nicename(buf, sizeof(buf), tdmi);
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);
@ -164,7 +164,8 @@ tdt_add(dvb_mux_t *dm, int tableid, int mask,
const char *name, int flags, int pid)
{
th_dvb_table_t *t;
th_dvb_mux_instance_t *tdmi = dm->dm_tdmi;
th_dvb_mux_instance_t *tdmi = dm->dm_current_tdmi;
assert(tdmi != NULL);
// Allow multiple entries per PID, but only one per callback/opaque instance
// TODO: this could mean reading the same data multiple times, and not
@ -298,7 +299,7 @@ dvb_bat_callback(dvb_mux_t *dm, uint8_t *buf, int len,
save = 1;
}
if (save)
dvb_mux_save(dm->dm_tdmi);
dvb_mux_save(dm);
}
i += tdlen;
@ -377,7 +378,7 @@ dvb_sdt_callback(dvb_mux_t *dm, uint8_t *ptr, int len,
if(dllen > len)
break;
if (!(t = dvb_service_find(dm->dm_tdmi, service_id, 0, NULL))) {
if (!(t = dvb_service_find(dm, service_id, 0, NULL))) {
len -= dllen;
ptr += dllen;
continue;
@ -519,8 +520,8 @@ dvb_pat_callback(dvb_mux_t *dm, uint8_t *ptr, int len,
if(service != 0 && pmt != 0) {
int save = 0;
dvb_service_find2(dm->dm_tdmi, service, pmt, NULL, &save);
if (save || ! dm->dm_tdmi->tdmi_adapter->tda_disable_pmt_monitor)
dvb_service_find2(dm, service, pmt, NULL, &save);
if (save || ! dm->dm_dn->dn_disable_pmt_monitor)
dvb_table_add_pmt(dm, pmt);
}
ptr += 4;
@ -623,7 +624,7 @@ dvb_table_cable_delivery(dvb_mux_t *dm, uint8_t *ptr, int len,
struct dvb_mux_conf dmc;
int freq, symrate;
if(!dm->dm_tdmi->tdmi_adapter->tda_autodiscovery)
if(!dm->dm_dn->dn_autodiscovery)
return -1;
if(len < 11)
@ -655,7 +656,7 @@ dvb_table_cable_delivery(dvb_mux_t *dm, uint8_t *ptr, int len,
dmc.dmc_fe_params.u.qam.fec_inner = fec_tab[ptr[10] & 0x07];
dvb_mux_create(dm->dm_tdmi->tdmi_adapter, &dmc, onid, tsid, NULL,
dvb_mux_create(dm->dm_dn, &dmc, onid, tsid, NULL,
"automatic mux discovery", 1, 1, NULL);
return 0;
}
@ -671,7 +672,7 @@ dvb_table_sat_delivery(dvb_mux_t *dm, uint8_t *ptr, int len,
// uint16_t orbital_pos;
struct dvb_mux_conf dmc;
if(!dm->dm_tdmi->tdmi_adapter->tda_autodiscovery)
if(!dm->dm_dn->dn_autodiscovery)
return -1;
if(len < 11)
@ -738,7 +739,7 @@ dvb_table_sat_delivery(dvb_mux_t *dm, uint8_t *ptr, int len,
}
#endif
dvb_mux_create(dm->dm_tdmi->tdmi_adapter, &dmc, onid, tsid, NULL,
dvb_mux_create(dm->dm_dn, &dmc, onid, tsid, NULL,
"automatic mux discovery", 1, 1, NULL);
return 0;
}
@ -767,7 +768,7 @@ dvb_table_local_channel(dvb_mux_t *dm, uint8_t *ptr, int len,
chan = ((ptr[2] & 3) << 8) | ptr[3];
if(chan != 0) {
t = dvb_service_find(dm->dm_tdmi, sid, 0, NULL);
t = dvb_service_find(dm, sid, 0, NULL);
if(t != NULL) {
if(t->s_channel_number != chan) {
@ -797,11 +798,11 @@ dvb_nit_callback(dvb_mux_t *dm, uint8_t *ptr, int len,
uint16_t tsid, onid;
uint16_t network_id = (ptr[0] << 8) | ptr[1];
if(dm->dm_tdmi->tdmi_adapter->tda_nitoid) {
if(dm->dm_dn->dn_nitoid) {
if(tableid != 0x41)
return -1;
if(network_id != dm->dm_tdmi->tdmi_adapter->tda_nitoid)
if(network_id != dm->dm_dn->dn_nitoid)
return -1;
} else {
@ -943,7 +944,7 @@ atsc_vct_callback(dvb_mux_t *dm, uint8_t *ptr, int len,
continue;
service_id = (ptr[24] << 8) | ptr[25];
if((t = dvb_service_find(dm->dm_tdmi, service_id, 0, NULL)) == NULL)
if((t = dvb_service_find(dm, service_id, 0, NULL)) == NULL)
continue;
atsc_stype = ptr[27] & 0x3f;
@ -987,18 +988,18 @@ dvb_pmt_callback(dvb_mux_t *dm, uint8_t *ptr, int len,
int active = 0;
service_t *t;
th_dvb_table_t *tdt = opaque;
th_dvb_mux_instance_t *tdmi = dm->dm_tdmi;
LIST_FOREACH(t, &tdmi->tdmi_mux->dm_services, s_group_link) {
LIST_FOREACH(t, &dm->dm_services, s_group_link) {
pthread_mutex_lock(&t->s_stream_mutex);
psi_parse_pmt(t, ptr, len, 1, 1);
if (t->s_pmt_pid == tdt->tdt_pid && t->s_status == SERVICE_RUNNING)
active = 1;
pthread_mutex_unlock(&t->s_stream_mutex);
}
if (tdmi->tdmi_adapter->tda_disable_pmt_monitor && !active)
dvb_tdt_destroy(tdmi->tdmi_adapter, tdmi, tdt);
if (dm->dm_dn->dn_disable_pmt_monitor && !active)
dvb_tdt_destroy(dm->dm_current_tdmi->tdmi_adapter,
dm->dm_current_tdmi, tdt);
return 0;
}
@ -1014,7 +1015,7 @@ dvb_table_add_default_dvb(dvb_mux_t *dm)
int table;
if(dm->dm_tdmi->tdmi_adapter->tda_nitoid) {
if(dm->dm_dn->dn_nitoid) {
table = 0x41;
} else {
table = 0x40;
@ -1095,7 +1096,7 @@ dvb_table_add_pmt(dvb_mux_t *dm, int pmt_pid)
void
dvb_table_rem_pmt(dvb_mux_t *dm, int pmt_pid)
{
th_dvb_mux_instance_t *tdmi = dm->dm_tdmi;
th_dvb_mux_instance_t *tdmi = dm->dm_current_tdmi;
th_dvb_adapter_t *tda = tdmi->tdmi_adapter;
th_dvb_table_t *tdt = NULL;
LIST_FOREACH(tdt, &dm->dm_tables, tdt_link)
@ -1112,10 +1113,10 @@ dvb_table_rem_pmt(dvb_mux_t *dm, int pmt_pid)
void
dvb_table_flush_all(dvb_mux_t *dm)
{
th_dvb_adapter_t *tda = dm->dm_tdmi->tdmi_adapter;
th_dvb_mux_instance_t *tdmi = dm->dm_current_tdmi;
th_dvb_adapter_t *tda = tdmi->tdmi_adapter;
th_dvb_table_t *tdt;
while((tdt = LIST_FIRST(&dm->dm_tables)) != NULL)
dvb_tdt_destroy(tda, dm->dm_tdmi, tdt);
dvb_tdt_destroy(tda, tdmi, tdt);
}

View file

@ -475,7 +475,7 @@ static int _eit_desc_crid
} else {
char *defauth = svc->s_default_authority;
if (!defauth)
defauth = svc->s_dvb_mux_instance->tdmi_mux->dm_default_authority;
defauth = svc->s_dvb_mux->dm_default_authority;
if (defauth)
snprintf(crid, clen, "crid://%s%s", defauth, buf);
}
@ -544,8 +544,8 @@ static int _eit_process_event
/* Override */
if (!ev.default_charset) {
ev.default_charset
= dvb_charset_find(svc->s_dvb_mux_instance->tdmi_mux->dm_network_id,
svc->s_dvb_mux_instance->tdmi_mux->dm_transport_stream_id,
= dvb_charset_find(svc->s_dvb_mux->dm_network_id,
svc->s_dvb_mux->dm_transport_stream_id,
svc->s_dvb_service_id);
}
@ -660,7 +660,6 @@ _eit_callback(dvb_mux_t *dm, uint8_t *ptr, int len,
{
epggrab_module_t *mod = opaque;
epggrab_ota_mux_t *ota;
th_dvb_adapter_t *tda;
service_t *svc;
eit_status_t *sta;
eit_table_status_t *tsta;
@ -713,9 +712,7 @@ _eit_callback(dvb_mux_t *dm, uint8_t *ptr, int len,
// Note: tableid=0x4f,0x60-0x6f is other TS
// so must find the tdmi
if(tableid == 0x4f || tableid >= 0x60) {
tda = dm->dm_tdmi->tdmi_adapter;
th_dvb_mux_instance_t *tdmi = dvb_mux_find(tda, NULL, onid, tsid, 1);
dm = tdmi->tdmi_mux;
dm = dvb_mux_find(dm->dm_dn, NULL, onid, tsid, 1);
} else {
if (dm->dm_transport_stream_id != tsid ||
@ -732,7 +729,7 @@ _eit_callback(dvb_mux_t *dm, uint8_t *ptr, int len,
if(!dm) goto done;
/* Get service */
svc = dvb_service_find3(NULL, dm->dm_tdmi, NULL, 0, 0, sid, 1, 1);
svc = dvb_service_find3(NULL, dm, NULL, 0, 0, sid, 1, 1);
if (!svc || !svc->s_ch) goto done;
/* Register as interesting */

View file

@ -254,12 +254,11 @@ void epggrab_ota_create_and_register_by_id
( epggrab_module_ota_t *mod, int onid, int tsid, int period, int interval,
const char *networkname )
{
th_dvb_adapter_t *tda;
th_dvb_mux_instance_t *tdmi;
dvb_network_t *dn;
dvb_mux_t *dm;
epggrab_ota_mux_t *ota;
TAILQ_FOREACH(tda, &dvb_adapters, tda_global_link) {
LIST_FOREACH(tdmi, &tda->tda_dn->dn_mux_instances, tdmi_adapter_link) {
dvb_mux_t *dm = tdmi->tdmi_mux;
LIST_FOREACH(dn, &dvb_networks, dn_global_link) {
LIST_FOREACH(dm, &dn->dn_muxes, dm_network_link) {
if (dm->dm_transport_stream_id != tsid) continue;
if (onid && dm->dm_network_id != onid) continue;
if (networkname && (!dm->dm_network_name ||

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);
}
if(fd == -1) {
tvhlog(LOG_ERR, "IPTV", "\"%s\" cannot open socket", t->s_identifier);
tvhlog(LOG_ERR, "IPTV", "\"%s\" cannot open socket", t->s_uuid);
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_identifier, t->s_iptv_iface);
t->s_uuid, 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_identifier, inet_ntoa(sin.sin_addr), t->s_iptv_port,
t->s_uuid, 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_identifier, inet_ntoa(m.imr_multiaddr), strerror(errno));
t->s_uuid, 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_identifier, straddr, t->s_iptv_port,
t->s_uuid, 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_identifier, straddr, strerror(errno));
t->s_uuid, 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_identifier, strerror(errno));
t->s_uuid, 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_identifier, t->s_iptv_iface);
t->s_uuid, 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_identifier, inet_ntoa(m.imr_multiaddr), strerror(errno));
t->s_uuid, 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_identifier, straddr, strerror(errno));
t->s_uuid, straddr, strerror(errno));
}
@ -441,27 +441,12 @@ iptv_service_save(service_t *t)
pthread_mutex_unlock(&t->s_stream_mutex);
hts_settings_save(m, "iptvservices/%s",
t->s_identifier);
t->s_uuid);
htsmsg_destroy(m);
}
/**
*
*/
static int
iptv_service_quality(service_t *t)
{
if(t->s_iptv_iface == NULL ||
(t->s_iptv_group.s_addr == 0 && t->s_iptv_group6.s6_addr == 0) ||
t->s_iptv_port == 0)
return 0;
return 100;
}
/**
* Generate a descriptive name for the source
*/
@ -499,7 +484,7 @@ iptv_grace_period(service_t *t)
static void
iptv_service_dtor(service_t *t)
{
hts_settings_remove("iptvservices/%s", t->s_identifier);
hts_settings_remove("iptvservices/%s", t->s_uuid);
}
@ -519,7 +504,7 @@ iptv_service_find(const char *id, int create)
return NULL;
LIST_FOREACH(t, &iptv_all_services, s_group_link)
if(!strcmp(t->s_identifier, id))
if(!strcmp(t->s_uuid, id))
return t;
}
@ -534,7 +519,7 @@ iptv_service_find(const char *id, int create)
tally = MAX(atoi(id + 5), tally);
}
t = service_create(id, SERVICE_TYPE_IPTV, S_MPEG_TS);
t = service_create(id, S_MPEG_TS);
t->s_servicetype = ST_SDTV;
t->s_start_feed = iptv_service_start;
@ -542,7 +527,6 @@ iptv_service_find(const char *id, int create)
t->s_stop_feed = iptv_service_stop;
t->s_config_save = iptv_service_save;
t->s_setsourceinfo = iptv_service_setsourceinfo;
t->s_quality_index = iptv_service_quality;
t->s_grace_period = iptv_grace_period;
t->s_dtor = iptv_service_dtor;
t->s_iptv_fd = -1;

View file

@ -83,17 +83,6 @@ rawts_service_save(service_t *t)
}
/**
*
*/
static int
rawts_service_quality(service_t *t)
{
return 100;
}
/**
* Generate a descriptive name for the source
*/
@ -123,7 +112,7 @@ rawts_service_add(rawts_t *rt, uint16_t sid, int pmt_pid)
snprintf(tmp, sizeof(tmp), "%s_%04x", rt->rt_identifier, sid);
t = service_create(tmp, SERVICE_TYPE_DVB, S_MPEG_TS);
t = service_create(tmp, S_MPEG_TS);
t->s_flags |= S_DEBUG;
t->s_dvb_service_id = sid;
@ -133,7 +122,6 @@ rawts_service_add(rawts_t *rt, uint16_t sid, int pmt_pid)
t->s_stop_feed = rawts_service_stop;
t->s_config_save = rawts_service_save;
t->s_setsourceinfo = rawts_service_setsourceinfo;
t->s_quality_index = rawts_service_quality;
t->s_svcname = strdup(tmp);

View file

@ -231,86 +231,6 @@ service_start(service_t *t, unsigned int weight, int force_start)
return 0;
}
/**
*
*/
static int
dvb_extra_prio(th_dvb_adapter_t *tda)
{
return tda->tda_extrapriority + tda->tda_hostconnection * 10;
}
/**
* Return prio for the given service
*/
static int
service_get_prio(service_t *t)
{
switch(t->s_type) {
case SERVICE_TYPE_DVB:
return (t->s_scrambled ? 300 : 100) +
dvb_extra_prio(t->s_dvb_mux_instance->tdmi_adapter);
case SERVICE_TYPE_IPTV:
return 200;
case SERVICE_TYPE_V4L:
return 400;
default:
return 500;
}
}
/**
* Return quality index for given service
*
* We invert the result (providers say that negative numbers are worse)
*
* But for sorting, we want low numbers first
*
* Also, we bias and trim with an offset of two to avoid counting any
* transient errors.
*/
static int
service_get_quality(service_t *t)
{
return t->s_quality_index ? -MIN(t->s_quality_index(t) + 2, 0) : 0;
}
/**
* a - b -> lowest number first
*/
static int
servicecmp(const void *A, const void *B)
{
service_t *a = *(service_t **)A;
service_t *b = *(service_t **)B;
/* only check quality if both adapters have the same prio
*
* there needs to be a much more sophisticated algorithm to take priority and quality into account
* additional, it may be problematic, since a higher priority value lowers the ranking
*
*/
int prio_a = service_get_prio(a);
int prio_b = service_get_prio(b);
if (prio_a == prio_b) {
int q = service_get_quality(a) - service_get_quality(b);
if(q != 0)
return q; /* Quality precedes priority */
}
return prio_a - prio_b;
}
/**
*
*/
@ -351,7 +271,7 @@ service_find(channel_t *ch, unsigned int weight, const char *loginfo,
/* Sort services, lower priority should come come earlier in the vector
(i.e. it will be more favoured when selecting a service */
qsort(vec, cnt, sizeof(service_t *), servicecmp);
// qsort(vec, cnt, sizeof(service_t *), servicecmp);
// Skip up to the service that the caller didn't want
// If the sorting above is not stable that might mess up things
@ -371,15 +291,6 @@ service_find(channel_t *ch, unsigned int weight, const char *loginfo,
t = vec[i];
if(t->s_status == SERVICE_RUNNING)
return t;
if(t->s_quality_index(t) < 10) {
if(loginfo != NULL) {
tvhlog(LOG_NOTICE, "Service",
"%s: Skipping \"%s\" -- Quality below 10%%",
loginfo, service_nicename(t));
err = SM_CODE_BAD_SIGNAL;
}
continue;
}
tvhlog(LOG_DEBUG, "Service", "%s: Probing adapter \"%s\" without stealing for service \"%s\"",
loginfo, service_adapter_nicename(t), service_nicename(t));
if((r = service_start(t, 0, 0)) == 0)
@ -487,7 +398,7 @@ service_destroy(service_t *t)
t->s_status = SERVICE_ZOMBIE;
free(t->s_identifier);
free(t->s_uuid);
free(t->s_svcname);
free(t->s_provider);
free(t->s_dvb_charset);
@ -516,17 +427,16 @@ service_destroy(service_t *t)
* Create and initialize a new service struct
*/
service_t *
service_create(const char *identifier, int type, int source_type)
service_create(const char *uuid, int source_type)
{
unsigned int hash = tvh_strhash(identifier, SERVICE_HASH_WIDTH);
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_identifier = strdup(identifier);
t->s_type = type;
t->s_uuid = strdup(uuid);
t->s_source_type = source_type;
t->s_refcount = 1;
t->s_enabled = 1;
@ -555,7 +465,7 @@ service_find_by_identifier(const char *identifier)
lock_assert(&global_lock);
LIST_FOREACH(t, &servicehash[hash], s_hash_link)
if(!strcmp(t->s_identifier, identifier))
if(!strcmp(t->s_uuid, identifier))
break;
return t;
}
@ -1061,25 +971,7 @@ service_component_nicename(elementary_stream_t *st)
const char *
service_adapter_nicename(service_t *t)
{
switch(t->s_type) {
case SERVICE_TYPE_DVB:
if(t->s_dvb_mux_instance)
return t->s_dvb_mux_instance->tdmi_identifier;
else
return "Unknown adapter";
case SERVICE_TYPE_IPTV:
return t->s_iptv_iface;
case SERVICE_TYPE_V4L:
if(t->s_v4l_adapter)
return t->s_v4l_adapter->va_displayname;
else
return "Unknown adapter";
default:
return "Unknown adapter";
}
return "Adapter";
}
const char *
@ -1140,6 +1032,45 @@ service_refresh_channel(service_t *t)
}
/**
*
*/
static int
ssc_cmp(const service_start_cand_t *a,
const service_start_cand_t *b)
{
return a->ssc_prio - b->ssc_prio;
}
/**
*
*/
service_start_cand_t *
service_find_cand(struct service_start_cand_list *sscl,
struct service *s, int instance, int prio)
{
service_start_cand_t *ssc;
LIST_FOREACH(ssc, sscl, ssc_link) {
if(ssc->ssc_s == s && ssc->ssc_instance == instance)
break;
}
if(ssc != NULL) {
ssc = calloc(1, sizeof(service_start_cand_t));
ssc->ssc_s = s;
service_ref(s);
ssc->ssc_instance = instance;
} else {
if(ssc->ssc_prio == prio)
return ssc;
LIST_REMOVE(ssc, ssc_link);
}
ssc->ssc_prio = prio;
LIST_INSERT_SORTED(sscl, ssc, ssc_link, ssc_cmp);
return ssc;
}
/**
* Get the encryption CAID from a service
* only the first CA stream in a service is returned
@ -1174,9 +1105,8 @@ service_is_primary_epg(service_t *svc)
service_t *ret = NULL, *t;
if (!svc || !svc->s_ch) return 0;
LIST_FOREACH(t, &svc->s_ch->ch_services, s_ch_link) {
if (!t->s_dvb_mux_instance) continue;
if (!t->s_enabled || !t->s_dvb_eit_enable) continue;
if (!ret || service_get_prio(t) < service_get_prio(ret))
if (!ret)
ret = t;
}
return !ret ? 0 : (ret->s_dvb_service_id == svc->s_dvb_service_id);

View file

@ -167,6 +167,36 @@ typedef struct elementary_stream {
} elementary_stream_t;
LIST_HEAD(service_start_cand_list, service_start_cand);
/**
*
*/
typedef struct service_start_cand {
LIST_ENTRY(service_start_cand) ssc_link;
int ssc_prio;
struct service *ssc_s; // A reference is held
int ssc_instance; // Discriminator when having multiple adapters, etc
int ssc_error_code; // Set if we deem this cand to be broken
time_t ssc_err_time; // Time we detected it was broken
int ssc_weight; // Highest weight that holds this cand
} service_start_cand_t;
/**
*
*/
service_start_cand_t *service_find_cand(struct service_start_cand_list *sscl,
struct service *s,
int instance,
int prio);
/**
*
*/
@ -174,12 +204,6 @@ typedef struct service {
LIST_ENTRY(service) s_hash_link;
enum {
SERVICE_TYPE_DVB,
SERVICE_TYPE_IPTV,
SERVICE_TYPE_V4L,
} s_type;
enum {
/**
* Transport is idle.
@ -262,6 +286,10 @@ typedef struct service {
LIST_HEAD(, th_subscription) s_subscriptions;
void (*s_enlist)(struct service *s,
struct service_start_cand_list *sscl);
int (*s_start_feed)(struct service *t, unsigned int weight,
int force_start);
@ -273,8 +301,6 @@ typedef struct service {
void (*s_setsourceinfo)(struct service *t, struct source_info *si);
int (*s_quality_index)(struct service *t);
int (*s_grace_period)(struct service *t);
void (*s_dtor)(struct service *t);
@ -282,12 +308,12 @@ typedef struct service {
/*
* Per source type structs
*/
struct th_dvb_mux_instance *s_dvb_mux_instance;
struct dvb_mux *s_dvb_mux;
/**
* Unique identifer (used for storing on disk, etc)
* Unique identifer
*/
char *s_identifier;
char *s_uuid;
/**
* Name usable for displaying to user
@ -520,8 +546,7 @@ unsigned int service_compute_weight(struct service_list *head);
int service_start(service_t *t, unsigned int weight, int force_start);
service_t *service_create(const char *identifier, int type,
int source_type);
service_t *service_create(const char *uuid, int source_type);
void service_unref(service_t *t);

View file

@ -108,7 +108,8 @@ serviceprobe_thread(void *aux)
was_doing_work = 1;
}
checksubscr = !t->s_dvb_mux_instance->tdmi_adapter->tda_skip_checksubscr;
// XXX(dvbreorg)
checksubscr = 1; // !t->s_dvb_mux->tdmi_adapter->tda_skip_checksubscr;
if (checksubscr) {
tvhlog(LOG_INFO, "serviceprobe", "%20s: checking...",
@ -176,10 +177,10 @@ serviceprobe_thread(void *aux)
} else if(t->s_ch == NULL) {
int channum = t->s_channel_number;
const char *str;
#if 0 // XXX(dvbreorg)
if (!channum && t->s_dvb_mux_instance->tdmi_adapter->tda_sidtochan)
channum = t->s_dvb_service_id;
#endif
ch = channel_find_by_name(t->s_svcname, 1, channum);
service_map_channel(t, ch, 1);

View file

@ -214,7 +214,7 @@ hts_settings_load_one(const char *filename)
*
*/
static htsmsg_t *
_hts_settings_load(const char *fullpath)
hts_settings_load_path(const char *fullpath, int depth)
{
char child[256];
struct filebundle_stat st;
@ -237,9 +237,16 @@ _hts_settings_load(const char *fullpath)
for(i = 0; i < n; i++) {
d = namelist[i];
if(d->name[0] != '.') {
snprintf(child, sizeof(child), "%s/%s", fullpath, d->name);
if ((c = hts_settings_load_one(child)))
snprintf(child, sizeof(child), "%s/%s", fullpath, d->name);
if(d->type == FB_DIR && depth > 0) {
c = hts_settings_load_path(child, depth - 1);
} else {
c = hts_settings_load_one(child);
}
if(c != NULL)
htsmsg_add_msg(r, d->name, c);
}
free(d);
}
@ -256,32 +263,56 @@ _hts_settings_load(const char *fullpath)
/**
*
*/
htsmsg_t *
hts_settings_load(const char *pathfmt, ...)
static htsmsg_t *
hts_settings_vload(const char *pathfmt, va_list ap, int depth)
{
htsmsg_t *ret = NULL;
char fullpath[256];
va_list ap;
va_list ap2;
va_copy(ap2, ap);
/* Try normal path */
va_start(ap, pathfmt);
hts_settings_buildpath(fullpath, sizeof(fullpath),
hts_settings_buildpath(fullpath, sizeof(fullpath),
pathfmt, ap, settingspath);
va_end(ap);
ret = _hts_settings_load(fullpath);
ret = hts_settings_load_path(fullpath, depth);
/* Try bundle path */
if (!ret && *pathfmt != '/') {
va_start(ap, pathfmt);
hts_settings_buildpath(fullpath, sizeof(fullpath),
pathfmt, ap, "data/conf");
va_end(ap);
ret = _hts_settings_load(fullpath);
pathfmt, ap2, "data/conf");
ret = hts_settings_load_path(fullpath, depth);
}
return ret;
}
/**
*
*/
htsmsg_t *
hts_settings_load(const char *pathfmt, ...)
{
va_list ap;
va_start(ap, pathfmt);
htsmsg_t *r = hts_settings_vload(pathfmt, ap, 0);
va_end(ap);
return r;
}
/**
*
*/
htsmsg_t *
hts_settings_load_r(int depth, const char *pathfmt, ...)
{
va_list ap;
va_start(ap, pathfmt);
htsmsg_t *r = hts_settings_vload(pathfmt, ap, depth);
va_end(ap);
return r;
}
/**
*
*/

View file

@ -28,6 +28,8 @@ void hts_settings_save(htsmsg_t *record, const char *pathfmt, ...);
htsmsg_t *hts_settings_load(const char *pathfmt, ...);
htsmsg_t *hts_settings_load_r(int depth, const char *pathfmt, ...);
void hts_settings_remove(const char *pathfmt, ...);
const char *hts_settings_get_root(void);

View file

@ -385,14 +385,13 @@ subscription_create_from_channel(channel_t *ch, unsigned int weight,
tvhlog(LOG_INFO, "subscription",
"\"%s\" subscribing on \"%s\", weight: %d, adapter: \"%s\", "
"network: \"%s\", mux: \"%s\", provider: \"%s\", "
"service: \"%s\", quality: %d",
"service: \"%s\"",
s->ths_title, ch->ch_name, weight,
si.si_adapter ?: "<N/A>",
si.si_network ?: "<N/A>",
si.si_mux ?: "<N/A>",
si.si_provider ?: "<N/A>",
si.si_service ?: "<N/A>",
s->ths_service->s_quality_index(s->ths_service));
si.si_service ?: "<N/A>");
service_source_info_free(&si);
}
@ -432,14 +431,13 @@ subscription_create_from_service(service_t *t, const char *name,
tvhlog(LOG_INFO, "subscription",
"\"%s\" direct subscription to adapter: \"%s\", "
"network: \"%s\", mux: \"%s\", provider: \"%s\", "
"service: \"%s\", quality: %d",
"service: \"%s\"",
s->ths_title,
si.si_adapter ?: "<N/A>",
si.si_network ?: "<N/A>",
si.si_mux ?: "<N/A>",
si.si_provider ?: "<N/A>",
si.si_service ?: "<N/A>",
t->s_quality_index(t));
si.si_service ?: "<N/A>");
service_source_info_free(&si);
subscription_link_service(s, t);

View file

@ -56,6 +56,7 @@ typedef struct source_info {
int si_type;
} source_info_t;
static inline void
lock_assert0(pthread_mutex_t *l, const char *file, int line)
{

View file

@ -289,7 +289,7 @@ v4l_service_save(service_t *t)
pthread_mutex_unlock(&t->s_stream_mutex);
hts_settings_save(m, "v4lservices/%s/%s",
va->va_identifier, t->s_identifier);
va->va_identifier, t->s_uuid);
htsmsg_destroy(m);
}
@ -349,7 +349,7 @@ v4l_service_find(v4l_adapter_t *va, const char *id, int create)
return NULL;
LIST_FOREACH(t, &va->va_services, s_group_link)
if(!strcmp(t->s_identifier, id))
if(!strcmp(t->s_uuid, id))
return t;
}
@ -364,7 +364,7 @@ v4l_service_find(v4l_adapter_t *va, const char *id, int create)
va->va_tally = MAX(atoi(id + vaidlen + 1), va->va_tally);
}
t = service_create(id, SERVICE_TYPE_V4L, 0);
t = service_create(id, 0);
t->s_start_feed = v4l_service_start;
t->s_refresh_feed = v4l_service_refresh;

View file

@ -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_identifier);
htsmsg_add_str(r, "id", t->s_uuid);
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

View file

@ -43,6 +43,10 @@
#include "dvb/dvb_preconf.h"
#include "dvr/dvr.h"
#if 0
/**
*
*/
@ -685,6 +689,7 @@ extjs_list_dvb_adapters(htsmsg_t *array)
htsmsg_add_msg(array, NULL, dvb_adapter_build_msg(tda));
}
#endif
/**
*
@ -741,11 +746,12 @@ extjs_dvbnetworks(http_connection_t *hc, const char *remain, void *opaque)
void
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/networks",
NULL, extjs_dvbnetworks, ACCESS_WEB_INTERFACE);
http_path_add("/dvb/adapter",
NULL, extjs_dvbadapter, ACCESS_ADMIN);
@ -767,7 +773,6 @@ extjs_start_dvb(void)
http_path_add("/dvb/addmux",
NULL, extjs_dvb_addmux, ACCESS_ADMIN);
#if 0 // XXX(dvbreorg)
http_path_add("/dvb/copymux",
NULL, extjs_dvb_copymux, ACCESS_ADMIN);
#endif

View file

@ -76,6 +76,7 @@ dumpchannels(htsbuf_queue_t *hq)
}
#if ENABLE_LINUXDVB
#if 0
static void
dumptransports(htsbuf_queue_t *hq, struct service_list *l, int indent)
{
@ -119,6 +120,7 @@ dumptransports(htsbuf_queue_t *hq, struct service_list *l, int indent)
}
}
#endif
@ -126,23 +128,11 @@ static void
dumpdvbadapters(htsbuf_queue_t *hq)
{
th_dvb_adapter_t *tda;
th_dvb_mux_instance_t *tdmi;
outputtitle(hq, 0, "DVB Adapters");
TAILQ_FOREACH(tda, &dvb_adapters, tda_global_link) {
htsbuf_qprintf(hq, "%s (%s)\n", tda->tda_displayname, tda->tda_identifier);
outputtitle(hq, 4, "Multiplexes");
LIST_FOREACH(tdmi, &tda->tda_dn->dn_mux_instances, tdmi_adapter_link) {
char tdminame[64];
dvb_mux_nicename(tdminame, sizeof(tdminame), tdmi);
htsbuf_qprintf(hq, " %s (%s)\n",
tdminame, tdmi->tdmi_identifier);
htsbuf_qprintf(hq, "\n");
dumptransports(hq, &tdmi->tdmi_mux->dm_services, 8);
}
}
}
#endif

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);
s = dvb_subscription_create_from_tdmi(tdmi, "HTTP", &sq.sq_st);
name = strdupa(tdmi->tdmi_identifier);
name = strdupa(tdmi->tdmi_mux->dm_uuid);
pthread_mutex_unlock(&global_lock);
http_stream_run(hc, &sq, name, MC_PASS);
pthread_mutex_lock(&global_lock);
@ -723,7 +723,7 @@ http_stream(http_connection_t *hc, const char *remain, void *opaque)
} else if(!strcmp(components[0], "service")) {
service = service_find_by_identifier(components[1]);
} else if(!strcmp(components[0], "mux")) {
tdmi = dvb_mux_find_by_identifier(components[1]);
tdmi = NULL; // dvb_mux_find_by_identifier(components[1]);
}
if(ch != NULL) {