From 607010c3df9e2daa947c603e8def7b21ea3226cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20=C3=96man?= Date: Fri, 16 Nov 2012 09:22:24 +0100 Subject: [PATCH 01/31] dvb: Remove the idlescan feature --- src/dvb/dvb.h | 13 +--- src/dvb/dvb_adapter.c | 98 ++++++++++++------------------ src/dvb/dvb_fe.c | 15 ++--- src/dvb/dvb_multiplex.c | 12 ---- src/webui/extjs_dvb.c | 4 -- src/webui/static/app/dvb.js | 8 +-- src/webui/static/app/status.js | 4 ++ src/webui/static/app/tvadapters.js | 2 +- 8 files changed, 55 insertions(+), 101 deletions(-) diff --git a/src/dvb/dvb.h b/src/dvb/dvb.h index 92fcaf2c..beca3dbb 100644 --- a/src/dvb/dvb.h +++ b/src/dvb/dvb.h @@ -177,23 +177,17 @@ typedef struct dvb_table_feed { */ #define TDA_MUX_HASH_WIDTH 101 -#define TDA_SCANQ_BAD 0 ///< Bad muxes (monitor quality) -#define TDA_SCANQ_OK 1 ///< OK muxes -#define TDA_SCANQ_NUM 2 - typedef struct th_dvb_adapter { TAILQ_ENTRY(th_dvb_adapter) tda_global_link; struct th_dvb_mux_instance_list tda_muxes; - struct th_dvb_mux_instance_queue tda_scan_queues[TDA_SCANQ_NUM]; - int tda_scan_selector; - struct th_dvb_mux_instance_queue tda_initial_scan_queue; int tda_initial_num_mux; th_dvb_mux_instance_t *tda_mux_current; + char *tda_tune_reason; // Reason for last tune th_dvb_mux_instance_t *tda_mux_epg; @@ -202,7 +196,6 @@ typedef struct th_dvb_adapter { const char *tda_rootpath; char *tda_identifier; uint32_t tda_autodiscovery; - uint32_t tda_idlescan; uint32_t tda_idleclose; uint32_t tda_skip_initialscan; uint32_t tda_skip_checksubscr; @@ -344,8 +337,6 @@ void dvb_adapter_set_auto_discovery(th_dvb_adapter_t *tda, int on); void dvb_adapter_set_skip_initialscan(th_dvb_adapter_t *tda, int on); -void dvb_adapter_set_idlescan(th_dvb_adapter_t *tda, int on); - void dvb_adapter_set_skip_checksubscr(th_dvb_adapter_t *tda, int on); void dvb_adapter_set_qmon(th_dvb_adapter_t *tda, int on); @@ -450,8 +441,6 @@ const char *dvb_mux_add_by_params(th_dvb_adapter_t *tda, int dvb_mux_copy(th_dvb_adapter_t *dst, th_dvb_mux_instance_t *tdmi_src, dvb_satconf_t *satconf); -void dvb_mux_add_to_scan_queue (th_dvb_mux_instance_t *tdmi); - th_dvb_mux_instance_t *dvb_mux_find (th_dvb_adapter_t *tda, const char *netname, uint16_t onid, uint16_t tsid, int enabled ); diff --git a/src/dvb/dvb_adapter.c b/src/dvb/dvb_adapter.c index 1847304a..8a088340 100644 --- a/src/dvb/dvb_adapter.c +++ b/src/dvb/dvb_adapter.c @@ -56,12 +56,9 @@ static void *dvb_adapter_input_dvr(void *aux); static th_dvb_adapter_t * tda_alloc(void) { - int i; th_dvb_adapter_t *tda = calloc(1, sizeof(th_dvb_adapter_t)); pthread_mutex_init(&tda->tda_delivery_mutex, NULL); - for (i = 0; i < TDA_SCANQ_NUM; i++ ) - TAILQ_INIT(&tda->tda_scan_queues[i]); TAILQ_INIT(&tda->tda_initial_scan_queue); TAILQ_INIT(&tda->tda_satconfs); streaming_pad_init(&tda->tda_streaming_pad); @@ -82,7 +79,6 @@ tda_save(th_dvb_adapter_t *tda) htsmsg_add_str(m, "type", dvb_adaptertype_to_str(tda->tda_type)); htsmsg_add_str(m, "displayname", tda->tda_displayname); htsmsg_add_u32(m, "autodiscovery", tda->tda_autodiscovery); - htsmsg_add_u32(m, "idlescan", tda->tda_idlescan); 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); @@ -161,24 +157,6 @@ dvb_adapter_set_skip_initialscan(th_dvb_adapter_t *tda, int on) } -/** - * - */ -void -dvb_adapter_set_idlescan(th_dvb_adapter_t *tda, int on) -{ - if(tda->tda_idlescan == on) - return; - - lock_assert(&global_lock); - - tvhlog(LOG_NOTICE, "dvb", "Adapter \"%s\" idle mux scanning set to: %s", - tda->tda_displayname, on ? "On" : "Off"); - - tda->tda_idlescan = on; - tda_save(tda); -} - /** * */ @@ -481,7 +459,7 @@ tda_add(int adapter_num) free(tda); return; } - if (tda->tda_idlescan || !tda->tda_idleclose) + if (!tda->tda_idleclose) tda->tda_fe_fd = fe; else close(fe); @@ -499,7 +477,6 @@ tda_add(int adapter_num) tda->tda_identifier = strdup(buf); tda->tda_autodiscovery = tda->tda_type != FE_QPSK; - tda->tda_idlescan = 1; tda->tda_sat = tda->tda_type == FE_QPSK; @@ -549,7 +526,6 @@ tda_add_from_file(const char *filename) tda->tda_identifier = strdup(buf); tda->tda_autodiscovery = 0; - tda->tda_idlescan = 0; tda->tda_sat = 0; @@ -608,30 +584,33 @@ dvb_adapter_start ( th_dvb_adapter_t *tda ) void dvb_adapter_stop ( th_dvb_adapter_t *tda ) { + assert(tda->tda_mux_current == NULL); + /* Poweroff */ dvb_adapter_poweroff(tda); - /* Don't stop/close */ - if (!tda->tda_idleclose) return; + if(tda->tda_idleclose) { - /* Close front end */ - if (tda->tda_fe_fd != -1) { - tvhlog(LOG_DEBUG, "dvb", "%s closing frontend", tda->tda_rootpath); - close(tda->tda_fe_fd); - tda->tda_fe_fd = -1; - } + /* Close front end */ + if (tda->tda_fe_fd != -1) { + tvhlog(LOG_DEBUG, "dvb", "%s closing frontend", tda->tda_rootpath); + close(tda->tda_fe_fd); + tda->tda_fe_fd = -1; + } - /* Stop DVR thread */ - if (tda->tda_dvr_pipe[0] != -1) { - tvhlog(LOG_DEBUG, "dvb", "%s stopping thread", tda->tda_rootpath); - int err = write(tda->tda_dvr_pipe[1], "", 1); - assert(err != -1); - pthread_join(tda->tda_dvr_thread, NULL); - close(tda->tda_dvr_pipe[0]); - close(tda->tda_dvr_pipe[1]); - tda->tda_dvr_pipe[0] = -1; - tvhlog(LOG_DEBUG, "dvb", "%s stopped thread", tda->tda_rootpath); + /* Stop DVR thread */ + if (tda->tda_dvr_pipe[0] != -1) { + tvhlog(LOG_DEBUG, "dvb", "%s stopping thread", tda->tda_rootpath); + int err = write(tda->tda_dvr_pipe[1], "", 1); + assert(err != -1); + pthread_join(tda->tda_dvr_thread, NULL); + close(tda->tda_dvr_pipe[0]); + close(tda->tda_dvr_pipe[1]); + tda->tda_dvr_pipe[0] = -1; + tvhlog(LOG_DEBUG, "dvb", "%s stopped thread", tda->tda_rootpath); + } } + dvb_adapter_notify(tda); } /** @@ -686,7 +665,6 @@ dvb_adapter_init(uint32_t adapter_mask, const char *rawfile) tda->tda_displayname = strdup(name); htsmsg_get_u32(c, "autodiscovery", &tda->tda_autodiscovery); - htsmsg_get_u32(c, "idlescan", &tda->tda_idlescan); 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); @@ -725,7 +703,6 @@ dvb_adapter_mux_scanner(void *aux) { th_dvb_adapter_t *tda = aux; th_dvb_mux_instance_t *tdmi; - int i; if(tda->tda_rootpath == NULL) return; // No hardware @@ -770,20 +747,6 @@ dvb_adapter_mux_scanner(void *aux) dvb_fe_tune(tda->tda_mux_epg, "EPG scan"); return; - /* Normal */ - } else if (tda->tda_idlescan) { - - /* Alternate queue */ - for(i = 0; i < TDA_SCANQ_NUM; i++) { - tda->tda_scan_selector++; - if (tda->tda_scan_selector == TDA_SCANQ_NUM) - tda->tda_scan_selector = 0; - tdmi = TAILQ_FIRST(&tda->tda_scan_queues[tda->tda_scan_selector]); - if (tdmi) { - dvb_fe_tune(tdmi, "Autoscan"); - return; - } - } } /* Ensure we stop current mux and power off (if required) */ @@ -833,6 +796,7 @@ dvb_adapter_destroy(th_dvb_adapter_t *tda) free(tda->tda_identifier); free(tda->tda_displayname); + free(tda->tda_tune_reason); free(tda); @@ -1052,6 +1016,22 @@ dvb_adapter_build_msg(th_dvb_adapter_t *tda) htsmsg_add_u32(m, "ber", tdmi->tdmi_ber); htsmsg_add_u32(m, "unc", tdmi->tdmi_unc); htsmsg_add_u32(m, "uncavg", tdmi->tdmi_unc_avg); + + htsmsg_add_str(m, "reason", tda->tda_tune_reason); + } else { + htsmsg_add_str(m, "currentMux", ""); + + htsmsg_add_u32(m, "signal", 0); + htsmsg_add_u32(m, "snr", 0); + htsmsg_add_u32(m, "ber", 0); + htsmsg_add_u32(m, "unc", 0); + htsmsg_add_u32(m, "uncavg", 0); + + if(tda->tda_fe_fd == -1) { + htsmsg_add_str(m, "reason", "Closed"); + } else { + htsmsg_add_str(m, "reason", "Idle"); + } } if(tda->tda_rootpath == NULL) diff --git a/src/dvb/dvb_fe.c b/src/dvb/dvb_fe.c index 2731e13a..9660ce0a 100644 --- a/src/dvb/dvb_fe.c +++ b/src/dvb/dvb_fe.c @@ -277,12 +277,8 @@ dvb_fe_stop(th_dvb_mux_instance_t *tdmi, int retune) assert(tdmi->tdmi_scan_queue == NULL); - if(tdmi->tdmi_enabled) { - dvb_mux_add_to_scan_queue(tdmi); - } - epggrab_mux_stop(tdmi, 0); - + time(&tdmi->tdmi_lost_adapter); if (!retune) { @@ -411,9 +407,14 @@ dvb_fe_tune(th_dvb_mux_instance_t *tdmi, const char *reason) lock_assert(&global_lock); - if(tda->tda_mux_current == tdmi) + free(tda->tda_tune_reason); + tda->tda_tune_reason = strdup(reason); + + if(tda->tda_mux_current == tdmi) { + dvb_adapter_notify(tda); return 0; - + } + if(tdmi->tdmi_scan_queue != NULL) { TAILQ_REMOVE(tdmi->tdmi_scan_queue, tdmi, tdmi_scan_link); tdmi->tdmi_scan_queue = NULL; diff --git a/src/dvb/dvb_multiplex.c b/src/dvb/dvb_multiplex.c index 1ac5caf1..7f8a70b7 100644 --- a/src/dvb/dvb_multiplex.c +++ b/src/dvb/dvb_multiplex.c @@ -299,8 +299,6 @@ dvb_mux_create(th_dvb_adapter_t *tda, const struct dvb_mux_conf *dmc, tda->tda_initial_num_mux++; tdmi->tdmi_table_initial = 1; mux_link_initial(tda, tdmi); - } else { - dvb_mux_add_to_scan_queue(tdmi); } } @@ -1255,16 +1253,6 @@ dvb_mux_copy(th_dvb_adapter_t *dst, th_dvb_mux_instance_t *tdmi_src, return 0; } -void dvb_mux_add_to_scan_queue ( th_dvb_mux_instance_t *tdmi ) -{ - int ti; - th_dvb_adapter_t *tda = tdmi->tdmi_adapter; - ti = tdmi->tdmi_quality == 100 ? TDA_SCANQ_OK - : TDA_SCANQ_BAD; - tdmi->tdmi_scan_queue = &tda->tda_scan_queues[ti]; - TAILQ_INSERT_TAIL(tdmi->tdmi_scan_queue, tdmi, tdmi_scan_link); -} - th_dvb_mux_instance_t *dvb_mux_find ( th_dvb_adapter_t *tda, const char *netname, uint16_t onid, uint16_t tsid, int enabled ) diff --git a/src/webui/extjs_dvb.c b/src/webui/extjs_dvb.c index d1ce5b15..443bf22f 100644 --- a/src/webui/extjs_dvb.c +++ b/src/webui/extjs_dvb.c @@ -149,7 +149,6 @@ extjs_dvbadapter(http_connection_t *hc, const char *remain, void *opaque) 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, "idlescan", tda->tda_idlescan); 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); @@ -179,9 +178,6 @@ extjs_dvbadapter(http_connection_t *hc, const char *remain, void *opaque) s = http_arg_get(&hc->hc_req_args, "skip_initialscan"); dvb_adapter_set_skip_initialscan(tda, !!s); - s = http_arg_get(&hc->hc_req_args, "idlescan"); - dvb_adapter_set_idlescan(tda, !!s); - s = http_arg_get(&hc->hc_req_args, "idleclose"); dvb_adapter_set_idleclose(tda, !!s); diff --git a/src/webui/static/app/dvb.js b/src/webui/static/app/dvb.js index 746ac7d6..565f9eee 100644 --- a/src/webui/static/app/dvb.js +++ b/src/webui/static/app/dvb.js @@ -1086,7 +1086,7 @@ tvheadend.dvb_adapter_general = function(adapterData, satConfStore) { var confreader = new Ext.data.JsonReader({ root : 'dvbadapters' - }, [ 'name', 'automux', 'skip_initialscan', 'idlescan', 'diseqcversion', + }, [ 'name', 'automux', 'skip_initialscan', 'diseqcversion', 'diseqcrepeats', 'qmon', 'skip_checksubscr', 'poweroff', 'sidtochan', 'nitoid', 'extrapriority', ,'disable_pmt_monitor', 'full_mux_rx', 'idleclose' ]); @@ -1115,10 +1115,6 @@ tvheadend.dvb_adapter_general = function(adapterData, satConfStore) { fieldLabel : 'Skip initial scan', name : 'skip_initialscan' }), - new Ext.form.Checkbox({ - fieldLabel : 'Idle scanning', - name : 'idlescan' - }), new Ext.form.Checkbox({ fieldLabel : 'Close device handle when idle', name : 'idleclose' @@ -1235,7 +1231,7 @@ tvheadend.dvb_adapter_general = function(adapterData, satConfStore) { + '

Symbolrate range:

' + '{symrateMin} Baud - {symrateMax} Baud' + '

Status

' - + '

Currently tuned to:

{currentMux} ' + + '

Currently tuned to:

{currentMux} ({reason})' + '

Services:

{services}' + '

Muxes:

{muxes}' + '

Muxes awaiting initial scan:

{initialMuxes}' + '

Signal Strength:

{signal}%' diff --git a/src/webui/static/app/status.js b/src/webui/static/app/status.js index bf3c2cbb..e0549048 100644 --- a/src/webui/static/app/status.js +++ b/src/webui/static/app/status.js @@ -160,6 +160,10 @@ tvheadend.status_adapters = function() { width : 100, header : "Currently tuned to", dataIndex : 'currentMux' + },{ + width : 50, + header : "Used for", + dataIndex : 'reason' },{ width : 50, header : "Bit error rate", diff --git a/src/webui/static/app/tvadapters.js b/src/webui/static/app/tvadapters.js index d6928ed8..1644835f 100644 --- a/src/webui/static/app/tvadapters.js +++ b/src/webui/static/app/tvadapters.js @@ -7,7 +7,7 @@ tvheadend.tvAdapterStore = new Ext.data.JsonStore({ fields : [ 'identifier', 'type', 'name', 'path', 'devicename', 'hostconnection', 'currentMux', 'services', 'muxes', 'initialMuxes', 'satConf', 'deliverySystem', 'freqMin', 'freqMax', 'freqStep', - 'symrateMin', 'symrateMax', 'signal', 'snr', 'ber', 'unc', 'uncavg'], + 'symrateMin', 'symrateMax', 'signal', 'snr', 'ber', 'unc', 'uncavg', 'reason'], autoLoad : true, url : 'tv/adapter' }); From b14e4ddb62c1cd6cfda343838b958e6f1af0e35d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20=C3=96man?= Date: Fri, 16 Nov 2012 09:45:15 +0100 Subject: [PATCH 02/31] dvb: Don't do initial scan on startup --- src/dvb/dvb_multiplex.c | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/src/dvb/dvb_multiplex.c b/src/dvb/dvb_multiplex.c index 7f8a70b7..798b876d 100644 --- a/src/dvb/dvb_multiplex.c +++ b/src/dvb/dvb_multiplex.c @@ -294,12 +294,10 @@ dvb_mux_create(th_dvb_adapter_t *tda, const struct dvb_mux_conf *dmc, dvb_service_load(tdmi, identifier); dvb_mux_notify(tdmi); - if(enabled) { - if(initialscan) { - tda->tda_initial_num_mux++; - tdmi->tdmi_table_initial = 1; - mux_link_initial(tda, tdmi); - } + if(enabled && initialscan) { + tda->tda_initial_num_mux++; + tdmi->tdmi_table_initial = 1; + mux_link_initial(tda, tdmi); } return tdmi; @@ -783,12 +781,9 @@ tdmi_create_by_msg(th_dvb_adapter_t *tda, htsmsg_t *m, const char *identifier) dmc.dmc_satconf = NULL; initscan = htsmsg_get_u32_or_default(m, "initialscan", 1); - if (!initscan && !tda->tda_skip_initialscan) - initscan = 1; - tdmi = dvb_mux_create(tda, &dmc, onid, tsid, htsmsg_get_str(m, "network"), NULL, enabled, - initscan, + initscan, identifier, NULL); if(tdmi != NULL) { From 2ebf80876567c6207e34d353d3b8954dc06cebb0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20=C3=96man?= Date: Fri, 16 Nov 2012 09:49:17 +0100 Subject: [PATCH 03/31] dvb: Remove tdmi_got_adapter and tdmi_lost_adapter (unused) --- src/dvb/dvb.h | 3 --- src/dvb/dvb_fe.c | 2 -- 2 files changed, 5 deletions(-) diff --git a/src/dvb/dvb.h b/src/dvb/dvb.h index beca3dbb..0a223df8 100644 --- a/src/dvb/dvb.h +++ b/src/dvb/dvb.h @@ -128,9 +128,6 @@ typedef struct th_dvb_mux_instance { int tdmi_enabled; - time_t tdmi_got_adapter; - time_t tdmi_lost_adapter; - dvb_mux_conf_t tdmi_conf; /* Linked if tdmi_conf.dmc_satconf != NULL */ diff --git a/src/dvb/dvb_fe.c b/src/dvb/dvb_fe.c index 9660ce0a..d8b5ba27 100644 --- a/src/dvb/dvb_fe.c +++ b/src/dvb/dvb_fe.c @@ -279,8 +279,6 @@ dvb_fe_stop(th_dvb_mux_instance_t *tdmi, int retune) epggrab_mux_stop(tdmi, 0); - time(&tdmi->tdmi_lost_adapter); - if (!retune) { gtimer_disarm(&tda->tda_fe_monitor_timer); dvb_adapter_stop(tda); From 230032b3801eb035e6525395ace597056d9cd4ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20=C3=96man?= Date: Fri, 16 Nov 2012 09:50:38 +0100 Subject: [PATCH 04/31] dvb: Remove tdmi_time (unused) --- src/dvb/dvb.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/dvb/dvb.h b/src/dvb/dvb.h index 0a223df8..94b2616b 100644 --- a/src/dvb/dvb.h +++ b/src/dvb/dvb.h @@ -105,9 +105,6 @@ typedef struct th_dvb_mux_instance { uint32_t tdmi_fec_err_histogram[TDMI_FEC_ERR_HISTOGRAM_SIZE]; int tdmi_fec_err_ptr; - time_t tdmi_time; - - LIST_HEAD(, th_dvb_table) tdmi_tables; int tdmi_num_tables; From ba59e82ad400105ea3903965e15c23387ca36622 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20=C3=96man?= Date: Fri, 16 Nov 2012 10:03:31 +0100 Subject: [PATCH 05/31] dvb: Make sure to remember initialscan after restart --- src/dvb/dvb_multiplex.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/dvb/dvb_multiplex.c b/src/dvb/dvb_multiplex.c index 798b876d..7efb6f36 100644 --- a/src/dvb/dvb_multiplex.c +++ b/src/dvb/dvb_multiplex.c @@ -282,6 +282,7 @@ dvb_mux_create(th_dvb_adapter_t *tda, const struct dvb_mux_conf *dmc, LIST_INSERT_HEAD(&tda->tda_mux_list, tdmi, tdmi_adapter_hash_link); LIST_INSERT_HEAD(&tda->tda_muxes, tdmi, tdmi_adapter_link); + tdmi->tdmi_table_initial = initialscan; if(source != NULL) { dvb_mux_nicename(buf, sizeof(buf), tdmi); @@ -294,9 +295,8 @@ dvb_mux_create(th_dvb_adapter_t *tda, const struct dvb_mux_conf *dmc, dvb_service_load(tdmi, identifier); dvb_mux_notify(tdmi); - if(enabled && initialscan) { + if(enabled && tdmi->tdmi_table_initial) { tda->tda_initial_num_mux++; - tdmi->tdmi_table_initial = 1; mux_link_initial(tda, tdmi); } @@ -780,7 +780,7 @@ tdmi_create_by_msg(th_dvb_adapter_t *tda, htsmsg_t *m, const char *identifier) else dmc.dmc_satconf = NULL; - initscan = htsmsg_get_u32_or_default(m, "initialscan", 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, From 5716eaebf66d1587c65f1bc938ab94c2f2e8fb50 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20=C3=96man?= Date: Fri, 16 Nov 2012 11:41:29 +0100 Subject: [PATCH 06/31] webui: Upgrade CheckColumn to extjs 3.4 --- src/webui/extjs.c | 1 + src/webui/static/app/acleditor.js | 136 ++++++++++---------- src/webui/static/app/capmteditor.js | 29 ++--- src/webui/static/app/cteditor.js | 88 +++++++------ src/webui/static/app/cwceditor.js | 41 +++--- src/webui/static/app/dvb.js | 43 +++---- src/webui/static/app/dvr.js | 17 +-- src/webui/static/app/extensions.js | 35 ----- src/webui/static/app/iptv.js | 14 +- src/webui/static/checkcolumn/CheckColumn.js | 71 ++++++++++ 10 files changed, 251 insertions(+), 224 deletions(-) create mode 100644 src/webui/static/checkcolumn/CheckColumn.js diff --git a/src/webui/extjs.c b/src/webui/extjs.c index 10829e2e..9ceef1df 100644 --- a/src/webui/extjs.c +++ b/src/webui/extjs.c @@ -111,6 +111,7 @@ extjs_root(http_connection_t *hc, const char *remain, void *opaque) extjs_load(hq, "static/lovcombo/lovcombo-all.js"); extjs_load(hq, "static/multiselect/multiselect.js"); extjs_load(hq, "static/multiselect/ddview.js"); + extjs_load(hq, "static/checkcolumn/CheckColumn.js"); /** * Create a namespace for our app diff --git a/src/webui/static/app/acleditor.js b/src/webui/static/app/acleditor.js index f1dee2a6..78c05363 100644 --- a/src/webui/static/app/acleditor.js +++ b/src/webui/static/app/acleditor.js @@ -1,77 +1,73 @@ tvheadend.acleditor = function() { var fm = Ext.form; - var enabledColumn = new Ext.grid.CheckColumn({ - header : "Enabled", - dataIndex : 'enabled', - width : 60 - }); + var cm = new Ext.grid.ColumnModel({ + defaultSortable: true, - var streamingColumn = new Ext.grid.CheckColumn({ - header : "Streaming", - dataIndex : 'streaming', - width : 100 - }); + columns : [{ + xtype: 'checkcolumn', + header : "Enabled", + dataIndex : 'enabled', + width : 60 + }, { + header : "Username", + dataIndex : 'username', + editor : new fm.TextField({ + allowBlank : false + }) + }, { + header : "Password", + dataIndex : 'password', + renderer : function(value, metadata, record, row, col, store) { + return 'Hidden'; + }, + editor : new fm.TextField({ + allowBlank : false + }) + }, { + header : "Prefix", + dataIndex : 'prefix', + editor : new fm.TextField({ + allowBlank : false + }) + }, { + xtype: 'checkcolumn', + header : "Streaming", + dataIndex : 'streaming', + width : 100 + }, { + xtype: 'checkcolumn', + header : "Video Recorder", + dataIndex : 'dvr', + width : 100 + }, { + xtype: 'checkcolumn', + header : "All Configs (VR)", + dataIndex : 'dvrallcfg', + width : 100 + }, { + xtype: 'checkcolumn', + header : "Web Interface", + dataIndex : 'webui', + width : 100 + }, { + xtype: 'checkcolumn', + header : "Admin", + dataIndex : 'admin', + width : 100 + }, { + header : "Comment", + dataIndex : 'comment', + width : 400, + editor : new fm.TextField({}) + }]}); - var dvrColumn = new Ext.grid.CheckColumn({ - header : "Video Recorder", - dataIndex : 'dvr', - width : 100 - }); + var UserRecord = Ext.data.Record.create( + [ 'enabled', 'streaming', 'dvr', 'dvrallcfg', 'admin', 'webui', 'username', + 'prefix', 'password', 'comment' + ]); - var dvrallcfgColumn = new Ext.grid.CheckColumn({ - header : "All Configs (VR)", - dataIndex : 'dvrallcfg', - width : 100 - }); - - var webuiColumn = new Ext.grid.CheckColumn({ - header : "Web Interface", - dataIndex : 'webui', - width : 100 - }); - - var adminColumn = new Ext.grid.CheckColumn({ - header : "Admin", - dataIndex : 'admin', - width : 100 - }); - - var cm = new Ext.grid.ColumnModel({ - defaultSortable: true, - columns : [ enabledColumn, { - header : "Username", - dataIndex : 'username', - editor : new fm.TextField({ - allowBlank : false - }) - }, { - header : "Password", - dataIndex : 'password', - renderer : function(value, metadata, record, row, col, store) { - return 'Hidden'; - }, - editor : new fm.TextField({ - allowBlank : false - }) - }, { - header : "Prefix", - dataIndex : 'prefix', - editor : new fm.TextField({ - allowBlank : false - }) - }, streamingColumn, dvrColumn, dvrallcfgColumn, webuiColumn, adminColumn, { - header : "Comment", - dataIndex : 'comment', - width : 400, - editor : new fm.TextField({}) - } ]}); - - var UserRecord = Ext.data.Record.create([ 'enabled', 'streaming', 'dvr', - 'dvrallcfg', 'admin', 'webui', 'username', 'prefix', 'password', - 'comment' ]); - - return new tvheadend.tableEditor('Access control', 'accesscontrol', cm, - UserRecord, [ enabledColumn, streamingColumn, dvrColumn, dvrallcfgColumn, - webuiColumn, adminColumn ], null, 'config_access.html', 'group'); + return new tvheadend.tableEditor('Access control', 'accesscontrol', cm, + UserRecord, [], null, 'config_access.html', + 'group'); } diff --git a/src/webui/static/app/capmteditor.js b/src/webui/static/app/capmteditor.js index 6f0c73ea..a5928647 100644 --- a/src/webui/static/app/capmteditor.js +++ b/src/webui/static/app/capmteditor.js @@ -1,18 +1,6 @@ tvheadend.capmteditor = function() { var fm = Ext.form; - var enabledColumn = new Ext.grid.CheckColumn({ - header : "Enabled", - dataIndex : 'enabled', - width : 60 - }); - - var oscamColumn = new Ext.grid.CheckColumn({ - header : "OSCam mode", - dataIndex : 'oscam', - width : 60 - }); - function setMetaAttr(meta, record) { var enabled = record.get('enabled'); if (!enabled) return; @@ -28,7 +16,12 @@ tvheadend.capmteditor = function() { var cm = new Ext.grid.ColumnModel({ defaultSortable: true, - columns: [ enabledColumn, { + columns: [ { + xtype: 'checkcolumn', + header : "Enabled", + dataIndex : 'enabled', + width : 60 + }, { header : "Camd.socket Filename", dataIndex : 'camdfilename', width : 200, @@ -49,7 +42,13 @@ tvheadend.capmteditor = function() { editor : new fm.TextField({ allowBlank : false }) - }, oscamColumn, { + }, { + xtype: 'checkcolumn', + header : "OSCam mode", + dataIndex : 'oscam', + width : 60 + + } , { header : "Comment", dataIndex : 'comment', width : 400, @@ -83,5 +82,5 @@ tvheadend.capmteditor = function() { }); return new tvheadend.tableEditor('Capmt Connections', 'capmt', cm, rec, - [ enabledColumn, oscamColumn ], store, 'config_capmt.html', 'key'); + [ ], store, 'config_capmt.html', 'key'); } diff --git a/src/webui/static/app/cteditor.js b/src/webui/static/app/cteditor.js index 414730ba..7cbda3d4 100644 --- a/src/webui/static/app/cteditor.js +++ b/src/webui/static/app/cteditor.js @@ -1,51 +1,49 @@ tvheadend.cteditor = function() { - var fm = Ext.form; + var fm = Ext.form; - var enabledColumn = new Ext.grid.CheckColumn({ - header : "Enabled", - dataIndex : 'enabled', - width : 60 - }); - var internalColumn = new Ext.grid.CheckColumn({ - header : "Internal", - dataIndex : 'internal', - width : 100 - }); + var cm = new Ext.grid.ColumnModel({ + defaultSortable: true, + columns : [{ + xtype: 'checkcolumn', + header : "Enabled", + dataIndex : 'enabled', + width : 60 + } , { + header : "Name", + dataIndex : 'name', + editor : new fm.TextField({ + allowBlank : false + }) + }, { + xtype: 'checkcolumn', + header : "Internal", + dataIndex : 'internal', + width : 100 + }, { + header : "Icon (full URL)", + dataIndex : 'icon', + width : 400, + editor : new fm.TextField({}) + }, { + xtype: 'checkcolumn', + header : "Icon has title", + dataIndex : 'titledIcon', + width : 100, + tooltip : 'Set this if the supplied icon has a title embedded. ' + + 'This will tell displaying application not to superimpose title ' + + 'on top of logo.' + }, { + header : "Comment", + dataIndex : 'comment', + width : 400, + editor : new fm.TextField({}) + } ]}); - var titledIconColumn = new Ext.grid.CheckColumn({ - header : "Icon has title", - dataIndex : 'titledIcon', - width : 100, - tooltip : 'Set this if the supplied icon has a title embedded. ' - + 'This will tell displaying application not to superimpose title ' - + 'on top of logo.' - }); + var ChannelTagRecord = Ext.data.Record.create([ + 'enabled', 'name', 'internal', 'icon', 'comment', 'titledIcon' ]); - var cm = new Ext.grid.ColumnModel({ - defaultSortable: true, - columns : [ enabledColumn, { - header : "Name", - dataIndex : 'name', - editor : new fm.TextField({ - allowBlank : false - }) - }, internalColumn, { - header : "Icon (full URL)", - dataIndex : 'icon', - width : 400, - editor : new fm.TextField({}) - }, titledIconColumn, { - header : "Comment", - dataIndex : 'comment', - width : 400, - editor : new fm.TextField({}) - } ]}); - - var ChannelTagRecord = Ext.data.Record.create([ 'enabled', 'name', - 'internal', 'icon', 'comment', 'titledIcon' ]); - - return new tvheadend.tableEditor('Channel Tags', 'channeltags', cm, - ChannelTagRecord, [ enabledColumn, internalColumn, titledIconColumn ], - null, 'config_tags.html', 'tags'); + return new tvheadend.tableEditor('Channel Tags', 'channeltags', cm, + ChannelTagRecord, [], + null, 'config_tags.html', 'tags'); } diff --git a/src/webui/static/app/cwceditor.js b/src/webui/static/app/cwceditor.js index 52d82455..1a96ee2d 100644 --- a/src/webui/static/app/cwceditor.js +++ b/src/webui/static/app/cwceditor.js @@ -1,24 +1,6 @@ tvheadend.cwceditor = function() { var fm = Ext.form; - var enabledColumn = new Ext.grid.CheckColumn({ - header : "Enabled", - dataIndex : 'enabled', - width : 60 - }); - - var emmColumn = new Ext.grid.CheckColumn({ - header : "Update Card", - dataIndex : 'emm', - width : 100 - }); - - var emmexColumn = new Ext.grid.CheckColumn({ - header : "Update One", - dataIndex : 'emmex', - width : 100 - }); - function setMetaAttr(meta, record) { var enabled = record.get('enabled'); if (!enabled) return; @@ -34,7 +16,12 @@ tvheadend.cwceditor = function() { var cm = new Ext.grid.ColumnModel({ defaultSortable: true, - columns : [ enabledColumn, { + columns : [ { + xtype: 'checkcolumn', + header : "Enabled", + dataIndex : 'enabled', + width : 60 + }, { header : "Hostname", dataIndex : 'hostname', width : 200, @@ -86,7 +73,17 @@ tvheadend.cwceditor = function() { editor : new fm.TextField({ allowBlank : false }) - }, emmColumn, emmexColumn, { + }, { + xtype: 'checkcolumn', + header : "Update Card", + dataIndex : 'emm', + width : 100 + }, { + xtype: 'checkcolumn', + header : "Update One", + dataIndex : 'emmex', + width : 100 + }, { header : "Comment", dataIndex : 'comment', width : 400, @@ -112,8 +109,8 @@ tvheadend.cwceditor = function() { } }); - var grid = new tvheadend.tableEditor('Code Word Client', 'cwc', cm, rec, [ - enabledColumn, emmColumn, emmexColumn ], store, 'config_cwc.html', 'key'); + var grid = new tvheadend.tableEditor('Code Word Client', 'cwc', cm, rec, [], + store, 'config_cwc.html', 'key'); tvheadend.comet.on('cwcStatus', function(msg) { var rec = store.getById(msg.id); diff --git a/src/webui/static/app/dvb.js b/src/webui/static/app/dvb.js index 565f9eee..3f1ccb0d 100644 --- a/src/webui/static/app/dvb.js +++ b/src/webui/static/app/dvb.js @@ -7,12 +7,6 @@ tvheadend.dvb_muxes = function(adapterData, satConfStore) { var fm = Ext.form; - var enabledColumn = new Ext.grid.CheckColumn({ - header : "Enabled", - dataIndex : 'enabled', - width : 40 - }); - var qualityColumn = new Ext.ux.grid.ProgressColumn({ header : "Quality", dataIndex : 'quality', @@ -23,7 +17,13 @@ tvheadend.dvb_muxes = function(adapterData, satConfStore) { var cmlist = Array(); - cmlist.push(enabledColumn, { + cmlist.push({ + xtype: 'checkcolumn', + header : "Enabled", + dataIndex : 'enabled', + width : 40 + + }, { header : "Network", dataIndex : 'network', width : 200 @@ -352,7 +352,7 @@ tvheadend.dvb_muxes = function(adapterData, satConfStore) { var grid = new Ext.grid.EditorGridPanel({ stripeRows : true, title : 'Multiplexes', - plugins : [ enabledColumn, qualityColumn ], + plugins : [ qualityColumn ], store : store, clicksToEdit : 2, cm : cm, @@ -379,17 +379,6 @@ tvheadend.dvb_services = function(adapterId) { var fm = Ext.form; - var enabledColumn = new Ext.grid.CheckColumn({ - header : "Enabled", - dataIndex : 'enabled', - width : 45 - }); - - var eitColumn = new Ext.grid.CheckColumn({ - header : "EPG", - dataIndex : 'dvb_eit_enable', - width : 45 - }); var actions = new Ext.ux.grid.RowActions({ header : '', @@ -413,7 +402,12 @@ tvheadend.dvb_services = function(adapterId) { var cm = new Ext.grid.ColumnModel({ defaultSortable: true, columns: [ - enabledColumn, + { + xtype: 'checkcolumn', + header : "Enabled", + dataIndex : 'enabled', + width : 45 + }, { header : "Service name", dataIndex : 'svcname', @@ -485,7 +479,12 @@ tvheadend.dvb_services = function(adapterId) { displayField : 'value', valueField : 'key' }) - }, eitColumn, { + }, { + xtype: 'checkcolumn', + header : "EPG", + dataIndex : 'dvb_eit_enable', + width : 45 + } , { header : "Type", dataIndex : 'type', width : 50 @@ -608,7 +607,7 @@ tvheadend.dvb_services = function(adapterId) { var grid = new Ext.grid.EditorGridPanel({ stripeRows : true, title : 'Services', - plugins : [ enabledColumn, eitColumn, actions ], + plugins : [ actions ], store : store, clicksToEdit : 2, cm : cm, diff --git a/src/webui/static/app/dvr.js b/src/webui/static/app/dvr.js index 72a5ed9e..c7a77e44 100644 --- a/src/webui/static/app/dvr.js +++ b/src/webui/static/app/dvr.js @@ -404,17 +404,18 @@ tvheadend.dvrschedule = function() { tvheadend.autoreceditor = function() { var fm = Ext.form; - var enabledColumn = new Ext.grid.CheckColumn({ - header : "Enabled", - dataIndex : 'enabled', - width : 30 - }); var cm = new Ext.grid.ColumnModel({ defaultSortable: true, columns : - [ - enabledColumn, + [ + { + header: 'Enabled', + dataIndex: 'enabled', + width: 30, + xtype: 'checkcolumn' + }, + { header : "Title (Regexp)", dataIndex : 'title', @@ -562,7 +563,7 @@ tvheadend.autoreceditor = function() { } ]}); return new tvheadend.tableEditor('Automatic Recorder', 'autorec', cm, - tvheadend.autorecRecord, [ enabledColumn ], tvheadend.autorecStore, + tvheadend.autorecRecord, [], tvheadend.autorecStore, 'autorec.html', 'wand'); } /** diff --git a/src/webui/static/app/extensions.js b/src/webui/static/app/extensions.js index 281a98e4..8ba3b39c 100644 --- a/src/webui/static/app/extensions.js +++ b/src/webui/static/app/extensions.js @@ -6,41 +6,6 @@ * http://extjs.com/license */ -/** - * CheckedColumn - */ -Ext.grid.CheckColumn = function(config){ - Ext.apply(this, config); - if(!this.id){ - this.id = Ext.id(); - } - this.renderer = this.renderer.createDelegate(this); -}; - -Ext.grid.CheckColumn.prototype ={ - init : function(grid){ - this.grid = grid; - this.grid.on('render', function(){ - var view = this.grid.getView(); - view.mainBody.on('mousedown', this.onMouseDown, this); - }, this); - }, - - onMouseDown : function(e, t){ - if(t.className && t.className.indexOf('x-grid3-cc-'+this.id) != -1){ - e.stopEvent(); - var index = this.grid.getView().findRowIndex(t); - var record = this.grid.store.getAt(index); - record.set(this.dataIndex, !record.data[this.dataIndex]); - } - }, - - renderer : function(v, p, record){ - p.css += ' x-grid3-check-col-td'; - return '
 
'; - } -}; - /** * Rowexpander diff --git a/src/webui/static/app/iptv.js b/src/webui/static/app/iptv.js index e1c9a41b..1aab499c 100644 --- a/src/webui/static/app/iptv.js +++ b/src/webui/static/app/iptv.js @@ -16,11 +16,6 @@ tvheadend.iptv = function(adapterId) { var fm = Ext.form; - var enabledColumn = new Ext.grid.CheckColumn({ - header : "Enabled", - dataIndex : 'enabled', - width : 45 - }); var actions = new Ext.ux.grid.RowActions({ header : '', @@ -44,7 +39,12 @@ tvheadend.iptv = function(adapterId) { var cm = new Ext.grid.ColumnModel({ defaultSortable: true, columns : [ - enabledColumn, + { + xtype: 'checkcolumn', + header : "Enabled", + dataIndex : 'enabled', + width : 45 + }, { header : "Channel name", dataIndex : 'channelname', @@ -275,7 +275,7 @@ tvheadend.iptv = function(adapterId) { stripeRows : true, title : 'IPTV', iconCls : 'iptv', - plugins : [ enabledColumn, actions ], + plugins : [ actions ], store : store, clicksToEdit : 2, cm : cm, diff --git a/src/webui/static/checkcolumn/CheckColumn.js b/src/webui/static/checkcolumn/CheckColumn.js new file mode 100644 index 00000000..8ebf47bf --- /dev/null +++ b/src/webui/static/checkcolumn/CheckColumn.js @@ -0,0 +1,71 @@ +/*! + * Ext JS Library 3.4.0 + * Copyright(c) 2006-2011 Sencha Inc. + * licensing@sencha.com + * http://www.sencha.com/license + */ +Ext.ns('Ext.ux.grid'); + +/** + * @class Ext.ux.grid.CheckColumn + * @extends Ext.grid.Column + *

A Column subclass which renders a checkbox in each column cell which toggles the truthiness of the associated data field on click.

+ *

Note. As of ExtJS 3.3 this no longer has to be configured as a plugin of the GridPanel.

+ *

Example usage:

+ *

+var cm = new Ext.grid.ColumnModel([{
+       header: 'Foo',
+       ...
+    },{
+       xtype: 'checkcolumn',
+       header: 'Indoor?',
+       dataIndex: 'indoor',
+       width: 55
+    }
+]);
+
+// create the grid
+var grid = new Ext.grid.EditorGridPanel({
+    ...
+    colModel: cm,
+    ...
+});
+ * 
+ * In addition to toggling a Boolean value within the record data, this + * class toggles a css class between 'x-grid3-check-col' and + * 'x-grid3-check-col-on' to alter the background image used for + * a column. + */ +Ext.ux.grid.CheckColumn = Ext.extend(Ext.grid.Column, { + + /** + * @private + * Process and refire events routed from the GridView's processEvent method. + */ + processEvent : function(name, e, grid, rowIndex, colIndex){ + if (name == 'mousedown') { + var record = grid.store.getAt(rowIndex); + record.set(this.dataIndex, !record.data[this.dataIndex]); + return false; // Cancel row selection. + } else { + return Ext.grid.ActionColumn.superclass.processEvent.apply(this, arguments); + } + }, + + renderer : function(v, p, record){ + p.css += ' x-grid3-check-col-td'; + return String.format('
 
', v ? '-on' : ''); + }, + + // Deprecate use as a plugin. Remove in 4.0 + init: Ext.emptyFn +}); + +// register ptype. Deprecate. Remove in 4.0 +Ext.preg('checkcolumn', Ext.ux.grid.CheckColumn); + +// backwards compat. Remove in 4.0 +Ext.grid.CheckColumn = Ext.ux.grid.CheckColumn; + +// register Column xtype +Ext.grid.Column.types.checkcolumn = Ext.ux.grid.CheckColumn; \ No newline at end of file From 7092bc14504d6cf9d950f128f111eed85bfbf9ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20=C3=96man?= Date: Fri, 16 Nov 2012 12:05:06 +0100 Subject: [PATCH 07/31] Fix DVB URI /dvbnetworks -> /dev/locations --- src/webui/extjs_dvb.c | 6 +++--- src/webui/static/app/dvb.js | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/webui/extjs_dvb.c b/src/webui/extjs_dvb.c index 443bf22f..c1c1c632 100644 --- a/src/webui/extjs_dvb.c +++ b/src/webui/extjs_dvb.c @@ -47,7 +47,7 @@ * */ static int -extjs_dvbnetworks(http_connection_t *hc, const char *remain, void *opaque) +extjs_dvblocations(http_connection_t *hc, const char *remain, void *opaque) { htsbuf_queue_t *hq = &hc->hc_reply; const char *s = http_arg_get(&hc->hc_req_args, "node"); @@ -691,8 +691,8 @@ extjs_list_dvb_adapters(htsmsg_t *array) void extjs_start_dvb(void) { - http_path_add("/dvbnetworks", - NULL, extjs_dvbnetworks, ACCESS_WEB_INTERFACE); + http_path_add("/dvb/locations", + NULL, extjs_dvblocations, ACCESS_WEB_INTERFACE); http_path_add("/dvb/adapter", NULL, extjs_dvbadapter, ACCESS_ADMIN); diff --git a/src/webui/static/app/dvb.js b/src/webui/static/app/dvb.js index 3f1ccb0d..bdbc022b 100644 --- a/src/webui/static/app/dvb.js +++ b/src/webui/static/app/dvb.js @@ -668,7 +668,7 @@ tvheadend.addMuxByLocation = function(adapterData, satConfStore) { baseParams : { adapter : adapterData.identifier }, - dataUrl : 'dvbnetworks' + dataUrl : 'dvb/locations' }), root : new Ext.tree.AsyncTreeNode({ id : 'root' From f33dd3b7224b149cdd9af943659a75a3f964868b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20=C3=96man?= Date: Fri, 16 Nov 2012 12:05:57 +0100 Subject: [PATCH 08/31] Remove unused Ext.grid.RowExpander --- src/webui/static/app/extensions.js | 132 ----------------------------- 1 file changed, 132 deletions(-) diff --git a/src/webui/static/app/extensions.js b/src/webui/static/app/extensions.js index 8ba3b39c..5a14d9f8 100644 --- a/src/webui/static/app/extensions.js +++ b/src/webui/static/app/extensions.js @@ -7,138 +7,6 @@ */ -/** - * Rowexpander - */ -Ext.grid.RowExpander = function(config){ - Ext.apply(this, config); - - this.addEvents({ - beforeexpand : true, - expand: true, - beforecollapse: true, - collapse: true - }); - - Ext.grid.RowExpander.superclass.constructor.call(this); - - if(this.tpl){ - if(typeof this.tpl == 'string'){ - this.tpl = new Ext.Template(this.tpl); - } - this.tpl.compile(); - } - - this.state = {}; - this.bodyContent = {}; -}; - -Ext.extend(Ext.grid.RowExpander, Ext.util.Observable, { - header: "", - width: 20, - sortable: false, - fixed:true, - menuDisabled:true, - dataIndex: '', - id: 'expander', - lazyRender : true, - enableCaching: true, - - getRowClass : function(record, rowIndex, p, ds){ - p.cols = p.cols-1; - var content = this.bodyContent[record.id]; - if(!content && !this.lazyRender){ - content = this.getBodyContent(record, rowIndex); - } - if(content){ - p.body = content; - } - return this.state[record.id] ? 'x-grid3-row-expanded' : 'x-grid3-row-collapsed'; - }, - - init : function(grid){ - this.grid = grid; - - var view = grid.getView(); - view.getRowClass = this.getRowClass.createDelegate(this); - - view.enableRowBody = true; - - grid.on('render', function(){ - view.mainBody.on('mousedown', this.onMouseDown, this); - }, this); - }, - - getBodyContent : function(record, index){ - if(!this.enableCaching){ - return this.tpl.apply(record.data); - } - var content = this.bodyContent[record.id]; - if(!content){ - content = this.tpl.apply(record.data); - this.bodyContent[record.id] = content; - } - return content; - }, - - onMouseDown : function(e, t){ - if(t.className == 'x-grid3-row-expander'){ - e.stopEvent(); - var row = e.getTarget('.x-grid3-row'); - this.toggleRow(row); - } - }, - - renderer : function(v, p, record){ - p.cellAttr = 'rowspan="2"'; - return '
 
'; - }, - - beforeExpand : function(record, body, rowIndex){ - if(this.fireEvent('beforeexpand', this, record, body, rowIndex) !== false){ - if(this.tpl && this.lazyRender){ - body.innerHTML = this.getBodyContent(record, rowIndex); - } - return true; - }else{ - return false; - } - }, - - toggleRow : function(row){ - if(typeof row == 'number'){ - row = this.grid.view.getRow(row); - } - this[Ext.fly(row).hasClass('x-grid3-row-collapsed') ? 'expandRow' : 'collapseRow'](row); - }, - - expandRow : function(row){ - if(typeof row == 'number'){ - row = this.grid.view.getRow(row); - } - var record = this.grid.store.getAt(row.rowIndex); - var body = Ext.DomQuery.selectNode('tr:nth(2) div.x-grid3-row-body', row); - if(this.beforeExpand(record, body, row.rowIndex)){ - this.state[record.id] = true; - Ext.fly(row).replaceClass('x-grid3-row-collapsed', 'x-grid3-row-expanded'); - this.fireEvent('expand', this, record, body, row.rowIndex); - } - }, - - collapseRow : function(row){ - if(typeof row == 'number'){ - row = this.grid.view.getRow(row); - } - var record = this.grid.store.getAt(row.rowIndex); - var body = Ext.fly(row).child('tr:nth(1) div.x-grid3-row-body', true); - if(this.fireEvent('beforecollapse', this, record, body, row.rowIndex) !== false){ - this.state[record.id] = false; - Ext.fly(row).replaceClass('x-grid3-row-expanded', 'x-grid3-row-collapsed'); - this.fireEvent('collapse', this, record, body, row.rowIndex); - } - } -}); - /* From abde2507d82e90e818593d0a56880d32afeacb1c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20=C3=96man?= Date: Mon, 19 Nov 2012 13:15:19 +0100 Subject: [PATCH 09/31] DVB networks view, WIP --- src/webui/extjs.c | 1 + src/webui/extjs_dvb.c | 52 +++++++++++++++++++++++++++++++ src/webui/static/app/tvheadend.js | 12 ++++--- 3 files changed, 60 insertions(+), 5 deletions(-) diff --git a/src/webui/extjs.c b/src/webui/extjs.c index 9ceef1df..df1ce74e 100644 --- a/src/webui/extjs.c +++ b/src/webui/extjs.c @@ -130,6 +130,7 @@ extjs_root(http_connection_t *hc, const char *remain, void *opaque) extjs_load(hq, "static/app/tvadapters.js"); #if ENABLE_LINUXDVB extjs_load(hq, "static/app/dvb.js"); + extjs_load(hq, "static/app/dvb_networks.js"); #endif extjs_load(hq, "static/app/iptv.js"); #if ENABLE_V4L diff --git a/src/webui/extjs_dvb.c b/src/webui/extjs_dvb.c index c1c1c632..3f007529 100644 --- a/src/webui/extjs_dvb.c +++ b/src/webui/extjs_dvb.c @@ -685,6 +685,55 @@ extjs_list_dvb_adapters(htsmsg_t *array) } +/** + * + */ +static int +extjs_dvbnetworks(http_connection_t *hc, const char *remain, void *opaque) +{ + htsbuf_queue_t *hq = &hc->hc_reply; + const char *s = http_arg_get(&hc->hc_req_args, "node"); + htsmsg_t *out = NULL; + + if(s == NULL) + return HTTP_STATUS_BAD_REQUEST; + + pthread_mutex_lock(&global_lock); + + if(http_access_verify(hc, ACCESS_ADMIN)) { + pthread_mutex_unlock(&global_lock); + 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); + + 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); + } + + + pthread_mutex_unlock(&global_lock); + + htsmsg_json_serialize(out, hq, 0); + htsmsg_destroy(out); + http_output_content(hc, "text/x-json; charset=UTF-8"); + return 0; +} + + + /** * DVB WEB user interface */ @@ -694,6 +743,9 @@ extjs_start_dvb(void) 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); diff --git a/src/webui/static/app/tvheadend.js b/src/webui/static/app/tvheadend.js index 3b44f6ca..ec990c58 100644 --- a/src/webui/static/app/tvheadend.js +++ b/src/webui/static/app/tvheadend.js @@ -235,11 +235,13 @@ function accessUpdate(o) { autoScroll : true, title : 'Configuration', iconCls : 'wrench', - items : [ new tvheadend.miscconf, new tvheadend.chconf, - new tvheadend.epggrab, new tvheadend.cteditor, - new tvheadend.dvrsettings, new tvheadend.tvadapters, - new tvheadend.iptv, new tvheadend.acleditor, - new tvheadend.cwceditor, new tvheadend.capmteditor ] + items : [ new tvheadend.dvb_networks, + new tvheadend.miscconf, new tvheadend.chconf, + new tvheadend.epggrab, new tvheadend.cteditor, + new tvheadend.dvrsettings, new tvheadend.tvadapters, + + new tvheadend.iptv, new tvheadend.acleditor, + new tvheadend.cwceditor, new tvheadend.capmteditor ] }); tvheadend.rootTabPanel.add(tvheadend.confpanel); } From d1051e6cc0fb4f0aa511ae68a1683d917ffc5a08 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20=C3=96man?= Date: Tue, 4 Dec 2012 16:47:28 +0100 Subject: [PATCH 10/31] dvb: Add dvb_network_t and start to migrate stuff there from dvb_adapter_t --- src/dvb/dvb.h | 28 +++++++++++++++++++--------- src/dvb/dvb_adapter.c | 18 ++++++++++-------- src/dvb/dvb_fe.c | 4 ++-- src/dvb/dvb_multiplex.c | 16 +++++++--------- src/dvb/dvb_service.c | 2 +- src/dvb/dvb_tables.c | 12 ++++++------ src/epggrab/otamux.c | 2 +- src/webui/extjs_dvb.c | 8 ++++---- src/webui/statedump.c | 2 +- 9 files changed, 51 insertions(+), 41 deletions(-) diff --git a/src/dvb/dvb.h b/src/dvb/dvb.h index 94b2616b..51392357 100644 --- a/src/dvb/dvb.h +++ b/src/dvb/dvb.h @@ -93,7 +93,6 @@ typedef struct th_dvb_mux_instance { RB_ENTRY(th_dvb_mux_instance) tdmi_global_link; LIST_ENTRY(th_dvb_mux_instance) tdmi_adapter_link; - LIST_ENTRY(th_dvb_mux_instance) tdmi_adapter_hash_link; struct th_dvb_adapter *tdmi_adapter; @@ -166,6 +165,21 @@ typedef struct dvb_table_feed { +/** + * + */ +typedef struct dvb_network { + + struct th_dvb_mux_instance_list dn_muxes; + + struct th_dvb_mux_instance_queue dn_initial_scan_queue; + int dn_initial_num_mux; + + int dn_fe_type; + +} dvb_network_t; + + /** * DVB Adapter (one of these per physical adapter) */ @@ -175,10 +189,7 @@ typedef struct th_dvb_adapter { TAILQ_ENTRY(th_dvb_adapter) tda_global_link; - struct th_dvb_mux_instance_list tda_muxes; - - struct th_dvb_mux_instance_queue tda_initial_scan_queue; - int tda_initial_num_mux; + dvb_network_t *tda_dn; th_dvb_mux_instance_t *tda_mux_current; char *tda_tune_reason; // Reason for last tune @@ -203,10 +214,11 @@ typedef struct th_dvb_adapter { int32_t tda_full_mux_rx; char *tda_displayname; + int tda_type; + struct dvb_frontend_info *tda_fe_info; // result of FE_GET_INFO ioctl() + char *tda_fe_path; int tda_fe_fd; - int tda_type; - struct dvb_frontend_info *tda_fe_info; int tda_adapter_num; @@ -230,8 +242,6 @@ typedef struct th_dvb_adapter { struct dvb_satconf_queue tda_satconfs; - struct th_dvb_mux_instance_list tda_mux_list; - uint32_t tda_last_fec; int tda_unc_is_delta; /* 1 if we believe FE_READ_UNCORRECTED_BLOCKS diff --git a/src/dvb/dvb_adapter.c b/src/dvb/dvb_adapter.c index 8a088340..c0a3c9cf 100644 --- a/src/dvb/dvb_adapter.c +++ b/src/dvb/dvb_adapter.c @@ -57,9 +57,11 @@ static th_dvb_adapter_t * tda_alloc(void) { th_dvb_adapter_t *tda = calloc(1, sizeof(th_dvb_adapter_t)); + dvb_network_t *dn = calloc(1, sizeof(dvb_network_t)); pthread_mutex_init(&tda->tda_delivery_mutex, NULL); - TAILQ_INIT(&tda->tda_initial_scan_queue); + tda->tda_dn = dn; + TAILQ_INIT(&dn->dn_initial_scan_queue); TAILQ_INIT(&tda->tda_satconfs); streaming_pad_init(&tda->tda_streaming_pad); return tda; @@ -711,7 +713,7 @@ dvb_adapter_mux_scanner(void *aux) gtimer_arm(&tda->tda_mux_scanner_timer, dvb_adapter_mux_scanner, tda, 20); /* No muxes */ - if(LIST_FIRST(&tda->tda_muxes) == NULL) { + if(LIST_FIRST(&tda->tda_dn->dn_muxes) == NULL) { dvb_adapter_poweroff(tda); return; } @@ -725,7 +727,7 @@ dvb_adapter_mux_scanner(void *aux) return; // Someone is doing full mux dump /* Check if we have muxes pending for quickscan, if so, choose them */ - if((tdmi = TAILQ_FIRST(&tda->tda_initial_scan_queue)) != NULL) { + if((tdmi = TAILQ_FIRST(&tda->tda_dn->dn_initial_scan_queue)) != NULL) { dvb_fe_tune(tdmi, "Initial autoscan"); return; } @@ -764,10 +766,10 @@ dvb_adapter_clone(th_dvb_adapter_t *dst, th_dvb_adapter_t *src) lock_assert(&global_lock); - while((tdmi_dst = LIST_FIRST(&dst->tda_muxes)) != NULL) + while((tdmi_dst = LIST_FIRST(&dst->tda_dn->dn_muxes)) != NULL) dvb_mux_destroy(tdmi_dst); - LIST_FOREACH(tdmi_src, &src->tda_muxes, tdmi_adapter_link) + LIST_FOREACH(tdmi_src, &src->tda_dn->dn_muxes, tdmi_adapter_link) dvb_mux_copy(dst, tdmi_src, NULL); tda_save(dst); @@ -789,7 +791,7 @@ dvb_adapter_destroy(th_dvb_adapter_t *tda) hts_settings_remove("dvbadapters/%s", tda->tda_identifier); - while((tdmi = LIST_FIRST(&tda->tda_muxes)) != NULL) + while((tdmi = LIST_FIRST(&tda->tda_dn->dn_muxes)) != NULL) dvb_mux_destroy(tdmi); TAILQ_REMOVE(&dvb_adapters, tda, tda_global_link); @@ -992,7 +994,7 @@ dvb_adapter_build_msg(th_dvb_adapter_t *tda) htsmsg_add_str(m, "name", tda->tda_displayname); // XXX: bad bad bad slow slow slow - LIST_FOREACH(tdmi, &tda->tda_muxes, tdmi_adapter_link) { + LIST_FOREACH(tdmi, &tda->tda_dn->dn_muxes, tdmi_adapter_link) { nummux++; LIST_FOREACH(t, &tdmi->tdmi_transports, s_group_link) { numsvc++; @@ -1003,7 +1005,7 @@ dvb_adapter_build_msg(th_dvb_adapter_t *tda) htsmsg_add_u32(m, "services", numsvc); htsmsg_add_u32(m, "muxes", nummux); - htsmsg_add_u32(m, "initialMuxes", tda->tda_initial_num_mux); + htsmsg_add_u32(m, "initialMuxes", tda->tda_dn->dn_initial_num_mux); if(tda->tda_mux_current != NULL) { th_dvb_mux_instance_t *tdmi = tda->tda_mux_current; diff --git a/src/dvb/dvb_fe.c b/src/dvb/dvb_fe.c index d8b5ba27..a7494810 100644 --- a/src/dvb/dvb_fe.c +++ b/src/dvb/dvb_fe.c @@ -269,7 +269,7 @@ dvb_fe_stop(th_dvb_mux_instance_t *tdmi, int retune) if(tdmi->tdmi_table_initial) { tdmi->tdmi_table_initial = 0; - tda->tda_initial_num_mux--; + tda->tda_dn->dn_initial_num_mux--; dvb_mux_save(tdmi); } @@ -497,7 +497,7 @@ dvb_fe_tune(th_dvb_mux_instance_t *tdmi, const char *reason) /* Remove from initial scan set */ if(tdmi->tdmi_table_initial) { tdmi->tdmi_table_initial = 0; - tda->tda_initial_num_mux--; + tda->tda_dn->dn_initial_num_mux--; } /* Mark as bad */ diff --git a/src/dvb/dvb_multiplex.c b/src/dvb/dvb_multiplex.c index 7efb6f36..8972226e 100644 --- a/src/dvb/dvb_multiplex.c +++ b/src/dvb/dvb_multiplex.c @@ -67,9 +67,9 @@ static void tdmi_set_enable(th_dvb_mux_instance_t *tdmi, int enabled); static void mux_link_initial(th_dvb_adapter_t *tda, th_dvb_mux_instance_t *tdmi) { - int was_empty = TAILQ_FIRST(&tda->tda_initial_scan_queue) == NULL; + int was_empty = TAILQ_FIRST(&tda->tda_dn->dn_initial_scan_queue) == NULL; - tdmi->tdmi_scan_queue = &tda->tda_initial_scan_queue; + tdmi->tdmi_scan_queue = &tda->tda_dn->dn_initial_scan_queue; TAILQ_INSERT_TAIL(tdmi->tdmi_scan_queue, tdmi, tdmi_scan_link); if(was_empty && (tda->tda_mux_current == NULL || @@ -163,7 +163,7 @@ dvb_mux_create(th_dvb_adapter_t *tda, const struct dvb_mux_conf *dmc, lock_assert(&global_lock); /* HACK - we hash/compare based on 2KHz spacing and compare on +/-500Hz */ - LIST_FOREACH(tdmi, &tda->tda_mux_list, tdmi_adapter_hash_link) { + LIST_FOREACH(tdmi, &tda->tda_dn->dn_muxes, tdmi_adapter_link) { if(tdmi_compare_key(&tdmi->tdmi_conf, dmc)) break; /* Mux already exist */ } @@ -280,8 +280,7 @@ dvb_mux_create(th_dvb_adapter_t *tda, const struct dvb_mux_conf *dmc, tdmi, tdmi_satconf_link); } - LIST_INSERT_HEAD(&tda->tda_mux_list, tdmi, tdmi_adapter_hash_link); - LIST_INSERT_HEAD(&tda->tda_muxes, tdmi, tdmi_adapter_link); + LIST_INSERT_HEAD(&tda->tda_dn->dn_muxes, tdmi, tdmi_adapter_link); tdmi->tdmi_table_initial = initialscan; if(source != NULL) { @@ -296,7 +295,7 @@ dvb_mux_create(th_dvb_adapter_t *tda, const struct dvb_mux_conf *dmc, dvb_mux_notify(tdmi); if(enabled && tdmi->tdmi_table_initial) { - tda->tda_initial_num_mux++; + tda->tda_dn->dn_initial_num_mux++; mux_link_initial(tda, tdmi); } @@ -334,13 +333,12 @@ dvb_mux_destroy(th_dvb_mux_instance_t *tdmi) RB_REMOVE(&dvb_muxes, tdmi, tdmi_global_link); LIST_REMOVE(tdmi, tdmi_adapter_link); - LIST_REMOVE(tdmi, tdmi_adapter_hash_link); if(tdmi->tdmi_scan_queue != NULL) TAILQ_REMOVE(tdmi->tdmi_scan_queue, tdmi, tdmi_scan_link); if(tdmi->tdmi_table_initial) - tda->tda_initial_num_mux--; + tda->tda_dn->dn_initial_num_mux--; epggrab_mux_delete(tdmi); @@ -1254,7 +1252,7 @@ th_dvb_mux_instance_t *dvb_mux_find { th_dvb_mux_instance_t *tdmi; if (tda) { - LIST_FOREACH(tdmi, &tda->tda_muxes, tdmi_adapter_link) { + LIST_FOREACH(tdmi, &tda->tda_dn->dn_muxes, tdmi_adapter_link) { if (enabled && !tdmi->tdmi_enabled) continue; if (onid && onid != tdmi->tdmi_network_id) continue; if (tsid && tsid != tdmi->tdmi_transport_stream_id) continue; diff --git a/src/dvb/dvb_service.c b/src/dvb/dvb_service.c index 82621227..821e9a30 100644 --- a/src/dvb/dvb_service.c +++ b/src/dvb/dvb_service.c @@ -352,7 +352,7 @@ dvb_service_find3 if (sid == svc->s_dvb_service_id) return svc; } } else if (tda) { - LIST_FOREACH(tdmi, &tda->tda_muxes, tdmi_adapter_link) { + LIST_FOREACH(tdmi, &tda->tda_dn->dn_muxes, tdmi_adapter_link) { if (enabled && !tdmi->tdmi_enabled) continue; if (onid && onid != tdmi->tdmi_network_id) continue; if (tsid && tsid != tdmi->tdmi_transport_stream_id) continue; diff --git a/src/dvb/dvb_tables.c b/src/dvb/dvb_tables.c index 529f5c50..29ac020e 100644 --- a/src/dvb/dvb_tables.c +++ b/src/dvb/dvb_tables.c @@ -61,7 +61,7 @@ dvb_table_fastswitch(th_dvb_mux_instance_t *tdmi) return; tdmi->tdmi_table_initial = 0; - tda->tda_initial_num_mux--; + tda->tda_dn->dn_initial_num_mux--; dvb_mux_save(tdmi); @@ -267,7 +267,7 @@ dvb_bat_callback(th_dvb_mux_instance_t *tdmi, uint8_t *buf, int len, j = 0; /* Find TDMI */ - LIST_FOREACH(tdmi, &tda->tda_muxes, tdmi_adapter_link) + LIST_FOREACH(tdmi, &tda->tda_dn->dn_muxes, tdmi_adapter_link) if(tdmi->tdmi_transport_stream_id == tsid && tdmi->tdmi_network_id == onid) break; @@ -337,7 +337,7 @@ dvb_sdt_callback(th_dvb_mux_instance_t *tdmi, uint8_t *ptr, int len, if(!tdmi->tdmi_network_id) dvb_mux_set_onid(tdmi, onid); } else { - LIST_FOREACH(tdmi, &tda->tda_muxes, tdmi_adapter_link) + LIST_FOREACH(tdmi, &tda->tda_dn->dn_muxes, tdmi_adapter_link) if(tdmi->tdmi_transport_stream_id == tsid && tdmi->tdmi_network_id != onid) break; @@ -495,7 +495,7 @@ dvb_pat_callback(th_dvb_mux_instance_t *tdmi, uint8_t *ptr, int len, // Make sure this TSID is not already known on another mux // That might indicate that we have accedentally received a PAT // from another mux - LIST_FOREACH(other, &tda->tda_muxes, tdmi_adapter_link) + LIST_FOREACH(other, &tda->tda_dn->dn_muxes, tdmi_adapter_link) if(other != tdmi && other->tdmi_conf.dmc_satconf == tdmi->tdmi_conf.dmc_satconf && other->tdmi_transport_stream_id == tsid && @@ -755,7 +755,7 @@ dvb_table_local_channel(th_dvb_mux_instance_t *tdmi, uint8_t *ptr, int len, th_dvb_adapter_t *tda = tdmi->tdmi_adapter; service_t *t; - LIST_FOREACH(tdmi, &tda->tda_muxes, tdmi_adapter_link) + LIST_FOREACH(tdmi, &tda->tda_dn->dn_muxes, tdmi_adapter_link) if(tdmi->tdmi_transport_stream_id == tsid && tdmi->tdmi_network_id == onid) break; @@ -935,7 +935,7 @@ atsc_vct_callback(th_dvb_mux_instance_t *tdmi, uint8_t *ptr, int len, onid = (ptr[24] << 8) | ptr[25]; /* Search all muxes on adapter */ - LIST_FOREACH(tdmi, &tda->tda_muxes, tdmi_adapter_link) + LIST_FOREACH(tdmi, &tda->tda_dn->dn_muxes, tdmi_adapter_link) if(tdmi->tdmi_transport_stream_id == tsid && tdmi->tdmi_network_id == onid); break; diff --git a/src/epggrab/otamux.c b/src/epggrab/otamux.c index c4242079..16def861 100644 --- a/src/epggrab/otamux.c +++ b/src/epggrab/otamux.c @@ -255,7 +255,7 @@ void epggrab_ota_create_and_register_by_id th_dvb_mux_instance_t *tdmi; epggrab_ota_mux_t *ota; TAILQ_FOREACH(tda, &dvb_adapters, tda_global_link) { - LIST_FOREACH(tdmi, &tda->tda_muxes, tdmi_adapter_link) { + LIST_FOREACH(tdmi, &tda->tda_dn->dn_muxes, tdmi_adapter_link) { if (tdmi->tdmi_transport_stream_id != tsid) continue; if (onid && tdmi->tdmi_network_id != onid) continue; if (networkname && (!tdmi->tdmi_network || strcmp(networkname, tdmi->tdmi_network))) continue; diff --git a/src/webui/extjs_dvb.c b/src/webui/extjs_dvb.c index 3f007529..e8948351 100644 --- a/src/webui/extjs_dvb.c +++ b/src/webui/extjs_dvb.c @@ -237,7 +237,7 @@ extjs_dvbadapter(http_connection_t *hc, const char *remain, void *opaque) tvhlog(LOG_NOTICE, "web interface", "Service probe started on \"%s\"", tda->tda_displayname); - LIST_FOREACH(tdmi, &tda->tda_muxes, tdmi_adapter_link) { + LIST_FOREACH(tdmi, &tda->tda_dn->dn_muxes, tdmi_adapter_link) { LIST_FOREACH(t, &tdmi->tdmi_transports, s_group_link) { if(t->s_enabled) serviceprobe_enqueue(t); @@ -334,7 +334,7 @@ extjs_dvbmuxes(http_connection_t *hc, const char *remain, void *opaque) if(!strcmp(op, "get")) { array = htsmsg_create_list(); - LIST_FOREACH(tdmi, &tda->tda_muxes, tdmi_adapter_link) + LIST_FOREACH(tdmi, &tda->tda_dn->dn_muxes, tdmi_adapter_link) htsmsg_add_msg(array, NULL, dvb_mux_build_msg(tdmi)); htsmsg_add_msg(out, "entries", array); @@ -415,7 +415,7 @@ extjs_dvbservices(http_connection_t *hc, const char *remain, void *opaque) out = htsmsg_create_map(); array = htsmsg_create_list(); - LIST_FOREACH(tdmi, &tda->tda_muxes, tdmi_adapter_link) { + LIST_FOREACH(tdmi, &tda->tda_dn->dn_muxes, tdmi_adapter_link) { LIST_FOREACH(t, &tdmi->tdmi_transports, s_group_link) { count++; } @@ -423,7 +423,7 @@ extjs_dvbservices(http_connection_t *hc, const char *remain, void *opaque) tvec = alloca(sizeof(service_t *) * count); - LIST_FOREACH(tdmi, &tda->tda_muxes, tdmi_adapter_link) { + LIST_FOREACH(tdmi, &tda->tda_dn->dn_muxes, tdmi_adapter_link) { LIST_FOREACH(t, &tdmi->tdmi_transports, s_group_link) { tvec[i++] = t; } diff --git a/src/webui/statedump.c b/src/webui/statedump.c index a9758e6f..10d12977 100644 --- a/src/webui/statedump.c +++ b/src/webui/statedump.c @@ -134,7 +134,7 @@ dumpdvbadapters(htsbuf_queue_t *hq) htsbuf_qprintf(hq, "%s (%s)\n", tda->tda_displayname, tda->tda_identifier); outputtitle(hq, 4, "Multiplexes"); - LIST_FOREACH(tdmi, &tda->tda_muxes, tdmi_adapter_link) { + LIST_FOREACH(tdmi, &tda->tda_dn->dn_muxes, tdmi_adapter_link) { char tdminame[64]; dvb_mux_nicename(tdminame, sizeof(tdminame), tdmi); htsbuf_qprintf(hq, " %s (%s)\n", From 9c2a55eb0128c0b9f15e06191657e85ff07c930c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20=C3=96man?= Date: Tue, 4 Dec 2012 16:59:08 +0100 Subject: [PATCH 11/31] More members to dvb_network_t --- src/dvb/dvb.h | 4 +--- src/dvb/dvb_adapter.c | 15 ++++++++------- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/src/dvb/dvb.h b/src/dvb/dvb.h index 51392357..be70e6b8 100644 --- a/src/dvb/dvb.h +++ b/src/dvb/dvb.h @@ -175,7 +175,7 @@ typedef struct dvb_network { struct th_dvb_mux_instance_queue dn_initial_scan_queue; int dn_initial_num_mux; - int dn_fe_type; + th_dvb_mux_instance_t *dn_mux_epg; } dvb_network_t; @@ -194,8 +194,6 @@ typedef struct th_dvb_adapter { th_dvb_mux_instance_t *tda_mux_current; char *tda_tune_reason; // Reason for last tune - th_dvb_mux_instance_t *tda_mux_epg; - int tda_table_epollfd; const char *tda_rootpath; diff --git a/src/dvb/dvb_adapter.c b/src/dvb/dvb_adapter.c index c0a3c9cf..a1175c69 100644 --- a/src/dvb/dvb_adapter.c +++ b/src/dvb/dvb_adapter.c @@ -733,20 +733,21 @@ dvb_adapter_mux_scanner(void *aux) } /* Check EPG */ - if (tda->tda_mux_epg) { - epggrab_mux_stop(tda->tda_mux_epg, 1); // timeout anything not complete - tda->tda_mux_epg = NULL; // skip this time + if (tda->tda_dn->dn_mux_epg) { + // timeout anything not complete + epggrab_mux_stop(tda->tda_dn->dn_mux_epg, 1); + tda->tda_dn->dn_mux_epg = NULL; // skip this time } else { - tda->tda_mux_epg = epggrab_mux_next(tda); + tda->tda_dn->dn_mux_epg = epggrab_mux_next(tda); } /* EPG */ - if (tda->tda_mux_epg) { - int period = epggrab_mux_period(tda->tda_mux_epg); + if (tda->tda_dn->dn_mux_epg) { + int period = epggrab_mux_period(tda->tda_dn->dn_mux_epg); if (period > 20) gtimer_arm(&tda->tda_mux_scanner_timer, dvb_adapter_mux_scanner, tda, period); - dvb_fe_tune(tda->tda_mux_epg, "EPG scan"); + dvb_fe_tune(tda->tda_dn->dn_mux_epg, "EPG scan"); return; } From 97debaeff327fe2340a952d9e466e7dcea5f7e8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20=C3=96man?= Date: Wed, 5 Dec 2012 09:24:10 +0100 Subject: [PATCH 12/31] Move mux configuration stuff into dvb_mux_t This also disables sat_conf stuff (LNB switches, etc) but we will have to solve that in a different manner anyway --- src/dvb/dvb.h | 76 ++++++++++++++++---------- src/dvb/dvb_adapter.c | 39 +++++++------- src/dvb/dvb_fe.c | 20 +++---- src/dvb/dvb_multiplex.c | 117 ++++++++++++++++------------------------ src/dvb/dvb_preconf.c | 15 +++--- src/dvb/dvb_preconf.h | 3 +- src/dvb/dvb_satconf.c | 9 +--- src/dvb/dvb_service.c | 10 ++-- src/dvb/dvb_support.c | 20 +++---- src/dvb/dvb_support.h | 2 +- src/dvb/dvb_tables.c | 30 +++++------ src/epggrab/otamux.c | 2 +- src/webui/extjs_dvb.c | 30 ++++++----- src/webui/statedump.c | 4 +- 14 files changed, 182 insertions(+), 195 deletions(-) diff --git a/src/dvb/dvb.h b/src/dvb/dvb.h index be70e6b8..d03b0dde 100644 --- a/src/dvb/dvb.h +++ b/src/dvb/dvb.h @@ -39,7 +39,7 @@ RB_HEAD(th_dvb_mux_instance_tree, th_dvb_mux_instance); TAILQ_HEAD(th_dvb_mux_instance_queue, th_dvb_mux_instance); LIST_HEAD(th_dvb_mux_instance_list, th_dvb_mux_instance); TAILQ_HEAD(dvb_satconf_queue, dvb_satconf); - +LIST_HEAD(dvb_mux_list, dvb_mux); /** * Satconf @@ -53,12 +53,9 @@ typedef struct dvb_satconf { char *sc_comment; char *sc_lnb; - struct th_dvb_mux_instance_list sc_tdmis; - } dvb_satconf_t; - enum polarisation { POLARISATION_HORIZONTAL = 0x00, POLARISATION_VERTICAL = 0x01, @@ -76,7 +73,7 @@ typedef struct dvb_frontend_parameters dvb_frontend_parameters_t; typedef struct dvb_mux_conf { dvb_frontend_parameters_t dmc_fe_params; int dmc_polarisation; - dvb_satconf_t *dmc_satconf; + // dvb_satconf_t *dmc_satconf; #if DVB_API_VERSION >= 5 fe_modulation_t dmc_fe_modulation; fe_delivery_system_t dmc_fe_delsys; @@ -85,14 +82,54 @@ typedef struct dvb_mux_conf { } dvb_mux_conf_t; + +/** + * + */ +typedef struct dvb_network { + + struct th_dvb_mux_instance_list dn_mux_instances; // Should go away + + struct th_dvb_mux_instance_queue dn_initial_scan_queue; + int dn_initial_num_mux; + + struct th_dvb_mux_instance *dn_mux_epg; + + int dn_fe_type; // Frontend types for this network (FE_QPSK, etc) + + // struct dvb_mux_list dn_muxes; + +} dvb_network_t; + + + +/** + * + */ +typedef struct dvb_mux { + + // LIST_ENTRY(dvb_mux) dm_network_link; + dvb_network_t *dm_network; + + struct service_list dm_services; + + dvb_mux_conf_t dm_conf; + +} dvb_mux_t; + + + + /** * DVB Mux instance */ 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; + LIST_ENTRY(th_dvb_mux_instance) tdmi_adapter_link; // wrong struct th_dvb_adapter *tdmi_adapter; @@ -124,8 +161,6 @@ typedef struct th_dvb_mux_instance { int tdmi_enabled; - dvb_mux_conf_t tdmi_conf; - /* Linked if tdmi_conf.dmc_satconf != NULL */ LIST_ENTRY(th_dvb_mux_instance) tdmi_satconf_link; @@ -137,8 +172,6 @@ typedef struct th_dvb_mux_instance { char *tdmi_default_authority; - struct service_list tdmi_transports; /* via s_mux_link */ - TAILQ_ENTRY(th_dvb_mux_instance) tdmi_scan_link; struct th_dvb_mux_instance_queue *tdmi_scan_queue; @@ -151,6 +184,7 @@ typedef struct th_dvb_mux_instance { + /** * When in raw mode we need to enqueue raw TS packet * to a different thread because we need to hold @@ -165,20 +199,6 @@ typedef struct dvb_table_feed { -/** - * - */ -typedef struct dvb_network { - - struct th_dvb_mux_instance_list dn_muxes; - - struct th_dvb_mux_instance_queue dn_initial_scan_queue; - int dn_initial_num_mux; - - th_dvb_mux_instance_t *dn_mux_epg; - -} dvb_network_t; - /** * DVB Adapter (one of these per physical adapter) @@ -212,7 +232,7 @@ typedef struct th_dvb_adapter { int32_t tda_full_mux_rx; char *tda_displayname; - int tda_type; + int tda_fe_type; struct dvb_frontend_info *tda_fe_info; // result of FE_GET_INFO ioctl() char *tda_fe_path; @@ -407,8 +427,7 @@ 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_satconf_t *satconf); + int initialscan, const char *identifier); void dvb_mux_set_networkname(th_dvb_mux_instance_t *tdmi, const char *name); @@ -439,9 +458,10 @@ const char *dvb_mux_add_by_params(th_dvb_adapter_t *tda, int fec, int polarisation, const char *satconf); - +#if 0 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, diff --git a/src/dvb/dvb_adapter.c b/src/dvb/dvb_adapter.c index a1175c69..5af203f5 100644 --- a/src/dvb/dvb_adapter.c +++ b/src/dvb/dvb_adapter.c @@ -78,7 +78,7 @@ tda_save(th_dvb_adapter_t *tda) lock_assert(&global_lock); - htsmsg_add_str(m, "type", dvb_adaptertype_to_str(tda->tda_type)); + 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); @@ -466,7 +466,8 @@ tda_add(int adapter_num) else close(fe); - tda->tda_type = tda->tda_fe_info->type; + tda->tda_fe_type = tda->tda_fe_info->type; + tda->tda_dn->dn_fe_type = tda->tda_fe_type; snprintf(buf, sizeof(buf), "%s_%s", tda->tda_rootpath, tda->tda_fe_info->name); @@ -478,9 +479,9 @@ tda_add(int adapter_num) tda->tda_identifier = strdup(buf); - tda->tda_autodiscovery = tda->tda_type != FE_QPSK; + tda->tda_autodiscovery = tda->tda_fe_type != FE_QPSK; - tda->tda_sat = tda->tda_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 be overridden by any stored settings later on */ @@ -516,7 +517,7 @@ tda_add_from_file(const char *filename) tda->tda_fe_fd = -1; tda->tda_dvr_pipe[0] = -1; - tda->tda_type = -1; + tda->tda_fe_type = -1; snprintf(buf, sizeof(buf), "%s", filename); @@ -546,7 +547,7 @@ tda_add_from_file(const char *filename) */ static void tda_init_input (th_dvb_adapter_t *tda) { - if(tda->tda_type == -1 || check_full_stream(tda)) { + if(tda->tda_fe_type == -1 || check_full_stream(tda)) { tvhlog(LOG_INFO, "dvb", "Adapter %s will run in full mux mode", tda->tda_rootpath); dvb_input_raw_setup(tda); } else { @@ -656,10 +657,10 @@ dvb_adapter_init(uint32_t adapter_mask, const char *rawfile) /* Not discovered by hardware, create it */ tda = tda_alloc(); tda->tda_identifier = strdup(f->hmf_name); - tda->tda_type = type; + tda->tda_fe_type = type; TAILQ_INSERT_TAIL(&dvb_adapters, tda, tda_global_link); } else { - if(type != tda->tda_type) + if(type != tda->tda_fe_type) continue; /* Something is wrong, ignore */ } @@ -713,7 +714,7 @@ dvb_adapter_mux_scanner(void *aux) gtimer_arm(&tda->tda_mux_scanner_timer, dvb_adapter_mux_scanner, tda, 20); /* No muxes */ - if(LIST_FIRST(&tda->tda_dn->dn_muxes) == NULL) { + if(LIST_FIRST(&tda->tda_dn->dn_mux_instances) == NULL) { dvb_adapter_poweroff(tda); return; } @@ -763,17 +764,17 @@ dvb_adapter_mux_scanner(void *aux) void dvb_adapter_clone(th_dvb_adapter_t *dst, th_dvb_adapter_t *src) { +#if 0 th_dvb_mux_instance_t *tdmi_src, *tdmi_dst; lock_assert(&global_lock); - while((tdmi_dst = LIST_FIRST(&dst->tda_dn->dn_muxes)) != NULL) + while((tdmi_dst = LIST_FIRST(&dst->tda_dn->dn_mux_instances)) != NULL) dvb_mux_destroy(tdmi_dst); - LIST_FOREACH(tdmi_src, &src->tda_dn->dn_muxes, tdmi_adapter_link) - dvb_mux_copy(dst, tdmi_src, NULL); - tda_save(dst); +#endif + abort(); // XXX(dvbreorg) } @@ -792,7 +793,7 @@ dvb_adapter_destroy(th_dvb_adapter_t *tda) hts_settings_remove("dvbadapters/%s", tda->tda_identifier); - while((tdmi = LIST_FIRST(&tda->tda_dn->dn_muxes)) != NULL) + while((tdmi = LIST_FIRST(&tda->tda_dn->dn_mux_instances)) != NULL) dvb_mux_destroy(tdmi); TAILQ_REMOVE(&dvb_adapters, tda, tda_global_link); @@ -995,9 +996,9 @@ dvb_adapter_build_msg(th_dvb_adapter_t *tda) htsmsg_add_str(m, "name", tda->tda_displayname); // XXX: bad bad bad slow slow slow - LIST_FOREACH(tdmi, &tda->tda_dn->dn_muxes, tdmi_adapter_link) { + LIST_FOREACH(tdmi, &tda->tda_dn->dn_mux_instances, tdmi_adapter_link) { nummux++; - LIST_FOREACH(t, &tdmi->tdmi_transports, s_group_link) { + LIST_FOREACH(t, &tdmi->tdmi_mux->dm_services, s_group_link) { numsvc++; } } @@ -1046,11 +1047,11 @@ dvb_adapter_build_msg(th_dvb_adapter_t *tda) htsmsg_add_str(m, "devicename", tda->tda_fe_info->name); htsmsg_add_str(m, "deliverySystem", - dvb_adaptertype_to_str(tda->tda_type) ?: ""); + dvb_adaptertype_to_str(tda->tda_fe_type) ?: ""); htsmsg_add_u32(m, "satConf", tda->tda_sat); - fdiv = tda->tda_type == FE_QPSK ? 1 : 1000; + fdiv = tda->tda_fe_type == FE_QPSK ? 1 : 1000; htsmsg_add_u32(m, "freqMin", tda->tda_fe_info->frequency_min / fdiv); htsmsg_add_u32(m, "freqMax", tda->tda_fe_info->frequency_max / fdiv); @@ -1208,7 +1209,7 @@ dvb_adapter_poweroff(th_dvb_adapter_t *tda) { if (tda->tda_fe_fd == -1) return; lock_assert(&global_lock); - if (!tda->tda_poweroff || tda->tda_type != FE_QPSK) + if (!tda->tda_poweroff || tda->tda_fe_type != FE_QPSK) return; diseqc_voltage_off(tda->tda_fe_fd); tvhlog(LOG_DEBUG, "dvb", "\"%s\" is off", tda->tda_rootpath); diff --git a/src/dvb/dvb_fe.c b/src/dvb/dvb_fe.c index a7494810..8d0f6689 100644 --- a/src/dvb/dvb_fe.c +++ b/src/dvb/dvb_fe.c @@ -396,7 +396,8 @@ dvb_fe_tune(th_dvb_mux_instance_t *tdmi, const char *reason) th_dvb_adapter_t *tda = tdmi->tdmi_adapter; // copy dmc, cause frequency may be change with FE_QPSK - dvb_mux_conf_t dmc = tdmi->tdmi_conf; + const dvb_mux_t *dm = tdmi->tdmi_mux; + dvb_mux_conf_t dmc = dm->dm_conf; dvb_frontend_parameters_t* p = &dmc.dmc_fe_params; char buf[256]; @@ -423,10 +424,9 @@ dvb_fe_tune(th_dvb_mux_instance_t *tdmi, const char *reason) else dvb_adapter_start(tda); - if(tda->tda_type == FE_QPSK) { + if(tda->tda_fe_type == FE_QPSK) { /* DVB-S */ - dvb_satconf_t *sc; int port, lowfreq, hifreq, switchfreq, hiband, pol, dbsbs; lowfreq = 9750000; @@ -434,8 +434,9 @@ dvb_fe_tune(th_dvb_mux_instance_t *tdmi, const char *reason) switchfreq = 11700000; port = 0; dbsbs = 0; - - if((sc = tdmi->tdmi_conf.dmc_satconf) != NULL) { +#if 0 + dvb_satconf_t *sc; + if((sc = dm->dm_conf.dmc_satconf) != NULL) { port = sc->sc_port; if(sc->sc_lnb != NULL) @@ -443,18 +444,19 @@ dvb_fe_tune(th_dvb_mux_instance_t *tdmi, const char *reason) if(!strcmp(sc->sc_id ?: "", "DBS Bandstacked")) dbsbs = 1; } +#endif if(dbsbs) { hiband = 0; - if(tdmi->tdmi_conf.dmc_polarisation == POLARISATION_HORIZONTAL || - tdmi->tdmi_conf.dmc_polarisation == POLARISATION_CIRCULAR_LEFT) + if(dm->dm_conf.dmc_polarisation == POLARISATION_HORIZONTAL || + dm->dm_conf.dmc_polarisation == POLARISATION_CIRCULAR_LEFT) p->frequency = abs(p->frequency - hifreq); else p->frequency = abs(p->frequency - lowfreq); pol = POLARISATION_CIRCULAR_LEFT; } else { hiband = switchfreq && p->frequency > switchfreq; - pol = tdmi->tdmi_conf.dmc_polarisation; + pol = dm->dm_conf.dmc_polarisation; if(hiband) p->frequency = abs(p->frequency - hifreq); else @@ -475,7 +477,7 @@ dvb_fe_tune(th_dvb_mux_instance_t *tdmi, const char *reason) #if DVB_API_VERSION >= 5 - if (tda->tda_type == FE_QPSK) { + if (tda->tda_fe_type == FE_QPSK) { tvhlog(LOG_DEBUG, "dvb", "\"%s\" tuning via s2api to \"%s\" (%d, %d Baud, " "%s, %s, %s) for %s", tda->tda_rootpath, buf, p->frequency, p->u.qpsk.symbol_rate, dvb_mux_fec2str(p->u.qpsk.fec_inner), dvb_mux_delsys2str(dmc.dmc_fe_delsys), diff --git a/src/dvb/dvb_multiplex.c b/src/dvb/dvb_multiplex.c index 8972226e..a223bbfb 100644 --- a/src/dvb/dvb_multiplex.c +++ b/src/dvb/dvb_multiplex.c @@ -108,8 +108,7 @@ tdmi_compare_key(const struct dvb_mux_conf *a, - (int32_t)b->dmc_fe_params.frequency; fd = labs(fd); return fd < 2000 && - a->dmc_polarisation == b->dmc_polarisation && - a->dmc_satconf == b->dmc_satconf; + a->dmc_polarisation == b->dmc_polarisation; } @@ -154,8 +153,7 @@ tdmi_compare_conf(int adapter_type, 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_satconf_t *satconf) + int enabled, int initialscan, const char *identifier) { th_dvb_mux_instance_t *tdmi, *c; char buf[200]; @@ -163,8 +161,8 @@ dvb_mux_create(th_dvb_adapter_t *tda, const struct dvb_mux_conf *dmc, lock_assert(&global_lock); /* HACK - we hash/compare based on 2KHz spacing and compare on +/-500Hz */ - LIST_FOREACH(tdmi, &tda->tda_dn->dn_muxes, tdmi_adapter_link) { - if(tdmi_compare_key(&tdmi->tdmi_conf, dmc)) + LIST_FOREACH(tdmi, &tda->tda_dn->dn_mux_instances, tdmi_adapter_link) { + if(tdmi_compare_key(&tdmi->tdmi_mux->dm_conf, dmc)) break; /* Mux already exist */ } @@ -174,25 +172,25 @@ dvb_mux_create(th_dvb_adapter_t *tda, const struct dvb_mux_conf *dmc, char buf2[1024]; buf2[0] = 0; - if(tdmi_compare_conf(tda->tda_type, &tdmi->tdmi_conf, dmc)) { + if(tdmi_compare_conf(tda->tda_fe_type, &tdmi->tdmi_mux->dm_conf, dmc)) { #if DVB_API_VERSION >= 5 snprintf(buf2, sizeof(buf2), " ("); - if (tdmi->tdmi_conf.dmc_fe_modulation != dmc->dmc_fe_modulation) + if (tdmi->tdmi_mux->dm_conf.dmc_fe_modulation != dmc->dmc_fe_modulation) sprintf(buf2, "%s %s->%s, ", buf2, - dvb_mux_qam2str(tdmi->tdmi_conf.dmc_fe_modulation), + dvb_mux_qam2str(tdmi->tdmi_mux->dm_conf.dmc_fe_modulation), dvb_mux_qam2str(dmc->dmc_fe_modulation)); - if (tdmi->tdmi_conf.dmc_fe_delsys != dmc->dmc_fe_delsys) + if (tdmi->tdmi_mux->dm_conf.dmc_fe_delsys != dmc->dmc_fe_delsys) sprintf(buf2, "%s %s->%s, ", buf2, - dvb_mux_delsys2str(tdmi->tdmi_conf.dmc_fe_delsys), + dvb_mux_delsys2str(tdmi->tdmi_mux->dm_conf.dmc_fe_delsys), dvb_mux_delsys2str(dmc->dmc_fe_delsys)); - if (tdmi->tdmi_conf.dmc_fe_rolloff != dmc->dmc_fe_rolloff) + if (tdmi->tdmi_mux->dm_conf.dmc_fe_rolloff != dmc->dmc_fe_rolloff) sprintf(buf2, "%s %s->%s, ", buf2, - dvb_mux_rolloff2str(tdmi->tdmi_conf.dmc_fe_rolloff), + dvb_mux_rolloff2str(tdmi->tdmi_mux->dm_conf.dmc_fe_rolloff), dvb_mux_rolloff2str(dmc->dmc_fe_rolloff)); sprintf(buf2, "%s)", buf2); #endif - memcpy(&tdmi->tdmi_conf, dmc, sizeof(struct dvb_mux_conf)); + memcpy(&tdmi->tdmi_mux->dm_conf, dmc, sizeof(struct dvb_mux_conf)); save = 1; } @@ -227,6 +225,10 @@ dvb_mux_create(th_dvb_adapter_t *tda, const struct dvb_mux_conf *dmc, tdmi = calloc(1, sizeof(th_dvb_mux_instance_t)); + tdmi->tdmi_mux = calloc(1, sizeof(dvb_mux_t)); + + tdmi->tdmi_mux->dm_network = tda->tda_dn; + if(identifier == NULL) { char qpsktxt[20]; @@ -236,12 +238,8 @@ dvb_mux_create(th_dvb_adapter_t *tda, const struct dvb_mux_conf *dmc, else qpsktxt[0] = 0; - snprintf(buf, sizeof(buf), "%s%d%s%s%s", - tda->tda_identifier, dmc->dmc_fe_params.frequency, qpsktxt, - (satconf || dmc->dmc_satconf) ? "_satconf_" : "", - (satconf ? satconf->sc_id : - (dmc->dmc_satconf ? dmc->dmc_satconf->sc_id : ""))); - + 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); @@ -272,15 +270,9 @@ dvb_mux_create(th_dvb_adapter_t *tda, const struct dvb_mux_conf *dmc, tdmi->tdmi_network = network ? strdup(network) : NULL; tdmi->tdmi_quality = 100; - memcpy(&tdmi->tdmi_conf, dmc, sizeof(struct dvb_mux_conf)); - if(satconf) - tdmi->tdmi_conf.dmc_satconf = satconf; - if(tdmi->tdmi_conf.dmc_satconf != NULL) { - LIST_INSERT_HEAD(&tdmi->tdmi_conf.dmc_satconf->sc_tdmis, - tdmi, tdmi_satconf_link); - } + memcpy(&tdmi->tdmi_mux->dm_conf, dmc, sizeof(struct dvb_mux_conf)); - LIST_INSERT_HEAD(&tda->tda_dn->dn_muxes, tdmi, tdmi_adapter_link); + LIST_INSERT_HEAD(&tda->tda_dn->dn_mux_instances, tdmi, tdmi_adapter_link); tdmi->tdmi_table_initial = initialscan; if(source != NULL) { @@ -316,7 +308,7 @@ dvb_mux_destroy(th_dvb_mux_instance_t *tdmi) hts_settings_remove("dvbmuxes/%s/%s", tda->tda_identifier, tdmi->tdmi_identifier); - while((t = LIST_FIRST(&tdmi->tdmi_transports)) != NULL) { + 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); @@ -328,9 +320,6 @@ dvb_mux_destroy(th_dvb_mux_instance_t *tdmi) if(tda->tda_mux_current == tdmi) dvb_fe_stop(tda->tda_mux_current, 0); - if(tdmi->tdmi_conf.dmc_satconf != NULL) - LIST_REMOVE(tdmi, tdmi_satconf_link); - RB_REMOVE(&dvb_muxes, tdmi, tdmi_global_link); LIST_REMOVE(tdmi, tdmi_adapter_link); @@ -552,7 +541,8 @@ int dvb_mux_str2hier(const char *str) void dvb_mux_save(th_dvb_mux_instance_t *tdmi) { - struct dvb_frontend_parameters *f = &tdmi->tdmi_conf.dmc_fe_params; + const dvb_mux_conf_t *dmc = &tdmi->tdmi_mux->dm_conf; + const struct dvb_frontend_parameters *f = &dmc->dmc_fe_params; htsmsg_t *m = htsmsg_create_map(); @@ -572,7 +562,7 @@ dvb_mux_save(th_dvb_mux_instance_t *tdmi) if(tdmi->tdmi_default_authority) htsmsg_add_str(m, "default_authority", tdmi->tdmi_default_authority); - switch(tdmi->tdmi_adapter->tda_type) { + switch(tdmi->tdmi_adapter->tda_fe_type) { case FE_OFDM: htsmsg_add_str(m, "bandwidth", val2str(f->u.ofdm.bandwidth, bwtab)); @@ -603,17 +593,17 @@ dvb_mux_save(th_dvb_mux_instance_t *tdmi) val2str(f->u.qpsk.fec_inner, fectab)); htsmsg_add_str(m, "polarisation", - val2str(tdmi->tdmi_conf.dmc_polarisation, poltab)); + val2str(dmc->dmc_polarisation, poltab)); #if DVB_API_VERSION >= 5 htsmsg_add_str(m, "modulation", - val2str(tdmi->tdmi_conf.dmc_fe_modulation, qamtab)); + val2str(dmc->dmc_fe_modulation, qamtab)); htsmsg_add_str(m, "delivery_system", - val2str(tdmi->tdmi_conf.dmc_fe_delsys, delsystab)); + val2str(dmc->dmc_fe_delsys, delsystab)); htsmsg_add_str(m, "rolloff", - val2str(tdmi->tdmi_conf.dmc_fe_rolloff, rollofftab)); + val2str(dmc->dmc_fe_rolloff, rollofftab)); #endif break; @@ -633,10 +623,7 @@ dvb_mux_save(th_dvb_mux_instance_t *tdmi) break; } - if(tdmi->tdmi_conf.dmc_satconf != NULL) - htsmsg_add_str(m, "satconf", tdmi->tdmi_conf.dmc_satconf->sc_id); - - hts_settings_save(m, "dvbmuxes/%s/%s", + hts_settings_save(m, "dvbmuxes/%s/%s", tdmi->tdmi_adapter->tda_identifier, tdmi->tdmi_identifier); htsmsg_destroy(m); } @@ -660,7 +647,7 @@ tdmi_create_by_msg(th_dvb_adapter_t *tda, htsmsg_t *m, const char *identifier) htsmsg_get_u32(m, "frequency", &dmc.dmc_fe_params.frequency); - switch(tda->tda_type) { + switch(tda->tda_fe_type) { case FE_OFDM: s = htsmsg_get_str(m, "bandwidth"); if(s == NULL || (r = str2val(s, bwtab)) < 0) @@ -773,16 +760,11 @@ tdmi_create_by_msg(th_dvb_adapter_t *tda, htsmsg_t *m, const char *identifier) if(htsmsg_get_u32(m, "enabled", &enabled)) enabled = 1; - if((s = htsmsg_get_str(m, "satconf")) != NULL) - dmc.dmc_satconf = dvb_satconf_entry_find(tda, s, 0); - else - dmc.dmc_satconf = NULL; - 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, NULL); + identifier); if(tdmi != NULL) { if((s = htsmsg_get_str(m, "status")) != NULL) @@ -956,9 +938,10 @@ dvb_mux_fe_status(char *buf, size_t size, th_dvb_mux_instance_t *tdmi) static void dvb_mux_modulation(char *buf, size_t size, th_dvb_mux_instance_t *tdmi) { - struct dvb_frontend_parameters *f = &tdmi->tdmi_conf.dmc_fe_params; + const dvb_mux_conf_t *dmc = &tdmi->tdmi_mux->dm_conf; + const struct dvb_frontend_parameters *f = &dmc->dmc_fe_params; - switch(tdmi->tdmi_adapter->tda_type) { + switch(tdmi->tdmi_adapter->tda_fe_type) { case FE_OFDM: snprintf(buf, size, "%s, %s, %s-mode", val2str(f->u.ofdm.constellation, qamtab), @@ -969,8 +952,8 @@ dvb_mux_modulation(char *buf, size_t size, th_dvb_mux_instance_t *tdmi) case FE_QPSK: #if DVB_API_VERSION >= 5 snprintf(buf, size, "%d kBaud, %s, %s", f->u.qpsk.symbol_rate / 1000, - val2str(tdmi->tdmi_conf.dmc_fe_delsys, delsystab), - val2str(tdmi->tdmi_conf.dmc_fe_modulation, qamtab)); + val2str(dmc->dmc_fe_delsys, delsystab), + val2str(dmc->dmc_fe_modulation, qamtab)); #else snprintf(buf, size, "%d kBaud", f->u.qpsk.symbol_rate / 1000); #endif @@ -1005,7 +988,7 @@ dvb_mux_build_msg(th_dvb_mux_instance_t *tdmi) htsmsg_add_u32(m, "enabled", tdmi->tdmi_enabled); htsmsg_add_str(m, "network", tdmi->tdmi_network ?: ""); - dvb_mux_nicefreq(buf, sizeof(buf), tdmi); + dvb_mux_nicefreq(buf, sizeof(buf), tdmi->tdmi_mux); htsmsg_add_str(m, "freq", buf); dvb_mux_modulation(buf, sizeof(buf), tdmi); @@ -1014,11 +997,11 @@ dvb_mux_build_msg(th_dvb_mux_instance_t *tdmi) dvb_mux_fe_status(buf, sizeof(buf), tdmi); htsmsg_add_str(m, "fe_status", buf); - htsmsg_add_str(m, "pol", - dvb_polarisation_to_str_long(tdmi->tdmi_conf.dmc_polarisation)); + const dvb_mux_conf_t *dmc = &tdmi->tdmi_mux->dm_conf; - if(tdmi->tdmi_conf.dmc_satconf != NULL) - htsmsg_add_str(m, "satconf", tdmi->tdmi_conf.dmc_satconf->sc_id); + + htsmsg_add_str(m, "pol", + dvb_polarisation_to_str_long(dmc->dmc_polarisation)); if(tdmi->tdmi_transport_stream_id != 0xffff) htsmsg_add_u32(m, "muxid", tdmi->tdmi_transport_stream_id); @@ -1066,7 +1049,7 @@ dvb_mux_add_by_params(th_dvb_adapter_t *tda, memset(&dmc, 0, sizeof(dmc)); dmc.dmc_fe_params.inversion = INVERSION_AUTO; - switch(tda->tda_type) { + switch(tda->tda_fe_type) { case FE_OFDM: dmc.dmc_fe_params.frequency = freq * 1000; if(!val2str(bw, bwtab)) @@ -1150,16 +1133,9 @@ dvb_mux_add_by_params(th_dvb_adapter_t *tda, } - if(satconf != NULL) { - dmc.dmc_satconf = dvb_satconf_entry_find(tda, satconf, 0); - if(dmc.dmc_satconf == NULL) - return "Satellite configuration not found"; - } else { - dmc.dmc_satconf = NULL; - } dmc.dmc_polarisation = polarisation; - tdmi = dvb_mux_create(tda, &dmc, 0, 0xffff, NULL, NULL, 1, 1, NULL, NULL); + tdmi = dvb_mux_create(tda, &dmc, 0, 0xffff, NULL, NULL, 1, 1, NULL); if(tdmi == NULL) return "Mux already exist"; @@ -1167,7 +1143,7 @@ dvb_mux_add_by_params(th_dvb_adapter_t *tda, return NULL; } - +#if 0 /** * */ @@ -1191,7 +1167,7 @@ dvb_mux_copy(th_dvb_adapter_t *dst, th_dvb_mux_instance_t *tdmi_src, if(tdmi_dst == NULL) return -1; // Already exist - LIST_FOREACH(t_src, &tdmi_src->tdmi_transports, s_group_link) { + LIST_FOREACH(t_src, &tdmi_src->tdmi_mux->dm_services, s_group_link) { t_dst = dvb_service_find(tdmi_dst, t_src->s_dvb_service_id, t_src->s_pmt_pid, NULL); @@ -1245,6 +1221,7 @@ dvb_mux_copy(th_dvb_adapter_t *dst, th_dvb_mux_instance_t *tdmi_src, dvb_mux_save(tdmi_dst); return 0; } +#endif th_dvb_mux_instance_t *dvb_mux_find ( th_dvb_adapter_t *tda, const char *netname, uint16_t onid, uint16_t tsid, @@ -1252,7 +1229,7 @@ th_dvb_mux_instance_t *dvb_mux_find { th_dvb_mux_instance_t *tdmi; if (tda) { - LIST_FOREACH(tdmi, &tda->tda_dn->dn_muxes, tdmi_adapter_link) { + LIST_FOREACH(tdmi, &tda->tda_dn->dn_mux_instances, tdmi_adapter_link) { if (enabled && !tdmi->tdmi_enabled) continue; if (onid && onid != tdmi->tdmi_network_id) continue; if (tsid && tsid != tdmi->tdmi_transport_stream_id) continue; diff --git a/src/dvb/dvb_preconf.c b/src/dvb/dvb_preconf.c index 755340db..1dfb5234 100644 --- a/src/dvb/dvb_preconf.c +++ b/src/dvb/dvb_preconf.c @@ -36,7 +36,7 @@ */ static void dvb_mux_preconf_add(th_dvb_adapter_t *tda, const network_t *net, - const char *source, const char *satconf) + const char *source) { const mux_t *m; struct dvb_mux_conf dmc; @@ -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_type) { + switch(tda->tda_fe_type) { case FE_OFDM: dmc.dmc_fe_params.u.ofdm.bandwidth = m->bw; dmc.dmc_fe_params.u.ofdm.constellation = m->constellation; @@ -96,9 +96,7 @@ dvb_mux_preconf_add(th_dvb_adapter_t *tda, const network_t *net, break; } - dmc.dmc_satconf = dvb_satconf_entry_find(tda, satconf, 0); - - dvb_mux_create(tda, &dmc, 0, 0xffff, NULL, source, 1, 1, NULL, NULL); + dvb_mux_create(tda, &dmc, 0, 0xffff, NULL, source, 1, 1, NULL); } } @@ -107,8 +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, - const char *satconf) +dvb_mux_preconf_add_network(th_dvb_adapter_t *tda, const char *id) { region_list_t *list; const region_t *r; @@ -117,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_type) { + switch(tda->tda_fe_type) { case FE_QAM: list = ®ions_DVBC; break; @@ -137,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, satconf); + dvb_mux_preconf_add(tda, n, source); break; } } diff --git a/src/dvb/dvb_preconf.h b/src/dvb/dvb_preconf.h index 71dbce28..a76f3a7e 100644 --- a/src/dvb/dvb_preconf.h +++ b/src/dvb/dvb_preconf.h @@ -23,7 +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, - const char *satconf); +int dvb_mux_preconf_add_network(th_dvb_adapter_t *tda, const char *id); #endif /* DVB_MUXCONFIG_H */ diff --git a/src/dvb/dvb_satconf.c b/src/dvb/dvb_satconf.c index ba607ef5..b0d609de 100644 --- a/src/dvb/dvb_satconf.c +++ b/src/dvb/dvb_satconf.c @@ -87,14 +87,7 @@ dvb_satconf_entry_find(th_dvb_adapter_t *tda, const char *id, int create) static void satconf_destroy(th_dvb_adapter_t *tda, dvb_satconf_t *sc) { - th_dvb_mux_instance_t *tdmi; - - while((tdmi = LIST_FIRST(&sc->sc_tdmis)) != NULL) { - tdmi->tdmi_conf.dmc_satconf = NULL; - LIST_REMOVE(tdmi, tdmi_satconf_link); - } - - TAILQ_REMOVE(&tda->tda_satconfs, sc, sc_adapter_link); + TAILQ_REMOVE(&tda->tda_satconfs, sc, sc_adapter_link); free(sc->sc_id); free(sc->sc_name); free(sc->sc_comment); diff --git a/src/dvb/dvb_service.c b/src/dvb/dvb_service.c index 821e9a30..9474338d 100644 --- a/src/dvb/dvb_service.c +++ b/src/dvb/dvb_service.c @@ -346,13 +346,13 @@ dvb_service_find3 { service_t *svc; if (tdmi) { - LIST_FOREACH(svc, &tdmi->tdmi_transports, s_group_link) { + LIST_FOREACH(svc, &tdmi->tdmi_mux->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_muxes, tdmi_adapter_link) { + LIST_FOREACH(tdmi, &tda->tda_dn->dn_mux_instances, tdmi_adapter_link) { if (enabled && !tdmi->tdmi_enabled) continue; if (onid && onid != tdmi->tdmi_network_id) continue; if (tsid && tsid != tdmi->tdmi_transport_stream_id) continue; @@ -393,7 +393,7 @@ dvb_service_find2(th_dvb_mux_instance_t *tdmi, uint16_t sid, int pmt_pid, lock_assert(&global_lock); - LIST_FOREACH(t, &tdmi->tdmi_transports, s_group_link) { + LIST_FOREACH(t, &tdmi->tdmi_mux->dm_services, s_group_link) { if(t->s_dvb_service_id == sid) return t; } @@ -424,7 +424,7 @@ dvb_service_find2(th_dvb_mux_instance_t *tdmi, uint16_t sid, int pmt_pid, t->s_grace_period = dvb_grace_period; t->s_dvb_mux_instance = tdmi; - LIST_INSERT_HEAD(&tdmi->tdmi_transports, t, s_group_link); + LIST_INSERT_HEAD(&tdmi->tdmi_mux->dm_services, t, s_group_link); pthread_mutex_lock(&t->s_stream_mutex); service_make_nicename(t); @@ -460,7 +460,7 @@ dvb_service_build_msg(service_t *t) htsmsg_add_str(m, "network", tdmi->tdmi_network ?: ""); - dvb_mux_nicefreq(buf, sizeof(buf), tdmi); + dvb_mux_nicefreq(buf, sizeof(buf), tdmi->tdmi_mux); htsmsg_add_str(m, "mux", buf); if(t->s_ch != NULL) diff --git a/src/dvb/dvb_support.c b/src/dvb/dvb_support.c index 64b35b2a..4b8679ee 100644 --- a/src/dvb/dvb_support.c +++ b/src/dvb/dvb_support.c @@ -466,16 +466,16 @@ nicenum(char *x, size_t siz, unsigned int v) * */ void -dvb_mux_nicefreq(char *buf, size_t size, th_dvb_mux_instance_t *tdmi) +dvb_mux_nicefreq(char *buf, size_t size, const dvb_mux_t *dm) { char freq[50]; - if(tdmi->tdmi_adapter->tda_type == FE_QPSK) { - nicenum(freq, sizeof(freq), tdmi->tdmi_conf.dmc_fe_params.frequency); + if(dm->dm_network->dn_fe_type == FE_QPSK) { + nicenum(freq, sizeof(freq), dm->dm_conf.dmc_fe_params.frequency); snprintf(buf, size, "%s kHz", freq); } else { nicenum(freq, sizeof(freq), - tdmi->tdmi_conf.dmc_fe_params.frequency / 1000); + dm->dm_conf.dmc_fe_params.frequency / 1000); snprintf(buf, size, "%s kHz", freq); } } @@ -489,16 +489,16 @@ dvb_mux_nicename(char *buf, size_t size, th_dvb_mux_instance_t *tdmi) { char freq[50]; const char *n = tdmi->tdmi_network; + const dvb_mux_t *dm = tdmi->tdmi_mux; - if(tdmi->tdmi_adapter->tda_type == FE_QPSK) { - nicenum(freq, sizeof(freq), tdmi->tdmi_conf.dmc_fe_params.frequency); - snprintf(buf, size, "%s%s%s kHz %s (%s)", + if(tdmi->tdmi_adapter->tda_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, - dvb_polarisation_to_str_long(tdmi->tdmi_conf.dmc_polarisation), - tdmi->tdmi_conf.dmc_satconf ? tdmi->tdmi_conf.dmc_satconf->sc_name : "No satconf"); + dvb_polarisation_to_str_long(dm->dm_conf.dmc_polarisation)); } else { - nicenum(freq, sizeof(freq), tdmi->tdmi_conf.dmc_fe_params.frequency / 1000); + nicenum(freq, sizeof(freq), dm->dm_conf.dmc_fe_params.frequency / 1000); snprintf(buf, size, "%s%s%s kHz", n?:"", n ? ": ":"", freq); } } diff --git a/src/dvb/dvb_support.h b/src/dvb/dvb_support.h index 22e81eca..3d6aabe7 100644 --- a/src/dvb/dvb_support.h +++ b/src/dvb/dvb_support.h @@ -82,7 +82,7 @@ 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); 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, th_dvb_mux_instance_t *tdmi); +void dvb_mux_nicefreq(char *buf, size_t size, const dvb_mux_t *dm); void atsc_utf16_to_utf8(uint8_t *src, int len, char *buf, int buflen); diff --git a/src/dvb/dvb_tables.c b/src/dvb/dvb_tables.c index 29ac020e..723664a8 100644 --- a/src/dvb/dvb_tables.c +++ b/src/dvb/dvb_tables.c @@ -267,7 +267,7 @@ dvb_bat_callback(th_dvb_mux_instance_t *tdmi, uint8_t *buf, int len, j = 0; /* Find TDMI */ - LIST_FOREACH(tdmi, &tda->tda_dn->dn_muxes, tdmi_adapter_link) + LIST_FOREACH(tdmi, &tda->tda_dn->dn_mux_instances, tdmi_adapter_link) if(tdmi->tdmi_transport_stream_id == tsid && tdmi->tdmi_network_id == onid) break; @@ -337,7 +337,7 @@ dvb_sdt_callback(th_dvb_mux_instance_t *tdmi, uint8_t *ptr, int len, if(!tdmi->tdmi_network_id) dvb_mux_set_onid(tdmi, onid); } else { - LIST_FOREACH(tdmi, &tda->tda_dn->dn_muxes, tdmi_adapter_link) + LIST_FOREACH(tdmi, &tda->tda_dn->dn_mux_instances, tdmi_adapter_link) if(tdmi->tdmi_transport_stream_id == tsid && tdmi->tdmi_network_id != onid) break; @@ -495,9 +495,8 @@ dvb_pat_callback(th_dvb_mux_instance_t *tdmi, uint8_t *ptr, int len, // Make sure this TSID is not already known on another mux // That might indicate that we have accedentally received a PAT // from another mux - LIST_FOREACH(other, &tda->tda_dn->dn_muxes, tdmi_adapter_link) - if(other != tdmi && - other->tdmi_conf.dmc_satconf == tdmi->tdmi_conf.dmc_satconf && + LIST_FOREACH(other, &tda->tda_dn->dn_mux_instances, tdmi_adapter_link) + if(other != tdmi && other->tdmi_transport_stream_id == tsid && other->tdmi_network_id == tdmi->tdmi_network_id) return -1; @@ -653,7 +652,7 @@ dvb_table_cable_delivery(th_dvb_mux_instance_t *tdmi, uint8_t *ptr, int len, dmc.dmc_fe_params.u.qam.fec_inner = fec_tab[ptr[10] & 0x07]; dvb_mux_create(tdmi->tdmi_adapter, &dmc, onid, tsid, NULL, - "automatic mux discovery", 1, 1, NULL, NULL); + "automatic mux discovery", 1, 1, NULL); return 0; } @@ -695,8 +694,6 @@ dvb_table_sat_delivery(th_dvb_mux_instance_t *tdmi, uint8_t *ptr, int len, dmc.dmc_fe_params.u.qam.fec_inner = fec_tab[ptr[10] & 0x0f]; dmc.dmc_polarisation = (ptr[6] >> 5) & 0x03; - // Same satconf (lnb, switch, etc) - dmc.dmc_satconf = tdmi->tdmi_conf.dmc_satconf; #if DVB_API_VERSION >= 5 int modulation = (ptr[6] & 0x03); @@ -738,8 +735,7 @@ dvb_table_sat_delivery(th_dvb_mux_instance_t *tdmi, uint8_t *ptr, int len, #endif dvb_mux_create(tdmi->tdmi_adapter, &dmc, onid, tsid, NULL, - "automatic mux discovery", 1, 1, NULL, tdmi->tdmi_conf.dmc_satconf); - + "automatic mux discovery", 1, 1, NULL); return 0; } @@ -755,7 +751,7 @@ dvb_table_local_channel(th_dvb_mux_instance_t *tdmi, uint8_t *ptr, int len, th_dvb_adapter_t *tda = tdmi->tdmi_adapter; service_t *t; - LIST_FOREACH(tdmi, &tda->tda_dn->dn_muxes, tdmi_adapter_link) + LIST_FOREACH(tdmi, &tda->tda_dn->dn_mux_instances, tdmi_adapter_link) if(tdmi->tdmi_transport_stream_id == tsid && tdmi->tdmi_network_id == onid) break; @@ -872,11 +868,11 @@ dvb_nit_callback(th_dvb_mux_instance_t *tdmi, uint8_t *ptr, int len, switch(tag) { case DVB_DESC_SAT: - if(tdmi->tdmi_adapter->tda_type == FE_QPSK) + if(tdmi->tdmi_adapter->tda_fe_type == FE_QPSK) dvb_table_sat_delivery(tdmi, ptr, tlen, tsid, onid); break; case DVB_DESC_CABLE: - if(tdmi->tdmi_adapter->tda_type == FE_QAM) + if(tdmi->tdmi_adapter->tda_fe_type == FE_QAM) dvb_table_cable_delivery(tdmi, ptr, tlen, tsid, onid); break; case DVB_DESC_LOCAL_CHAN: @@ -935,7 +931,7 @@ atsc_vct_callback(th_dvb_mux_instance_t *tdmi, uint8_t *ptr, int len, onid = (ptr[24] << 8) | ptr[25]; /* Search all muxes on adapter */ - LIST_FOREACH(tdmi, &tda->tda_dn->dn_muxes, tdmi_adapter_link) + LIST_FOREACH(tdmi, &tda->tda_dn->dn_mux_instances, tdmi_adapter_link) if(tdmi->tdmi_transport_stream_id == tsid && tdmi->tdmi_network_id == onid); break; @@ -988,7 +984,7 @@ dvb_pmt_callback(th_dvb_mux_instance_t *tdmi, uint8_t *ptr, int len, service_t *t; th_dvb_table_t *tdt = opaque; - LIST_FOREACH(t, &tdmi->tdmi_transports, s_group_link) { + LIST_FOREACH(t, &tdmi->tdmi_mux->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) @@ -1036,7 +1032,7 @@ dvb_table_add_default_atsc(th_dvb_mux_instance_t *tdmi) { int tableid; - if(tdmi->tdmi_conf.dmc_fe_params.u.vsb.modulation == VSB_8) { + if(tdmi->tdmi_mux->dm_conf.dmc_fe_params.u.vsb.modulation == VSB_8) { tableid = 0xc8; // Terrestrial } else { tableid = 0xc9; // Cable @@ -1064,7 +1060,7 @@ dvb_table_add_default(th_dvb_mux_instance_t *tdmi) TDT_CRC, 1); - switch(tdmi->tdmi_adapter->tda_type) { + switch(tdmi->tdmi_adapter->tda_fe_type) { case FE_QPSK: case FE_OFDM: case FE_QAM: diff --git a/src/epggrab/otamux.c b/src/epggrab/otamux.c index 16def861..517d4a68 100644 --- a/src/epggrab/otamux.c +++ b/src/epggrab/otamux.c @@ -255,7 +255,7 @@ void epggrab_ota_create_and_register_by_id th_dvb_mux_instance_t *tdmi; epggrab_ota_mux_t *ota; TAILQ_FOREACH(tda, &dvb_adapters, tda_global_link) { - LIST_FOREACH(tdmi, &tda->tda_dn->dn_muxes, tdmi_adapter_link) { + LIST_FOREACH(tdmi, &tda->tda_dn->dn_mux_instances, tdmi_adapter_link) { if (tdmi->tdmi_transport_stream_id != tsid) continue; if (onid && tdmi->tdmi_network_id != onid) continue; if (networkname && (!tdmi->tdmi_network || strcmp(networkname, tdmi->tdmi_network))) continue; diff --git a/src/webui/extjs_dvb.c b/src/webui/extjs_dvb.c index e8948351..211602f1 100644 --- a/src/webui/extjs_dvb.c +++ b/src/webui/extjs_dvb.c @@ -72,7 +72,7 @@ extjs_dvblocations(http_connection_t *hc, const char *remain, void *opaque) pthread_mutex_unlock(&global_lock); - if((out = dvb_mux_preconf_get_node(tda->tda_type, s)) == NULL) + if((out = dvb_mux_preconf_get_node(tda->tda_fe_type, s)) == NULL) return 404; htsmsg_json_serialize(out, hq, 0); @@ -110,7 +110,7 @@ extjs_dvbadapter(http_connection_t *hc, const char *remain, void *opaque) htsmsg_t *out, *array, *r; 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, *sc; + const char *s; th_dvb_mux_instance_t *tdmi; service_t *t; @@ -124,7 +124,7 @@ extjs_dvbadapter(http_connection_t *hc, const char *remain, void *opaque) array = htsmsg_create_list(); TAILQ_FOREACH(tda, &dvb_adapters, tda_global_link) { - if(ref == NULL || (ref != tda && ref->tda_type == tda->tda_type)) + if(ref == NULL || (ref != tda && ref->tda_fe_type == tda->tda_fe_type)) htsmsg_add_msg(array, NULL, dvb_adapter_build_msg(tda)); } pthread_mutex_unlock(&global_lock); @@ -224,10 +224,10 @@ extjs_dvbadapter(http_connection_t *hc, const char *remain, void *opaque) htsmsg_add_u32(out, "success", 1); } else if(!strcmp(op, "addnetwork")) { - sc = http_arg_get(&hc->hc_req_args, "satconf"); +// sc = http_arg_get(&hc->hc_req_args, "satconf"); if((s = http_arg_get(&hc->hc_req_args, "network")) != NULL) - dvb_mux_preconf_add_network(tda, s, sc); + dvb_mux_preconf_add_network(tda, s); out = htsmsg_create_map(); htsmsg_add_u32(out, "success", 1); @@ -237,8 +237,8 @@ extjs_dvbadapter(http_connection_t *hc, const char *remain, void *opaque) tvhlog(LOG_NOTICE, "web interface", "Service probe started on \"%s\"", tda->tda_displayname); - LIST_FOREACH(tdmi, &tda->tda_dn->dn_muxes, tdmi_adapter_link) { - LIST_FOREACH(t, &tdmi->tdmi_transports, s_group_link) { + LIST_FOREACH(tdmi, &tda->tda_dn->dn_mux_instances, tdmi_adapter_link) { + LIST_FOREACH(t, &tdmi->tdmi_mux->dm_services, s_group_link) { if(t->s_enabled) serviceprobe_enqueue(t); } @@ -334,7 +334,7 @@ extjs_dvbmuxes(http_connection_t *hc, const char *remain, void *opaque) if(!strcmp(op, "get")) { array = htsmsg_create_list(); - LIST_FOREACH(tdmi, &tda->tda_dn->dn_muxes, tdmi_adapter_link) + LIST_FOREACH(tdmi, &tda->tda_dn->dn_mux_instances, tdmi_adapter_link) htsmsg_add_msg(array, NULL, dvb_mux_build_msg(tdmi)); htsmsg_add_msg(out, "entries", array); @@ -415,16 +415,16 @@ extjs_dvbservices(http_connection_t *hc, const char *remain, void *opaque) out = htsmsg_create_map(); array = htsmsg_create_list(); - LIST_FOREACH(tdmi, &tda->tda_dn->dn_muxes, tdmi_adapter_link) { - LIST_FOREACH(t, &tdmi->tdmi_transports, s_group_link) { + LIST_FOREACH(tdmi, &tda->tda_dn->dn_mux_instances, tdmi_adapter_link) { + LIST_FOREACH(t, &tdmi->tdmi_mux->dm_services, s_group_link) { count++; } } tvec = alloca(sizeof(service_t *) * count); - LIST_FOREACH(tdmi, &tda->tda_dn->dn_muxes, tdmi_adapter_link) { - LIST_FOREACH(t, &tdmi->tdmi_transports, s_group_link) { + LIST_FOREACH(tdmi, &tda->tda_dn->dn_mux_instances, tdmi_adapter_link) { + LIST_FOREACH(t, &tdmi->tdmi_mux->dm_services, s_group_link) { tvec[i++] = t; } } @@ -608,7 +608,7 @@ extjs_dvb_addmux(http_connection_t *hc, const char *remain, void *opaque) return 0; } - +#if 0 /** * */ @@ -672,6 +672,7 @@ extjs_dvb_copymux(http_connection_t *hc, const char *remain, void *opaque) return 0; } +#endif /** * @@ -766,8 +767,9 @@ 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 } diff --git a/src/webui/statedump.c b/src/webui/statedump.c index 10d12977..ff7e4ef9 100644 --- a/src/webui/statedump.c +++ b/src/webui/statedump.c @@ -134,14 +134,14 @@ dumpdvbadapters(htsbuf_queue_t *hq) htsbuf_qprintf(hq, "%s (%s)\n", tda->tda_displayname, tda->tda_identifier); outputtitle(hq, 4, "Multiplexes"); - LIST_FOREACH(tdmi, &tda->tda_dn->dn_muxes, tdmi_adapter_link) { + 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_transports, 8); + dumptransports(hq, &tdmi->tdmi_mux->dm_services, 8); } } } From f1eef1f50221551175d98cc7f42d0f5de1daace9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20=C3=96man?= Date: Wed, 5 Dec 2012 09:26:07 +0100 Subject: [PATCH 13/31] Remove unused tdmi_satconf_link --- src/dvb/dvb.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/dvb/dvb.h b/src/dvb/dvb.h index d03b0dde..2ea7b179 100644 --- a/src/dvb/dvb.h +++ b/src/dvb/dvb.h @@ -161,9 +161,6 @@ typedef struct th_dvb_mux_instance { int tdmi_enabled; - /* Linked if tdmi_conf.dmc_satconf != NULL */ - LIST_ENTRY(th_dvb_mux_instance) tdmi_satconf_link; - uint32_t tdmi_network_id; uint16_t tdmi_transport_stream_id; From e9604bd9deb7b4c761b82359d52da27516a0d865 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20=C3=96man?= Date: Wed, 5 Dec 2012 10:05:55 +0100 Subject: [PATCH 14/31] Move more code from th_dvb_mux_instance_t to dvb_mux_t uint32_t dm_network_id; uint16_t dm_transport_stream_id; char *dm_network_name; /* Name of network, from NIT table */ char *dm_default_authority; --- src/dvb/dvb.h | 12 +++---- src/dvb/dvb_multiplex.c | 71 +++++++++++++++++++------------------ src/dvb/dvb_service.c | 12 +++---- src/dvb/dvb_support.c | 4 +-- src/dvb/dvb_tables.c | 34 +++++++++--------- src/epggrab/module/eit.c | 10 +++--- src/epggrab/module/opentv.c | 2 +- src/epggrab/otamux.c | 19 ++++++---- 8 files changed, 87 insertions(+), 77 deletions(-) diff --git a/src/dvb/dvb.h b/src/dvb/dvb.h index 2ea7b179..cf5de01a 100644 --- a/src/dvb/dvb.h +++ b/src/dvb/dvb.h @@ -109,12 +109,17 @@ typedef struct dvb_network { typedef struct dvb_mux { // LIST_ENTRY(dvb_mux) dm_network_link; - dvb_network_t *dm_network; + dvb_network_t *dm_dn; struct service_list dm_services; dvb_mux_conf_t dm_conf; + uint32_t dm_network_id; + uint16_t dm_transport_stream_id; + char *dm_network_name; /* Name of network, from NIT table */ + char *dm_default_authority; + } dvb_mux_t; @@ -161,13 +166,8 @@ typedef struct th_dvb_mux_instance { int tdmi_enabled; - uint32_t tdmi_network_id; - uint16_t tdmi_transport_stream_id; char *tdmi_identifier; - char *tdmi_network; /* Name of network, from NIT table */ - - char *tdmi_default_authority; TAILQ_ENTRY(th_dvb_mux_instance) tdmi_scan_link; struct th_dvb_mux_instance_queue *tdmi_scan_queue; diff --git a/src/dvb/dvb_multiplex.c b/src/dvb/dvb_multiplex.c index a223bbfb..2a69cc6a 100644 --- a/src/dvb/dvb_multiplex.c +++ b/src/dvb/dvb_multiplex.c @@ -194,12 +194,12 @@ dvb_mux_create(th_dvb_adapter_t *tda, const struct dvb_mux_conf *dmc, save = 1; } - if(tsid != 0xFFFF && tdmi->tdmi_transport_stream_id != tsid) { - tdmi->tdmi_transport_stream_id = tsid; + if(tsid != 0xFFFF && tdmi->tdmi_mux->dm_transport_stream_id != tsid) { + tdmi->tdmi_mux->dm_transport_stream_id = tsid; save = 1; } - if(onid && tdmi->tdmi_network_id != onid) { - tdmi->tdmi_network_id = onid; + if(onid && tdmi->tdmi_mux->dm_network_id != onid) { + tdmi->tdmi_mux->dm_network_id = onid; save = 1; } @@ -223,11 +223,16 @@ dvb_mux_create(th_dvb_adapter_t *tda, const struct dvb_mux_conf *dmc, return NULL; } + dvb_mux_t *dm = calloc(1, sizeof(dvb_mux_t)); + + dm->dm_network_id = onid; + dm->dm_transport_stream_id = tsid; + dm->dm_network_name = network ? strdup(network) : NULL; + dm->dm_dn = tda->tda_dn; + + tdmi = calloc(1, sizeof(th_dvb_mux_instance_t)); - - tdmi->tdmi_mux = calloc(1, sizeof(dvb_mux_t)); - - tdmi->tdmi_mux->dm_network = tda->tda_dn; + tdmi->tdmi_mux = dm; if(identifier == NULL) { char qpsktxt[20]; @@ -264,10 +269,8 @@ dvb_mux_create(th_dvb_adapter_t *tda, const struct dvb_mux_conf *dmc, TAILQ_INIT(&tdmi->tdmi_table_queue); - tdmi->tdmi_network_id = onid; - tdmi->tdmi_transport_stream_id = tsid; + tdmi->tdmi_adapter = tda; - tdmi->tdmi_network = network ? strdup(network) : NULL; tdmi->tdmi_quality = 100; memcpy(&tdmi->tdmi_mux->dm_conf, dmc, sizeof(struct dvb_mux_conf)); @@ -333,7 +336,7 @@ dvb_mux_destroy(th_dvb_mux_instance_t *tdmi) hts_settings_remove("dvbmuxes/%s", tdmi->tdmi_identifier); - free(tdmi->tdmi_network); + // free(tdmi->tdmi_network_name); // XXX(dvbreorg) free(tdmi->tdmi_identifier); free(tdmi); @@ -550,17 +553,17 @@ dvb_mux_save(th_dvb_mux_instance_t *tdmi) htsmsg_add_u32(m, "enabled", tdmi->tdmi_enabled); htsmsg_add_str(m, "status", dvb_mux_status(tdmi)); - htsmsg_add_u32(m, "transportstreamid", tdmi->tdmi_transport_stream_id); - htsmsg_add_u32(m, "originalnetworkid", tdmi->tdmi_network_id); - if(tdmi->tdmi_network != NULL) - htsmsg_add_str(m, "network", tdmi->tdmi_network); + 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, "frequency", f->frequency); htsmsg_add_u32(m, "initialscan", tdmi->tdmi_table_initial); - if(tdmi->tdmi_default_authority) - htsmsg_add_str(m, "default_authority", tdmi->tdmi_default_authority); + if(tdmi->tdmi_mux->dm_default_authority) + htsmsg_add_str(m, "default_authority", tdmi->tdmi_mux->dm_default_authority); switch(tdmi->tdmi_adapter->tda_fe_type) { case FE_OFDM: @@ -774,7 +777,7 @@ tdmi_create_by_msg(th_dvb_adapter_t *tda, htsmsg_t *m, const char *identifier) tdmi->tdmi_quality = u32; if((s = htsmsg_get_str(m, "default_authority"))) - tdmi->tdmi_default_authority = strdup(s); + tdmi->tdmi_mux->dm_default_authority = strdup(s); } return NULL; } @@ -811,13 +814,13 @@ dvb_mux_set_networkname(th_dvb_mux_instance_t *tdmi, const char *networkname) { htsmsg_t *m; - free(tdmi->tdmi_network); - tdmi->tdmi_network = strdup(networkname); + free(tdmi->tdmi_mux->dm_network_name); + tdmi->tdmi_mux->dm_network_name = strdup(networkname); dvb_mux_save(tdmi); m = htsmsg_create_map(); htsmsg_add_str(m, "id", tdmi->tdmi_identifier); - htsmsg_add_str(m, "network", tdmi->tdmi_network ?: ""); + htsmsg_add_str(m, "network", tdmi->tdmi_mux->dm_network_name ?: ""); notify_by_msg("dvbMux", m); } @@ -830,13 +833,13 @@ dvb_mux_set_tsid(th_dvb_mux_instance_t *tdmi, uint16_t tsid) { htsmsg_t *m; - tdmi->tdmi_transport_stream_id = tsid; + tdmi->tdmi_mux->dm_transport_stream_id = tsid; dvb_mux_save(tdmi); m = htsmsg_create_map(); htsmsg_add_str(m, "id", tdmi->tdmi_identifier); - htsmsg_add_u32(m, "muxid", tdmi->tdmi_transport_stream_id); + htsmsg_add_u32(m, "muxid", tdmi->tdmi_mux->dm_transport_stream_id); notify_by_msg("dvbMux", m); } @@ -848,13 +851,13 @@ dvb_mux_set_onid(th_dvb_mux_instance_t *tdmi, uint16_t onid) { htsmsg_t *m; - tdmi->tdmi_network_id = onid; + tdmi->tdmi_mux->dm_network_id = onid; dvb_mux_save(tdmi); m = htsmsg_create_map(); htsmsg_add_str(m, "id", tdmi->tdmi_identifier); - htsmsg_add_u32(m, "onid", tdmi->tdmi_network_id); + htsmsg_add_u32(m, "onid", tdmi->tdmi_mux->dm_network_id); notify_by_msg("dvbMux", m); } @@ -986,7 +989,7 @@ dvb_mux_build_msg(th_dvb_mux_instance_t *tdmi) htsmsg_add_str(m, "id", tdmi->tdmi_identifier); htsmsg_add_u32(m, "enabled", tdmi->tdmi_enabled); - htsmsg_add_str(m, "network", tdmi->tdmi_network ?: ""); + htsmsg_add_str(m, "network", tdmi->tdmi_mux->dm_network_name ?: ""); dvb_mux_nicefreq(buf, sizeof(buf), tdmi->tdmi_mux); htsmsg_add_str(m, "freq", buf); @@ -1003,11 +1006,11 @@ dvb_mux_build_msg(th_dvb_mux_instance_t *tdmi) htsmsg_add_str(m, "pol", dvb_polarisation_to_str_long(dmc->dmc_polarisation)); - if(tdmi->tdmi_transport_stream_id != 0xffff) - htsmsg_add_u32(m, "muxid", tdmi->tdmi_transport_stream_id); + if(tdmi->tdmi_mux->dm_transport_stream_id != 0xffff) + htsmsg_add_u32(m, "muxid", tdmi->tdmi_mux->dm_transport_stream_id); - if(tdmi->tdmi_network_id) - htsmsg_add_u32(m, "onid", tdmi->tdmi_network_id); + if(tdmi->tdmi_mux->dm_network_id) + htsmsg_add_u32(m, "onid", tdmi->tdmi_mux->dm_network_id); htsmsg_add_u32(m, "quality", tdmi->tdmi_quality); return m; @@ -1231,9 +1234,9 @@ th_dvb_mux_instance_t *dvb_mux_find 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_network_id) continue; - if (tsid && tsid != tdmi->tdmi_transport_stream_id) continue; - if (netname && strcmp(netname, tdmi->tdmi_network ?: "")) 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; } } else { diff --git a/src/dvb/dvb_service.c b/src/dvb/dvb_service.c index 9474338d..088d2d22 100644 --- a/src/dvb/dvb_service.c +++ b/src/dvb/dvb_service.c @@ -312,8 +312,8 @@ dvb_service_setsourceinfo(service_t *t, struct source_info *si) si->si_adapter = strdup(tdmi->tdmi_adapter->tda_displayname); - if(tdmi->tdmi_network != NULL) - si->si_network = strdup(tdmi->tdmi_network); + 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); si->si_mux = strdup(buf); @@ -354,9 +354,9 @@ dvb_service_find3 } 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_network_id) continue; - if (tsid && tsid != tdmi->tdmi_transport_stream_id) continue; - if (netname && strcmp(netname, tdmi->tdmi_network ?: "")) 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))) return svc; @@ -458,7 +458,7 @@ 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_network ?: ""); + htsmsg_add_str(m, "network", tdmi->tdmi_mux->dm_network_name ?: ""); dvb_mux_nicefreq(buf, sizeof(buf), tdmi->tdmi_mux); htsmsg_add_str(m, "mux", buf); diff --git a/src/dvb/dvb_support.c b/src/dvb/dvb_support.c index 4b8679ee..91a9bb2a 100644 --- a/src/dvb/dvb_support.c +++ b/src/dvb/dvb_support.c @@ -470,7 +470,7 @@ dvb_mux_nicefreq(char *buf, size_t size, const dvb_mux_t *dm) { char freq[50]; - if(dm->dm_network->dn_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 kHz", freq); } else { @@ -488,8 +488,8 @@ void dvb_mux_nicename(char *buf, size_t size, th_dvb_mux_instance_t *tdmi) { char freq[50]; - const char *n = tdmi->tdmi_network; const dvb_mux_t *dm = tdmi->tdmi_mux; + const char *n = dm->dm_network_name; if(tdmi->tdmi_adapter->tda_fe_type == FE_QPSK) { nicenum(freq, sizeof(freq), dm->dm_conf.dmc_fe_params.frequency); diff --git a/src/dvb/dvb_tables.c b/src/dvb/dvb_tables.c index 723664a8..94f6fb2b 100644 --- a/src/dvb/dvb_tables.c +++ b/src/dvb/dvb_tables.c @@ -268,8 +268,8 @@ dvb_bat_callback(th_dvb_mux_instance_t *tdmi, uint8_t *buf, int len, /* Find TDMI */ LIST_FOREACH(tdmi, &tda->tda_dn->dn_mux_instances, tdmi_adapter_link) - if(tdmi->tdmi_transport_stream_id == tsid && - tdmi->tdmi_network_id == onid) + if(tdmi->tdmi_mux->dm_transport_stream_id == tsid && + tdmi->tdmi_mux->dm_network_id == onid) break; /* Descriptors */ @@ -288,9 +288,9 @@ dvb_bat_callback(th_dvb_mux_instance_t *tdmi, uint8_t *buf, int len, } j += dlen; } - if (*crid && strcmp(tdmi->tdmi_default_authority ?: "", crid)) { - free(tdmi->tdmi_default_authority); - tdmi->tdmi_default_authority = strdup(crid); + if (*crid && strcmp(tdmi->tdmi_mux->dm_default_authority ?: "", crid)) { + free(tdmi->tdmi_mux->dm_default_authority); + tdmi->tdmi_mux->dm_default_authority = strdup(crid); save = 1; } if (save) @@ -332,14 +332,14 @@ dvb_sdt_callback(th_dvb_mux_instance_t *tdmi, uint8_t *ptr, int len, tsid = ptr[0] << 8 | ptr[1]; onid = ptr[5] << 8 | ptr[6]; if (tableid == 0x42) { - if(tdmi->tdmi_transport_stream_id != tsid) + if(tdmi->tdmi_mux->dm_transport_stream_id != tsid) return -1; - if(!tdmi->tdmi_network_id) + if(!tdmi->tdmi_mux->dm_network_id) dvb_mux_set_onid(tdmi, onid); } else { LIST_FOREACH(tdmi, &tda->tda_dn->dn_mux_instances, tdmi_adapter_link) - if(tdmi->tdmi_transport_stream_id == tsid && - tdmi->tdmi_network_id != onid) + if(tdmi->tdmi_mux->dm_transport_stream_id == tsid && + tdmi->tdmi_mux->dm_network_id != onid) break; if (!tdmi) return 0; } @@ -497,13 +497,13 @@ dvb_pat_callback(th_dvb_mux_instance_t *tdmi, uint8_t *ptr, int len, // from another mux LIST_FOREACH(other, &tda->tda_dn->dn_mux_instances, tdmi_adapter_link) if(other != tdmi && - other->tdmi_transport_stream_id == tsid && - other->tdmi_network_id == tdmi->tdmi_network_id) + other->tdmi_mux->dm_transport_stream_id == tsid && + other->tdmi_mux->dm_network_id == tdmi->tdmi_mux->dm_network_id) return -1; - if(tdmi->tdmi_transport_stream_id == 0xffff) + if(tdmi->tdmi_mux->dm_transport_stream_id == 0xffff) dvb_mux_set_tsid(tdmi, tsid); - else if (tdmi->tdmi_transport_stream_id != tsid) + else if (tdmi->tdmi_mux->dm_transport_stream_id != tsid) return -1; // TSID mismatches, skip packet, may be from another mux ptr += 5; @@ -752,7 +752,8 @@ dvb_table_local_channel(th_dvb_mux_instance_t *tdmi, uint8_t *ptr, int len, service_t *t; LIST_FOREACH(tdmi, &tda->tda_dn->dn_mux_instances, tdmi_adapter_link) - if(tdmi->tdmi_transport_stream_id == tsid && tdmi->tdmi_network_id == onid) + if(tdmi->tdmi_mux->dm_transport_stream_id == tsid && + tdmi->tdmi_mux->dm_network_id == onid) break; if(tdmi == NULL) @@ -830,7 +831,7 @@ dvb_nit_callback(th_dvb_mux_instance_t *tdmi, uint8_t *ptr, int len, if(dvb_get_string(networkname, sizeof(networkname), ptr, tlen, NULL, NULL)) return -1; - if(strcmp(tdmi->tdmi_network ?: "", networkname)) + if(strcmp(tdmi->tdmi_mux->dm_network_name ?: "", networkname)) dvb_mux_set_networkname(tdmi, networkname); break; } @@ -932,7 +933,8 @@ atsc_vct_callback(th_dvb_mux_instance_t *tdmi, uint8_t *ptr, int len, /* Search all muxes on adapter */ LIST_FOREACH(tdmi, &tda->tda_dn->dn_mux_instances, tdmi_adapter_link) - if(tdmi->tdmi_transport_stream_id == tsid && tdmi->tdmi_network_id == onid); + if(tdmi->tdmi_mux->dm_transport_stream_id == tsid && + tdmi->tdmi_mux->dm_network_id == onid); break; if(tdmi == NULL) diff --git a/src/epggrab/module/eit.c b/src/epggrab/module/eit.c index cb5bffd3..9d1b2cab 100644 --- a/src/epggrab/module/eit.c +++ b/src/epggrab/module/eit.c @@ -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_default_authority; + defauth = svc->s_dvb_mux_instance->tdmi_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_network_id, - svc->s_dvb_mux_instance->tdmi_transport_stream_id, + = dvb_charset_find(svc->s_dvb_mux_instance->tdmi_mux->dm_network_id, + svc->s_dvb_mux_instance->tdmi_mux->dm_transport_stream_id, svc->s_dvb_service_id); } @@ -716,8 +716,8 @@ static int _eit_callback tda = tdmi->tdmi_adapter; tdmi = dvb_mux_find(tda, NULL, onid, tsid, 1); } else { - if (tdmi->tdmi_transport_stream_id != tsid || - tdmi->tdmi_network_id != onid) { + if (tdmi->tdmi_mux->dm_transport_stream_id != tsid || + tdmi->tdmi_mux->dm_network_id != onid) { #ifdef EPG_EIT_TRACE tvhlog(LOG_DEBUG, mod->id, "invalid transport id found tid 0x%02X, onid:tsid %d:%d != %d:%d", diff --git a/src/epggrab/module/opentv.c b/src/epggrab/module/opentv.c index e1fd6ee3..20ed1d7a 100644 --- a/src/epggrab/module/opentv.c +++ b/src/epggrab/module/opentv.c @@ -651,7 +651,7 @@ static void _opentv_start /* Ignore */ if (!m->enabled) return; - if (mod->tsid != tdmi->tdmi_transport_stream_id) return; + if (mod->tsid != tdmi->tdmi_mux->dm_transport_stream_id) return; /* Create link */ if (!(ota = epggrab_ota_create(m, tdmi))) return; diff --git a/src/epggrab/otamux.c b/src/epggrab/otamux.c index 517d4a68..6d3a23cd 100644 --- a/src/epggrab/otamux.c +++ b/src/epggrab/otamux.c @@ -147,12 +147,15 @@ static void _epggrab_ota_save_one ( htsmsg_t *m, epggrab_module_ota_t *mod ) TAILQ_FOREACH(ota, &mod->muxes, grab_link) { if (!l) l = htsmsg_create_list(); e = htsmsg_create_map(); - htsmsg_add_u32(e, "onid", ota->tdmi->tdmi_network_id); - htsmsg_add_u32(e, "tsid", ota->tdmi->tdmi_transport_stream_id); + + const dvb_mux_t *dm = ota->tdmi->tdmi_mux; + + htsmsg_add_u32(e, "onid", dm->dm_network_id); + htsmsg_add_u32(e, "tsid", dm->dm_transport_stream_id); htsmsg_add_u32(e, "period", ota->timeout); htsmsg_add_u32(e, "interval", ota->interval); - if (ota->tdmi->tdmi_network) - htsmsg_add_str(e, "networkname", ota->tdmi->tdmi_network); + if (dm->dm_network_name) + htsmsg_add_str(e, "networkname", dm->dm_network_name); htsmsg_add_msg(l, NULL, e); } if (l) htsmsg_add_msg(m, mod->id, l); @@ -256,9 +259,11 @@ void epggrab_ota_create_and_register_by_id 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) { - if (tdmi->tdmi_transport_stream_id != tsid) continue; - if (onid && tdmi->tdmi_network_id != onid) continue; - if (networkname && (!tdmi->tdmi_network || strcmp(networkname, tdmi->tdmi_network))) continue; + const dvb_mux_t *dm = tdmi->tdmi_mux; + if (dm->dm_transport_stream_id != tsid) continue; + if (onid && dm->dm_network_id != onid) continue; + if (networkname && (!dm->dm_network_name || + strcmp(networkname, dm->dm_network_name))) continue; ota = epggrab_ota_create(mod, tdmi); epggrab_ota_register(ota, period, interval); } From 8681d718577a6ce1fb816a70c478a37e4b71ea67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20=C3=96man?= Date: Wed, 5 Dec 2012 12:03:58 +0100 Subject: [PATCH 15/31] Move some table stuff over to dvb_mux_t --- src/dvb/dvb.h | 35 +++---- src/dvb/dvb_adapter.c | 2 +- src/dvb/dvb_fe.c | 6 +- src/dvb/dvb_multiplex.c | 33 +++--- src/dvb/dvb_service.c | 2 +- src/dvb/dvb_tables.c | 198 ++++++++++++++++++------------------ src/epggrab.h | 20 ++-- src/epggrab/module.c | 2 +- src/epggrab/module/eit.c | 37 +++---- src/epggrab/module/opentv.c | 28 ++--- src/epggrab/otamux.c | 55 +++++----- src/epggrab/private.h | 8 +- 12 files changed, 220 insertions(+), 206 deletions(-) diff --git a/src/dvb/dvb.h b/src/dvb/dvb.h index cf5de01a..806360e4 100644 --- a/src/dvb/dvb.h +++ b/src/dvb/dvb.h @@ -93,11 +93,11 @@ typedef struct dvb_network { struct th_dvb_mux_instance_queue dn_initial_scan_queue; int dn_initial_num_mux; - struct th_dvb_mux_instance *dn_mux_epg; + struct dvb_mux *dn_mux_epg; int dn_fe_type; // Frontend types for this network (FE_QPSK, etc) - // struct dvb_mux_list dn_muxes; + struct dvb_mux_list dn_muxes; } dvb_network_t; @@ -108,7 +108,7 @@ typedef struct dvb_network { */ typedef struct dvb_mux { - // LIST_ENTRY(dvb_mux) dm_network_link; + LIST_ENTRY(dvb_mux) dm_network_link; dvb_network_t *dm_dn; struct service_list dm_services; @@ -120,6 +120,10 @@ typedef struct dvb_mux { char *dm_network_name; /* Name of network, from NIT table */ char *dm_default_authority; + TAILQ_HEAD(, epggrab_ota_mux) dm_epg_grab; + + struct th_dvb_mux_instance *dm_tdmi; // wrong + } dvb_mux_t; @@ -172,8 +176,6 @@ typedef struct th_dvb_mux_instance { TAILQ_ENTRY(th_dvb_mux_instance) tdmi_scan_link; struct th_dvb_mux_instance_queue *tdmi_scan_queue; - TAILQ_HEAD(, epggrab_ota_mux) tdmi_epg_grab; - struct th_subscription_list tdmi_subscriptions; } th_dvb_mux_instance_t; @@ -314,7 +316,7 @@ typedef struct th_dvb_table { char *tdt_name; void *tdt_opaque; - int (*tdt_callback)(th_dvb_mux_instance_t *tdmi, uint8_t *buf, int len, + int (*tdt_callback)(dvb_mux_t *dm, uint8_t *buf, int len, uint8_t tableid, void *opaque); @@ -426,11 +428,11 @@ th_dvb_mux_instance_t *dvb_mux_create(th_dvb_adapter_t *tda, const char *logprefix, int enabled, int initialscan, const char *identifier); -void dvb_mux_set_networkname(th_dvb_mux_instance_t *tdmi, const char *name); +void dvb_mux_set_networkname(dvb_mux_t *dm, const char *name); -void dvb_mux_set_tsid(th_dvb_mux_instance_t *tdmi, uint16_t tsid); +void dvb_mux_set_tsid(dvb_mux_t *dm, uint16_t tsid); -void dvb_mux_set_onid(th_dvb_mux_instance_t *tdmi, uint16_t onid); +void dvb_mux_set_onid(dvb_mux_t *mux, uint16_t onid); void dvb_mux_set_enable(th_dvb_mux_instance_t *tdmi, int enabled); @@ -501,22 +503,21 @@ void dvb_fe_stop(th_dvb_mux_instance_t *tdmi, int retune); */ void dvb_table_init(th_dvb_adapter_t *tda); -void dvb_table_add_default(th_dvb_mux_instance_t *tdmi); +void dvb_table_add_default(dvb_mux_t *dm); void dvb_table_flush_all(th_dvb_mux_instance_t *tdmi); -void dvb_table_add_pmt(th_dvb_mux_instance_t *tdmi, int pmt_pid); +void dvb_table_add_pmt(dvb_mux_t *dm, int pmt_pid); -void dvb_table_rem_pmt(th_dvb_mux_instance_t *tdmi, int pmt_pid); +void dvb_table_rem_pmt(dvb_mux_t *dm, int pmt_pid); -void tdt_add(th_dvb_mux_instance_t *tdmi, int table, int mask, - int (*callback)(th_dvb_mux_instance_t *tdmi, uint8_t *buf, int len, +void tdt_add(dvb_mux_t *dm, int table, int mask, + int (*callback)(dvb_mux_t *dm, uint8_t *buf, int len, uint8_t tableid, void *opaque), void *opaque, const char *name, int flags, int pid); -int dvb_pidx11_callback - (th_dvb_mux_instance_t *tdmi, uint8_t *ptr, int len, - uint8_t tableid, void *opaque); +int dvb_pidx11_callback(dvb_mux_t *dm, uint8_t *ptr, int len, + uint8_t tableid, void *opaque); #define TDT_CRC 0x1 #define TDT_QUICKREQ 0x2 diff --git a/src/dvb/dvb_adapter.c b/src/dvb/dvb_adapter.c index 5af203f5..d1d12bb7 100644 --- a/src/dvb/dvb_adapter.c +++ b/src/dvb/dvb_adapter.c @@ -748,7 +748,7 @@ dvb_adapter_mux_scanner(void *aux) if (period > 20) gtimer_arm(&tda->tda_mux_scanner_timer, dvb_adapter_mux_scanner, tda, period); - dvb_fe_tune(tda->tda_dn->dn_mux_epg, "EPG scan"); + dvb_fe_tune(tda->tda_dn->dn_mux_epg->dm_tdmi, "EPG scan"); return; } diff --git a/src/dvb/dvb_fe.c b/src/dvb/dvb_fe.c index 8d0f6689..97c1c042 100644 --- a/src/dvb/dvb_fe.c +++ b/src/dvb/dvb_fe.c @@ -277,7 +277,7 @@ dvb_fe_stop(th_dvb_mux_instance_t *tdmi, int retune) assert(tdmi->tdmi_scan_queue == NULL); - epggrab_mux_stop(tdmi, 0); + epggrab_mux_stop(tdmi->tdmi_mux, 0); if (!retune) { gtimer_disarm(&tda->tda_fe_monitor_timer); @@ -512,8 +512,8 @@ dvb_fe_tune(th_dvb_mux_instance_t *tdmi, const char *reason) gtimer_arm(&tda->tda_fe_monitor_timer, dvb_fe_monitor, tda, 1); - dvb_table_add_default(tdmi); - epggrab_mux_start(tdmi); + dvb_table_add_default(tdmi->tdmi_mux); + epggrab_mux_start(tdmi->tdmi_mux); dvb_adapter_notify(tda); return 0; diff --git a/src/dvb/dvb_multiplex.c b/src/dvb/dvb_multiplex.c index 2a69cc6a..a85bf6fc 100644 --- a/src/dvb/dvb_multiplex.c +++ b/src/dvb/dvb_multiplex.c @@ -228,11 +228,14 @@ dvb_mux_create(th_dvb_adapter_t *tda, const struct dvb_mux_conf *dmc, dm->dm_network_id = onid; dm->dm_transport_stream_id = tsid; dm->dm_network_name = network ? strdup(network) : NULL; - dm->dm_dn = tda->tda_dn; + TAILQ_INIT(&dm->dm_epg_grab); + dm->dm_dn = tda->tda_dn; + LIST_INSERT_HEAD(&tda->tda_dn->dn_muxes, dm, dm_network_link); tdmi = calloc(1, sizeof(th_dvb_mux_instance_t)); tdmi->tdmi_mux = dm; + dm->dm_tdmi = tdmi; if(identifier == NULL) { char qpsktxt[20]; @@ -263,7 +266,6 @@ dvb_mux_create(th_dvb_adapter_t *tda, const struct dvb_mux_conf *dmc, return NULL; } - TAILQ_INIT(&tdmi->tdmi_epg_grab); tdmi->tdmi_enabled = enabled; @@ -332,7 +334,7 @@ dvb_mux_destroy(th_dvb_mux_instance_t *tdmi) if(tdmi->tdmi_table_initial) tda->tda_dn->dn_initial_num_mux--; - epggrab_mux_delete(tdmi); + epggrab_mux_delete(tdmi->tdmi_mux); // XXX(dvbreorg) hts_settings_remove("dvbmuxes/%s", tdmi->tdmi_identifier); @@ -810,12 +812,15 @@ dvb_mux_load(th_dvb_adapter_t *tda) * */ void -dvb_mux_set_networkname(th_dvb_mux_instance_t *tdmi, const char *networkname) +dvb_mux_set_networkname(dvb_mux_t *dm, const char *networkname) { htsmsg_t *m; - free(tdmi->tdmi_mux->dm_network_name); - tdmi->tdmi_mux->dm_network_name = strdup(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); m = htsmsg_create_map(); @@ -829,12 +834,14 @@ dvb_mux_set_networkname(th_dvb_mux_instance_t *tdmi, const char *networkname) * */ void -dvb_mux_set_tsid(th_dvb_mux_instance_t *tdmi, uint16_t tsid) +dvb_mux_set_tsid(dvb_mux_t *dm, uint16_t tsid) { htsmsg_t *m; - tdmi->tdmi_mux->dm_transport_stream_id = tsid; - + dm->dm_transport_stream_id = tsid; + + th_dvb_mux_instance_t *tdmi = dm->dm_tdmi; + dvb_mux_save(tdmi); m = htsmsg_create_map(); @@ -847,12 +854,14 @@ dvb_mux_set_tsid(th_dvb_mux_instance_t *tdmi, uint16_t tsid) * */ void -dvb_mux_set_onid(th_dvb_mux_instance_t *tdmi, uint16_t onid) +dvb_mux_set_onid(dvb_mux_t *dm, uint16_t onid) { htsmsg_t *m; - tdmi->tdmi_mux->dm_network_id = onid; - + dm->dm_network_id = onid; + + th_dvb_mux_instance_t *tdmi = dm->dm_tdmi; + dvb_mux_save(tdmi); m = htsmsg_create_map(); diff --git a/src/dvb/dvb_service.c b/src/dvb/dvb_service.c index 088d2d22..b5d55794 100644 --- a/src/dvb/dvb_service.c +++ b/src/dvb/dvb_service.c @@ -97,7 +97,7 @@ dvb_service_start(service_t *t, unsigned int weight, int force_start) if(!r) tda->tda_open_service(tda, t); - dvb_table_add_pmt(t->s_dvb_mux_instance, t->s_pmt_pid); + dvb_table_add_pmt(t->s_dvb_mux_instance->tdmi_mux, t->s_pmt_pid); return r; } diff --git a/src/dvb/dvb_tables.c b/src/dvb/dvb_tables.c index 94f6fb2b..3708d025 100644 --- a/src/dvb/dvb_tables.c +++ b/src/dvb/dvb_tables.c @@ -86,6 +86,7 @@ dvb_table_dispatch(uint8_t *sec, int r, th_dvb_table_t *tdt) uint8_t *ptr; int ret; th_dvb_mux_instance_t *tdmi = tdt->tdt_tdmi; + dvb_mux_t *dm = tdmi->tdmi_mux; /* It seems some hardware (or is it the dvb API?) does not honour the DMX_CHECK_CRC flag, so we check it again */ @@ -106,12 +107,12 @@ dvb_table_dispatch(uint8_t *sec, int r, th_dvb_table_t *tdt) if(chkcrc) len -= 4; /* Strip trailing CRC */ if(tdt->tdt_flags & TDT_CA) - ret = tdt->tdt_callback((th_dvb_mux_instance_t *)tdt, - sec, len + 3, tableid, tdt->tdt_opaque); + ret = tdt->tdt_callback((dvb_mux_t *)tdt, + sec, len + 3, tableid, tdt->tdt_opaque); else if(tdt->tdt_flags & TDT_TDT) - ret = tdt->tdt_callback(tdt->tdt_tdmi, ptr, len, tableid, tdt); + ret = tdt->tdt_callback(dm, ptr, len, tableid, tdt); else - ret = tdt->tdt_callback(tdt->tdt_tdmi, ptr, len, tableid, tdt->tdt_opaque); + ret = tdt->tdt_callback(dm, ptr, len, tableid, tdt->tdt_opaque); if(ret == 0) tdt->tdt_count++; @@ -154,12 +155,13 @@ dvb_tdt_destroy(th_dvb_adapter_t *tda, th_dvb_mux_instance_t *tdmi, * Add a new DVB table */ void -tdt_add(th_dvb_mux_instance_t *tdmi, int tableid, int mask, - int (*callback)(th_dvb_mux_instance_t *tdmi, uint8_t *buf, int len, +tdt_add(dvb_mux_t *dm, int tableid, int mask, + int (*callback)(dvb_mux_t *dm, uint8_t *buf, int len, uint8_t tableid, void *opaque), void *opaque, const char *name, int flags, int pid) { th_dvb_table_t *t; + th_dvb_mux_instance_t *tdmi = dm->dm_tdmi; // Allow multiple entries per PID, but only one per callback/opaque instance // TODO: this could mean reading the same data multiple times, and not @@ -230,14 +232,14 @@ dvb_desc_def_authority(uint8_t *ptr, int len, char *defauth, size_t dalen) } static int -dvb_bat_callback(th_dvb_mux_instance_t *tdmi, uint8_t *buf, int len, +dvb_bat_callback(dvb_mux_t *dm, uint8_t *buf, int len, uint8_t tableid, void *opaque) { int i, j, bdlen, tslen, tdlen; uint8_t dtag, dlen; uint16_t tsid, onid; char crid[257]; - th_dvb_adapter_t *tda = tdmi->tdmi_adapter; + dvb_network_t *dn = dm->dm_dn; if (tableid != 0x4a) return -1; bdlen = ((buf[5] & 0xf) << 8) | buf[6]; @@ -266,14 +268,13 @@ dvb_bat_callback(th_dvb_mux_instance_t *tdmi, uint8_t *buf, int len, i += 6; j = 0; - /* Find TDMI */ - LIST_FOREACH(tdmi, &tda->tda_dn->dn_mux_instances, tdmi_adapter_link) - if(tdmi->tdmi_mux->dm_transport_stream_id == tsid && - tdmi->tdmi_mux->dm_network_id == onid) + /* Find mux */ + LIST_FOREACH(dm, &dn->dn_muxes, dm_network_link) + if(dm->dm_transport_stream_id == tsid && dm->dm_network_id == onid) break; /* Descriptors */ - if (tdmi) { + if (dm != NULL) { int save = 0; *crid = 0; while (j+2 < tdlen) { @@ -288,13 +289,13 @@ dvb_bat_callback(th_dvb_mux_instance_t *tdmi, uint8_t *buf, int len, } j += dlen; } - if (*crid && strcmp(tdmi->tdmi_mux->dm_default_authority ?: "", crid)) { - free(tdmi->tdmi_mux->dm_default_authority); - tdmi->tdmi_mux->dm_default_authority = strdup(crid); + if (*crid && strcmp(dm->dm_default_authority ?: "", crid)) { + free(dm->dm_default_authority); + dm->dm_default_authority = strdup(crid); save = 1; } if (save) - dvb_mux_save(tdmi); + dvb_mux_save(dm->dm_tdmi); } i += tdlen; @@ -307,7 +308,7 @@ dvb_bat_callback(th_dvb_mux_instance_t *tdmi, uint8_t *buf, int len, * DVB SDT (Service Description Table) */ static int -dvb_sdt_callback(th_dvb_mux_instance_t *tdmi, uint8_t *ptr, int len, +dvb_sdt_callback(dvb_mux_t *dm, uint8_t *ptr, int len, uint8_t tableid, void *opaque) { service_t *t; @@ -323,7 +324,7 @@ dvb_sdt_callback(th_dvb_mux_instance_t *tdmi, uint8_t *ptr, int len, uint8_t stype; int l; - th_dvb_adapter_t *tda = tdmi->tdmi_adapter; + dvb_network_t *dn = dm->dm_dn; if (tableid != 0x42 && tableid != 0x46) return -1; @@ -332,16 +333,16 @@ dvb_sdt_callback(th_dvb_mux_instance_t *tdmi, uint8_t *ptr, int len, tsid = ptr[0] << 8 | ptr[1]; onid = ptr[5] << 8 | ptr[6]; if (tableid == 0x42) { - if(tdmi->tdmi_mux->dm_transport_stream_id != tsid) + if(dm->dm_transport_stream_id != tsid) return -1; - if(!tdmi->tdmi_mux->dm_network_id) - dvb_mux_set_onid(tdmi, onid); + if(!dm->dm_network_id) + dvb_mux_set_onid(dm, onid); } else { - LIST_FOREACH(tdmi, &tda->tda_dn->dn_mux_instances, tdmi_adapter_link) - if(tdmi->tdmi_mux->dm_transport_stream_id == tsid && - tdmi->tdmi_mux->dm_network_id != onid) + LIST_FOREACH(dm, &dn->dn_muxes, dm_network_link) + if(dm->dm_transport_stream_id == tsid && + dm->dm_network_id != onid) break; - if (!tdmi) return 0; + if (!dm) return 0; } // version = ptr[2] >> 1 & 0x1f; @@ -373,7 +374,7 @@ dvb_sdt_callback(th_dvb_mux_instance_t *tdmi, uint8_t *ptr, int len, if(dllen > len) break; - if (!(t = dvb_service_find(tdmi, service_id, 0, NULL))) { + if (!(t = dvb_service_find(dm->dm_tdmi, service_id, 0, NULL))) { len -= dllen; ptr += dllen; continue; @@ -460,14 +461,14 @@ dvb_sdt_callback(th_dvb_mux_instance_t *tdmi, uint8_t *ptr, int len, /* * Combined PID 0x11 callback, for stuff commonly found on that PID */ -int dvb_pidx11_callback - (th_dvb_mux_instance_t *tdmi, uint8_t *ptr, int len, - uint8_t tableid, void *opaque) +int +dvb_pidx11_callback(dvb_mux_t *dm, uint8_t *ptr, int len, + uint8_t tableid, void *opaque) { if (tableid == 0x42 || tableid == 0x46) - return dvb_sdt_callback(tdmi, ptr, len, tableid, opaque); + return dvb_sdt_callback(dm, ptr, len, tableid, opaque); else if (tableid == 0x4a) - return dvb_bat_callback(tdmi, ptr, len, tableid, opaque); + return dvb_bat_callback(dm, ptr, len, tableid, opaque); return -1; } @@ -475,11 +476,11 @@ int dvb_pidx11_callback * PAT - Program Allocation table */ static int -dvb_pat_callback(th_dvb_mux_instance_t *tdmi, uint8_t *ptr, int len, +dvb_pat_callback(dvb_mux_t *dm, uint8_t *ptr, int len, uint8_t tableid, void *opaque) { - th_dvb_mux_instance_t *other; - th_dvb_adapter_t *tda = tdmi->tdmi_adapter; + dvb_mux_t *other; + dvb_network_t *dn = dm->dm_dn; uint16_t service, pmt, tsid; if(len < 5) @@ -495,15 +496,15 @@ dvb_pat_callback(th_dvb_mux_instance_t *tdmi, uint8_t *ptr, int len, // Make sure this TSID is not already known on another mux // That might indicate that we have accedentally received a PAT // from another mux - LIST_FOREACH(other, &tda->tda_dn->dn_mux_instances, tdmi_adapter_link) - if(other != tdmi && - other->tdmi_mux->dm_transport_stream_id == tsid && - other->tdmi_mux->dm_network_id == tdmi->tdmi_mux->dm_network_id) + LIST_FOREACH(other, &dn->dn_muxes, dm_network_link) + if(other != dm && + other->dm_transport_stream_id == tsid && + other->dm_network_id == dm->dm_network_id) return -1; - if(tdmi->tdmi_mux->dm_transport_stream_id == 0xffff) - dvb_mux_set_tsid(tdmi, tsid); - else if (tdmi->tdmi_mux->dm_transport_stream_id != tsid) + if(dm->dm_transport_stream_id == 0xffff) + dvb_mux_set_tsid(dm, tsid); + else if (dm->dm_transport_stream_id != tsid) return -1; // TSID mismatches, skip packet, may be from another mux ptr += 5; @@ -515,9 +516,9 @@ dvb_pat_callback(th_dvb_mux_instance_t *tdmi, uint8_t *ptr, int len, if(service != 0 && pmt != 0) { int save = 0; - dvb_service_find2(tdmi, service, pmt, NULL, &save); - if (save || !tda->tda_disable_pmt_monitor) - dvb_table_add_pmt(tdmi, pmt); + dvb_service_find2(dm->dm_tdmi, service, pmt, NULL, &save); + if (save || ! dm->dm_tdmi->tdmi_adapter->tda_disable_pmt_monitor) + dvb_table_add_pmt(dm, pmt); } ptr += 4; len -= 4; @@ -530,10 +531,10 @@ dvb_pat_callback(th_dvb_mux_instance_t *tdmi, uint8_t *ptr, int len, * CA - Conditional Access */ static int -dvb_ca_callback(th_dvb_mux_instance_t *tdmi, uint8_t *ptr, int len, +dvb_ca_callback(dvb_mux_t *dm, uint8_t *ptr, int len, uint8_t tableid, void *opaque) { - cwc_emm(ptr, len, (uintptr_t)opaque, (void *)tdmi); + cwc_emm(ptr, len, (uintptr_t)opaque, (void *)dm); return 0; } @@ -541,8 +542,8 @@ dvb_ca_callback(th_dvb_mux_instance_t *tdmi, uint8_t *ptr, int len, * CAT - Conditional Access Table */ static int -dvb_cat_callback(th_dvb_mux_instance_t *tdmi, uint8_t *ptr, int len, - uint8_t tableid, void *opaque) +dvb_cat_callback(dvb_mux_t *dm, uint8_t *ptr, int len, + uint8_t tableid, void *opaque) { int tag, tlen; uint16_t pid; @@ -568,7 +569,7 @@ dvb_cat_callback(th_dvb_mux_instance_t *tdmi, uint8_t *ptr, int len, if(pid == 0) break; - tdt_add(tdmi, 0, 0, dvb_ca_callback, (void *)caid, "CA", + tdt_add(dm, 0, 0, dvb_ca_callback, (void *)caid, "CA", TDT_CA, pid); break; @@ -613,13 +614,13 @@ static const fe_modulation_t qam_tab [6] = { * Cable delivery descriptor */ static int -dvb_table_cable_delivery(th_dvb_mux_instance_t *tdmi, uint8_t *ptr, int len, +dvb_table_cable_delivery(dvb_mux_t *dm, uint8_t *ptr, int len, uint16_t tsid, uint16_t onid) { struct dvb_mux_conf dmc; int freq, symrate; - if(!tdmi->tdmi_adapter->tda_autodiscovery) + if(!dm->dm_tdmi->tdmi_adapter->tda_autodiscovery) return -1; if(len < 11) @@ -651,7 +652,7 @@ dvb_table_cable_delivery(th_dvb_mux_instance_t *tdmi, uint8_t *ptr, int len, dmc.dmc_fe_params.u.qam.fec_inner = fec_tab[ptr[10] & 0x07]; - dvb_mux_create(tdmi->tdmi_adapter, &dmc, onid, tsid, NULL, + dvb_mux_create(dm->dm_tdmi->tdmi_adapter, &dmc, onid, tsid, NULL, "automatic mux discovery", 1, 1, NULL); return 0; } @@ -660,14 +661,14 @@ dvb_table_cable_delivery(th_dvb_mux_instance_t *tdmi, uint8_t *ptr, int len, * Satellite delivery descriptor */ static int -dvb_table_sat_delivery(th_dvb_mux_instance_t *tdmi, uint8_t *ptr, int len, +dvb_table_sat_delivery(dvb_mux_t *dm, uint8_t *ptr, int len, uint16_t tsid, uint16_t onid) { int freq, symrate; // uint16_t orbital_pos; struct dvb_mux_conf dmc; - if(!tdmi->tdmi_adapter->tda_autodiscovery) + if(!dm->dm_tdmi->tdmi_adapter->tda_autodiscovery) return -1; if(len < 11) @@ -734,7 +735,7 @@ dvb_table_sat_delivery(th_dvb_mux_instance_t *tdmi, uint8_t *ptr, int len, } #endif - dvb_mux_create(tdmi->tdmi_adapter, &dmc, onid, tsid, NULL, + dvb_mux_create(dm->dm_tdmi->tdmi_adapter, &dmc, onid, tsid, NULL, "automatic mux discovery", 1, 1, NULL); return 0; } @@ -744,19 +745,18 @@ dvb_table_sat_delivery(th_dvb_mux_instance_t *tdmi, uint8_t *ptr, int len, * */ static void -dvb_table_local_channel(th_dvb_mux_instance_t *tdmi, uint8_t *ptr, int len, +dvb_table_local_channel(dvb_mux_t *dm, uint8_t *ptr, int len, uint16_t tsid, uint16_t onid) { uint16_t sid, chan; - th_dvb_adapter_t *tda = tdmi->tdmi_adapter; + dvb_network_t *dn = dm->dm_dn; service_t *t; - LIST_FOREACH(tdmi, &tda->tda_dn->dn_mux_instances, tdmi_adapter_link) - if(tdmi->tdmi_mux->dm_transport_stream_id == tsid && - tdmi->tdmi_mux->dm_network_id == onid) + LIST_FOREACH(dm, &dn->dn_muxes, dm_network_link) + if(dm->dm_transport_stream_id == tsid && dm->dm_network_id == onid) break; - if(tdmi == NULL) + if(dm == NULL) return; while(len >= 4) { @@ -764,7 +764,7 @@ dvb_table_local_channel(th_dvb_mux_instance_t *tdmi, uint8_t *ptr, int len, chan = ((ptr[2] & 3) << 8) | ptr[3]; if(chan != 0) { - t = dvb_service_find(tdmi, sid, 0, NULL); + t = dvb_service_find(dm->dm_tdmi, sid, 0, NULL); if(t != NULL) { if(t->s_channel_number != chan) { @@ -785,7 +785,7 @@ dvb_table_local_channel(th_dvb_mux_instance_t *tdmi, uint8_t *ptr, int len, * NIT - Network Information Table */ static int -dvb_nit_callback(th_dvb_mux_instance_t *tdmi, uint8_t *ptr, int len, +dvb_nit_callback(dvb_mux_t *dm, uint8_t *ptr, int len, uint8_t tableid, void *opaque) { uint8_t tag, tlen; @@ -794,11 +794,11 @@ dvb_nit_callback(th_dvb_mux_instance_t *tdmi, uint8_t *ptr, int len, uint16_t tsid, onid; uint16_t network_id = (ptr[0] << 8) | ptr[1]; - if(tdmi->tdmi_adapter->tda_nitoid) { + if(dm->dm_tdmi->tdmi_adapter->tda_nitoid) { if(tableid != 0x41) return -1; - if(network_id != tdmi->tdmi_adapter->tda_nitoid) + if(network_id != dm->dm_tdmi->tdmi_adapter->tda_nitoid) return -1; } else { @@ -831,8 +831,8 @@ dvb_nit_callback(th_dvb_mux_instance_t *tdmi, uint8_t *ptr, int len, if(dvb_get_string(networkname, sizeof(networkname), ptr, tlen, NULL, NULL)) return -1; - if(strcmp(tdmi->tdmi_mux->dm_network_name ?: "", networkname)) - dvb_mux_set_networkname(tdmi, networkname); + if(strcmp(dm->dm_network_name ?: "", networkname)) + dvb_mux_set_networkname(dm, networkname); break; } @@ -869,15 +869,15 @@ dvb_nit_callback(th_dvb_mux_instance_t *tdmi, uint8_t *ptr, int len, switch(tag) { case DVB_DESC_SAT: - if(tdmi->tdmi_adapter->tda_fe_type == FE_QPSK) - dvb_table_sat_delivery(tdmi, ptr, tlen, tsid, onid); + if(dm->dm_dn->dn_fe_type == FE_QPSK) + dvb_table_sat_delivery(dm, ptr, tlen, tsid, onid); break; case DVB_DESC_CABLE: - if(tdmi->tdmi_adapter->tda_fe_type == FE_QAM) - dvb_table_cable_delivery(tdmi, ptr, tlen, tsid, onid); + if(dm->dm_dn->dn_fe_type == FE_QAM) + dvb_table_cable_delivery(dm, ptr, tlen, tsid, onid); break; case DVB_DESC_LOCAL_CHAN: - dvb_table_local_channel(tdmi, ptr, tlen, tsid, onid); + dvb_table_local_channel(dm, ptr, tlen, tsid, onid); break; } @@ -894,10 +894,10 @@ dvb_nit_callback(th_dvb_mux_instance_t *tdmi, uint8_t *ptr, int len, * VCT - ATSC Virtual Channel Table */ static int -atsc_vct_callback(th_dvb_mux_instance_t *tdmi, uint8_t *ptr, int len, +atsc_vct_callback(dvb_mux_t *dm, uint8_t *ptr, int len, uint8_t tableid, void *opaque) { - th_dvb_adapter_t *tda = tdmi->tdmi_adapter; + dvb_network_t *dn = dm->dm_dn; service_t *t; int numch; char chname[256]; @@ -932,16 +932,15 @@ atsc_vct_callback(th_dvb_mux_instance_t *tdmi, uint8_t *ptr, int len, onid = (ptr[24] << 8) | ptr[25]; /* Search all muxes on adapter */ - LIST_FOREACH(tdmi, &tda->tda_dn->dn_mux_instances, tdmi_adapter_link) - if(tdmi->tdmi_mux->dm_transport_stream_id == tsid && - tdmi->tdmi_mux->dm_network_id == onid); + LIST_FOREACH(dm, &dn->dn_muxes, dm_network_link) + if(dm->dm_transport_stream_id == tsid && dm->dm_network_id == onid); break; - if(tdmi == NULL) + if(dm == NULL) continue; service_id = (ptr[24] << 8) | ptr[25]; - if((t = dvb_service_find(tdmi, service_id, 0, NULL)) == NULL) + if((t = dvb_service_find(dm->dm_tdmi, service_id, 0, NULL)) == NULL) continue; atsc_stype = ptr[27] & 0x3f; @@ -979,12 +978,13 @@ atsc_vct_callback(th_dvb_mux_instance_t *tdmi, uint8_t *ptr, int len, * PMT - Program Mapping Table */ static int -dvb_pmt_callback(th_dvb_mux_instance_t *tdmi, uint8_t *ptr, int len, +dvb_pmt_callback(dvb_mux_t *dm, uint8_t *ptr, int len, uint8_t tableid, void *opaque) { 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) { pthread_mutex_lock(&t->s_stream_mutex); @@ -1005,23 +1005,23 @@ dvb_pmt_callback(th_dvb_mux_instance_t *tdmi, uint8_t *ptr, int len, * Demux for default DVB tables that we want */ static void -dvb_table_add_default_dvb(th_dvb_mux_instance_t *tdmi) +dvb_table_add_default_dvb(dvb_mux_t *dm) { /* Network Information Table */ int table; - if(tdmi->tdmi_adapter->tda_nitoid) { + if(dm->dm_tdmi->tdmi_adapter->tda_nitoid) { table = 0x41; } else { table = 0x40; } - tdt_add(tdmi, table, 0xff, dvb_nit_callback, NULL, "nit", + tdt_add(dm, table, 0xff, dvb_nit_callback, NULL, "nit", TDT_QUICKREQ | TDT_CRC, 0x10); /* Service Descriptor Table and Bouqeut Allocation Table */ - tdt_add(tdmi, 0, 0, dvb_pidx11_callback, NULL, "pidx11", + tdt_add(dm, 0, 0, dvb_pidx11_callback, NULL, "pidx11", TDT_QUICKREQ | TDT_CRC, 0x11); } @@ -1030,17 +1030,17 @@ dvb_table_add_default_dvb(th_dvb_mux_instance_t *tdmi) * Demux for default ATSC tables that we want */ static void -dvb_table_add_default_atsc(th_dvb_mux_instance_t *tdmi) +dvb_table_add_default_atsc(dvb_mux_t *dm) { int tableid; - if(tdmi->tdmi_mux->dm_conf.dmc_fe_params.u.vsb.modulation == VSB_8) { + if(dm->dm_conf.dmc_fe_params.u.vsb.modulation == VSB_8) { tableid = 0xc8; // Terrestrial } else { tableid = 0xc9; // Cable } - tdt_add(tdmi, tableid, 0xff, atsc_vct_callback, NULL, "vct", + tdt_add(dm, tableid, 0xff, atsc_vct_callback, NULL, "vct", TDT_QUICKREQ | TDT_CRC, 0x1ffb); } @@ -1051,26 +1051,26 @@ dvb_table_add_default_atsc(th_dvb_mux_instance_t *tdmi) * Setup FD + demux for default tables that we want */ void -dvb_table_add_default(th_dvb_mux_instance_t *tdmi) +dvb_table_add_default(dvb_mux_t *dm) { /* Program Allocation Table */ - tdt_add(tdmi, 0x00, 0xff, dvb_pat_callback, NULL, "pat", + tdt_add(dm, 0x00, 0xff, dvb_pat_callback, NULL, "pat", TDT_QUICKREQ | TDT_CRC, 0); /* Conditional Access Table */ - tdt_add(tdmi, 0x1, 0xff, dvb_cat_callback, NULL, "cat", + tdt_add(dm, 0x1, 0xff, dvb_cat_callback, NULL, "cat", TDT_CRC, 1); - switch(tdmi->tdmi_adapter->tda_fe_type) { + switch(dm->dm_dn->dn_fe_type) { case FE_QPSK: case FE_OFDM: case FE_QAM: - dvb_table_add_default_dvb(tdmi); + dvb_table_add_default_dvb(dm); break; case FE_ATSC: - dvb_table_add_default_atsc(tdmi); + dvb_table_add_default_atsc(dm); break; } } @@ -1080,24 +1080,26 @@ dvb_table_add_default(th_dvb_mux_instance_t *tdmi) * Setup FD + demux for a services PMT */ void -dvb_table_add_pmt(th_dvb_mux_instance_t *tdmi, int pmt_pid) +dvb_table_add_pmt(dvb_mux_t *dm, int pmt_pid) { char pmtname[100]; snprintf(pmtname, sizeof(pmtname), "PMT(%d)", pmt_pid); - tdt_add(tdmi, 0x2, 0xff, dvb_pmt_callback, NULL, pmtname, + tdt_add(dm, 0x2, 0xff, dvb_pmt_callback, NULL, pmtname, TDT_CRC | TDT_QUICKREQ | TDT_TDT, pmt_pid); } void -dvb_table_rem_pmt(th_dvb_mux_instance_t *tdmi, int pmt_pid) +dvb_table_rem_pmt(dvb_mux_t *dm, int pmt_pid) { + th_dvb_mux_instance_t *tdmi = dm->dm_tdmi; th_dvb_adapter_t *tda = tdmi->tdmi_adapter; th_dvb_table_t *tdt = NULL; LIST_FOREACH(tdt, &tdmi->tdmi_tables, tdt_link) if (tdt->tdt_pid == pmt_pid && tdt->tdt_callback == dvb_pmt_callback) break; - if (tdt) dvb_tdt_destroy(tda, tdmi, tdt); + if (tdt) + dvb_tdt_destroy(tda, tdmi, tdt); } diff --git a/src/epggrab.h b/src/epggrab.h index ddb46a41..d72f98d6 100644 --- a/src/epggrab.h +++ b/src/epggrab.h @@ -169,10 +169,10 @@ struct epggrab_module_ext */ struct epggrab_ota_mux { - TAILQ_ENTRY(epggrab_ota_mux) glob_link; ///< Grabber link - TAILQ_ENTRY(epggrab_ota_mux) tdmi_link; ///< Link to mux - TAILQ_ENTRY(epggrab_ota_mux) grab_link; ///< Link to grabber - struct th_dvb_mux_instance *tdmi; ///< Mux instance + TAILQ_ENTRY(epggrab_ota_mux) glob_link;///< Grabber link + TAILQ_ENTRY(epggrab_ota_mux) dm_link; ///< Link to dvb mux + TAILQ_ENTRY(epggrab_ota_mux) grab_link;///< Link to grabber + struct dvb_mux *dm; ///< Mux instance epggrab_module_ota_t *grab; ///< Grab instance int timeout; ///< Time out if this long @@ -203,7 +203,7 @@ struct epggrab_module_ota TAILQ_HEAD(, epggrab_ota_mux) muxes; ///< List of related muxes /* Transponder tuning */ - void (*start) ( epggrab_module_ota_t *m, struct th_dvb_mux_instance *tdmi ); + void (*start) ( epggrab_module_ota_t *m, struct dvb_mux *dm ); }; /* @@ -259,11 +259,11 @@ void epggrab_channel_mod ( struct channel *ch ); /* * Transport handling */ -void epggrab_mux_start ( struct th_dvb_mux_instance *tdmi ); -void epggrab_mux_stop ( struct th_dvb_mux_instance *tdmi, int timeout ); -void epggrab_mux_delete ( struct th_dvb_mux_instance *tdmi ); -int epggrab_mux_period ( struct th_dvb_mux_instance *tdmi ); -struct th_dvb_mux_instance *epggrab_mux_next ( struct th_dvb_adapter *tda ); +void epggrab_mux_start ( struct dvb_mux *tdmi ); +void epggrab_mux_stop ( struct dvb_mux *tdmi, int timeout ); +void epggrab_mux_delete ( struct dvb_mux *tdmi ); +int epggrab_mux_period ( struct dvb_mux *tdmi ); +struct dvb_mux *epggrab_mux_next ( struct th_dvb_adapter *tda ); /* * Re-schedule diff --git a/src/epggrab/module.c b/src/epggrab/module.c index b920eea1..788dd8ab 100644 --- a/src/epggrab/module.c +++ b/src/epggrab/module.c @@ -457,7 +457,7 @@ epggrab_module_ota_t *epggrab_module_ota_create ( epggrab_module_ota_t *skel, const char *id, const char *name, int priority, void (*start) (epggrab_module_ota_t*m, - struct th_dvb_mux_instance *tdmi), + struct dvb_mux *dm), int (*enable) (void *m, uint8_t e ), epggrab_channel_tree_t *channels ) { diff --git a/src/epggrab/module/eit.c b/src/epggrab/module/eit.c index 9d1b2cab..a2663af6 100644 --- a/src/epggrab/module/eit.c +++ b/src/epggrab/module/eit.c @@ -654,9 +654,9 @@ static int _eit_process_event return ret; } -static int _eit_callback - ( th_dvb_mux_instance_t *tdmi, uint8_t *ptr, int len, - uint8_t tableid, void *opaque ) +static int +_eit_callback(dvb_mux_t *dm, uint8_t *ptr, int len, + uint8_t tableid, void *opaque) { epggrab_module_t *mod = opaque; epggrab_ota_mux_t *ota; @@ -672,7 +672,7 @@ static int _eit_callback if(tableid < 0x4e || tableid > 0x6f || len < 11) return -1; /* Get OTA */ - ota = epggrab_ota_find((epggrab_module_ota_t*)mod, tdmi); + ota = epggrab_ota_find((epggrab_module_ota_t*)mod, dm); if (!ota || !ota->status) return -1; sta = ota->status; @@ -713,24 +713,26 @@ static int _eit_callback // Note: tableid=0x4f,0x60-0x6f is other TS // so must find the tdmi if(tableid == 0x4f || tableid >= 0x60) { - tda = tdmi->tdmi_adapter; - tdmi = dvb_mux_find(tda, NULL, onid, tsid, 1); + tda = dm->dm_tdmi->tdmi_adapter; + th_dvb_mux_instance_t *tdmi = dvb_mux_find(tda, NULL, onid, tsid, 1); + dm = tdmi->tdmi_mux; + } else { - if (tdmi->tdmi_mux->dm_transport_stream_id != tsid || - tdmi->tdmi_mux->dm_network_id != onid) { + if (dm->dm_transport_stream_id != tsid || + dm->dm_network_id != onid) { #ifdef EPG_EIT_TRACE tvhlog(LOG_DEBUG, mod->id, "invalid transport id found tid 0x%02X, onid:tsid %d:%d != %d:%d", tableid, tdmi->tdmi_network_id, tdmi->tdmi_transport_stream_id, onid, tsid); #endif - tdmi = NULL; + dm = NULL; } } - if(!tdmi) goto done; + if(!dm) goto done; /* Get service */ - svc = dvb_service_find3(NULL, tdmi, NULL, 0, 0, sid, 1, 1); + svc = dvb_service_find3(NULL, dm->dm_tdmi, NULL, 0, 0, sid, 1, 1); if (!svc || !svc->s_ch) goto done; /* Register as interesting */ @@ -815,10 +817,9 @@ static void _eit_ota_destroy ( epggrab_ota_mux_t *ota ) } static void _eit_start - ( epggrab_module_ota_t *m, th_dvb_mux_instance_t *tdmi ) + ( epggrab_module_ota_t *m, dvb_mux_t *dm ) { epggrab_ota_mux_t *ota; - /* Disabled */ if (!m->enabled) return; @@ -830,7 +831,7 @@ static void _eit_start } /* Register */ - if (!(ota = epggrab_ota_create(m, tdmi))) return; + if (!(ota = epggrab_ota_create(m, dm))) return; if (!ota->status) { ota->status = calloc(1, sizeof(eit_status_t)); ota->destroy = _eit_ota_destroy; @@ -842,16 +843,16 @@ static void _eit_start tdt_add(tdmi, 0, 0, dvb_pidx11_callback, m, m->id, TDT_CRC, 3840, NULL); tdt_add(tdmi, 0, 0, _eit_callback, m, m->id, TDT_CRC, 3841, NULL); #endif - tdt_add(tdmi, 0, 0, dvb_pidx11_callback, m, m->id, TDT_CRC, 3002); - tdt_add(tdmi, 0, 0, _eit_callback, m, m->id, TDT_CRC, 3003); + tdt_add(dm, 0, 0, dvb_pidx11_callback, m, m->id, TDT_CRC, 3002); + tdt_add(dm, 0, 0, _eit_callback, m, m->id, TDT_CRC, 3003); /* Viasat Baltic (0x39) */ } else if (!strcmp("viasat_baltic", m->id)) { - tdt_add(tdmi, 0, 0, _eit_callback, m, m->id, TDT_CRC, 0x39); + tdt_add(dm, 0, 0, _eit_callback, m, m->id, TDT_CRC, 0x39); /* Standard (0x12) */ } else { - tdt_add(tdmi, 0, 0, _eit_callback, m, m->id, TDT_CRC, 0x12); + tdt_add(dm, 0, 0, _eit_callback, m, m->id, TDT_CRC, 0x12); } tvhlog(LOG_DEBUG, m->id, "install table handlers"); } diff --git a/src/epggrab/module/opentv.c b/src/epggrab/module/opentv.c index 20ed1d7a..51cc3ef2 100644 --- a/src/epggrab/module/opentv.c +++ b/src/epggrab/module/opentv.c @@ -519,11 +519,11 @@ static int _opentv_bat_section * ***********************************************************************/ static epggrab_ota_mux_t *_opentv_event_callback - ( th_dvb_mux_instance_t *tdmi, uint8_t *buf, int len, uint8_t tid, void *p ) + ( dvb_mux_t *dm, uint8_t *buf, int len, uint8_t tid, void *p ) { th_dvb_table_t *tdt = p; opentv_module_t *mod = tdt->tdt_opaque; - epggrab_ota_mux_t *ota = epggrab_ota_find((epggrab_module_ota_t*)mod, tdmi); + epggrab_ota_mux_t *ota = epggrab_ota_find((epggrab_module_ota_t*)mod, dm); opentv_status_t *sta; opentv_pid_t *pid; @@ -584,9 +584,9 @@ static epggrab_ota_mux_t *_opentv_event_callback } static int _opentv_title_callback - ( th_dvb_mux_instance_t *tdmi, uint8_t *buf, int len, uint8_t tid, void *p ) + ( dvb_mux_t *dm, uint8_t *buf, int len, uint8_t tid, void *p ) { - epggrab_ota_mux_t *ota = _opentv_event_callback(tdmi, buf, len, tid, p); + epggrab_ota_mux_t *ota = _opentv_event_callback(dm, buf, len, tid, p); if (ota) return _opentv_parse_event_section((opentv_module_t*)ota->grab, (opentv_status_t*)ota->status, @@ -595,9 +595,9 @@ static int _opentv_title_callback } static int _opentv_summary_callback - ( th_dvb_mux_instance_t *tdmi, uint8_t *buf, int len, uint8_t tid, void *p ) + ( dvb_mux_t *dm, uint8_t *buf, int len, uint8_t tid, void *p ) { - epggrab_ota_mux_t *ota = _opentv_event_callback(tdmi, buf, len, tid, p); + epggrab_ota_mux_t *ota = _opentv_event_callback(dm, buf, len, tid, p); if (ota) return _opentv_parse_event_section((opentv_module_t*)ota->grab, (opentv_status_t*)ota->status, @@ -606,10 +606,10 @@ static int _opentv_summary_callback } static int _opentv_channel_callback - ( th_dvb_mux_instance_t *tdmi, uint8_t *buf, int len, uint8_t tid, void *p ) + ( dvb_mux_t *dm, uint8_t *buf, int len, uint8_t tid, void *p ) { opentv_module_t *mod = p; - epggrab_ota_mux_t *ota = epggrab_ota_find((epggrab_module_ota_t*)mod, tdmi); + epggrab_ota_mux_t *ota = epggrab_ota_find((epggrab_module_ota_t*)mod, dm); opentv_status_t *sta; if (!ota || !ota->status) return 0; sta = ota->status; @@ -642,7 +642,7 @@ static void _opentv_ota_destroy ( epggrab_ota_mux_t *ota ) } static void _opentv_start - ( epggrab_module_ota_t *m, th_dvb_mux_instance_t *tdmi ) + ( epggrab_module_ota_t *m, dvb_mux_t *dm ) { int *t; epggrab_ota_mux_t *ota; @@ -651,10 +651,10 @@ static void _opentv_start /* Ignore */ if (!m->enabled) return; - if (mod->tsid != tdmi->tdmi_mux->dm_transport_stream_id) return; + if (mod->tsid != dm->dm_transport_stream_id) return; /* Create link */ - if (!(ota = epggrab_ota_create(m, tdmi))) return; + if (!(ota = epggrab_ota_create(m, dm))) return; if (!ota->status) { ota->status = calloc(1, sizeof(opentv_status_t)); ota->destroy = _opentv_ota_destroy; @@ -672,7 +672,7 @@ static void _opentv_start t = mod->channel; while (*t) { // TODO: what about 0x46 (service description) - tdt_add(tdmi, 0x4a, 0xff, _opentv_channel_callback, m, + tdt_add(dm, 0x4a, 0xff, _opentv_channel_callback, m, m->id, TDT_CRC, *t++); } @@ -680,7 +680,7 @@ static void _opentv_start t = mod->title; while (*t) { _opentv_status_get_pid(sta, *t); - tdt_add(tdmi, 0xa0, 0xfc, _opentv_title_callback, m, + tdt_add(dm, 0xa0, 0xfc, _opentv_title_callback, m, m->id, TDT_CRC | TDT_TDT, *t++); } @@ -688,7 +688,7 @@ static void _opentv_start t = mod->summary; while (*t) { _opentv_status_get_pid(sta, *t); - tdt_add(tdmi, 0xa8, 0xfc, _opentv_summary_callback, m, + tdt_add(dm, 0xa8, 0xfc, _opentv_summary_callback, m, m->id, TDT_CRC | TDT_TDT, *t++); } } diff --git a/src/epggrab/otamux.c b/src/epggrab/otamux.c index 6d3a23cd..9fa07b67 100644 --- a/src/epggrab/otamux.c +++ b/src/epggrab/otamux.c @@ -36,27 +36,27 @@ TAILQ_HEAD(, epggrab_ota_mux) ota_mux_all; * Global functions (called from DVB code) * *************************************************************************/ -void epggrab_mux_start ( th_dvb_mux_instance_t *tdmi ) +void epggrab_mux_start ( dvb_mux_t *dm ) { epggrab_module_t *m; epggrab_module_ota_t *om; LIST_FOREACH(m, &epggrab_modules, link) { if (m->type == EPGGRAB_OTA) { om = (epggrab_module_ota_t*)m; - if (om->start) om->start(om, tdmi); + if (om->start) om->start(om, dm); } } } -void epggrab_mux_stop ( th_dvb_mux_instance_t *tdmi, int timeout ) +void epggrab_mux_stop ( dvb_mux_t *dm, int timeout ) { // Note: the slightly akward list iteration here is because // _ota_cancel/delete can remove the object and free() it epggrab_ota_mux_t *a, *b; - a = TAILQ_FIRST(&tdmi->tdmi_epg_grab); + a = TAILQ_FIRST(&dm->dm_epg_grab); while (a) { - b = TAILQ_NEXT(a, tdmi_link); - if (a->tdmi == tdmi) { + b = TAILQ_NEXT(a, dm_link); + if (a->dm == dm) { if (timeout) epggrab_ota_timeout(a); else @@ -66,16 +66,16 @@ void epggrab_mux_stop ( th_dvb_mux_instance_t *tdmi, int timeout ) } } -void epggrab_mux_delete ( th_dvb_mux_instance_t *tdmi ) +void epggrab_mux_delete ( dvb_mux_t *dm ) { - epggrab_ota_destroy_by_tdmi(tdmi); + epggrab_ota_destroy_by_dm(dm); } -int epggrab_mux_period ( th_dvb_mux_instance_t *tdmi ) +int epggrab_mux_period ( dvb_mux_t *dm ) { int period = 0; epggrab_ota_mux_t *ota; - TAILQ_FOREACH(ota, &tdmi->tdmi_epg_grab, tdmi_link) { + TAILQ_FOREACH(ota, &dm->dm_epg_grab, dm_link) { if (!ota->is_reg) continue; if (ota->timeout > period) period = ota->timeout; @@ -83,7 +83,7 @@ int epggrab_mux_period ( th_dvb_mux_instance_t *tdmi ) return period; } -th_dvb_mux_instance_t *epggrab_mux_next ( th_dvb_adapter_t *tda ) +dvb_mux_t *epggrab_mux_next ( th_dvb_adapter_t *tda ) { time_t now; epggrab_ota_mux_t *ota; @@ -91,9 +91,9 @@ th_dvb_mux_instance_t *epggrab_mux_next ( th_dvb_adapter_t *tda ) TAILQ_FOREACH(ota, &ota_mux_all, glob_link) { if (ota->interval + ota->completed > now) return NULL; if (!ota->is_reg) return NULL; - if (ota->tdmi->tdmi_adapter == tda) break; + if (ota->dm->dm_tdmi->tdmi_adapter == tda) break; } - return ota ? ota->tdmi : NULL; + return ota ? ota->dm : NULL; } /* ************************************************************************** @@ -148,7 +148,7 @@ static void _epggrab_ota_save_one ( htsmsg_t *m, epggrab_module_ota_t *mod ) if (!l) l = htsmsg_create_list(); e = htsmsg_create_map(); - const dvb_mux_t *dm = ota->tdmi->tdmi_mux; + const dvb_mux_t *dm = ota->dm; htsmsg_add_u32(e, "onid", dm->dm_network_id); htsmsg_add_u32(e, "tsid", dm->dm_transport_stream_id); @@ -212,11 +212,11 @@ static int _ota_time_cmp ( void *_a, void *_b ) * Find existing link */ epggrab_ota_mux_t *epggrab_ota_find - ( epggrab_module_ota_t *mod, th_dvb_mux_instance_t *tdmi ) + ( epggrab_module_ota_t *mod, dvb_mux_t *dm ) { epggrab_ota_mux_t *ota; TAILQ_FOREACH(ota, &mod->muxes, grab_link) { - if (ota->tdmi == tdmi) break; + if (ota->dm == dm) break; } return ota; } @@ -225,18 +225,18 @@ epggrab_ota_mux_t *epggrab_ota_find * Create (temporary) or Find (existing) link */ epggrab_ota_mux_t *epggrab_ota_create - ( epggrab_module_ota_t *mod, th_dvb_mux_instance_t *tdmi ) + ( epggrab_module_ota_t *mod, dvb_mux_t *dm) { /* Search for existing */ - epggrab_ota_mux_t *ota = epggrab_ota_find(mod, tdmi); + epggrab_ota_mux_t *ota = epggrab_ota_find(mod, dm); /* Create new */ if (!ota) { ota = calloc(1, sizeof(epggrab_ota_mux_t)); ota->grab = mod; - ota->tdmi = tdmi; + ota->dm = dm; TAILQ_INSERT_TAIL(&ota_mux_all, ota, glob_link); - TAILQ_INSERT_TAIL(&tdmi->tdmi_epg_grab, ota, tdmi_link); + TAILQ_INSERT_TAIL(&dm->dm_epg_grab, ota, dm_link); TAILQ_INSERT_TAIL(&mod->muxes, ota, grab_link); } else { @@ -259,12 +259,12 @@ void epggrab_ota_create_and_register_by_id 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) { - const dvb_mux_t *dm = tdmi->tdmi_mux; + dvb_mux_t *dm = tdmi->tdmi_mux; if (dm->dm_transport_stream_id != tsid) continue; if (onid && dm->dm_network_id != onid) continue; if (networkname && (!dm->dm_network_name || strcmp(networkname, dm->dm_network_name))) continue; - ota = epggrab_ota_create(mod, tdmi); + ota = epggrab_ota_create(mod, dm); epggrab_ota_register(ota, period, interval); } } @@ -276,7 +276,7 @@ void epggrab_ota_create_and_register_by_id void epggrab_ota_destroy ( epggrab_ota_mux_t *ota ) { TAILQ_REMOVE(&ota_mux_all, ota, glob_link); - TAILQ_REMOVE(&ota->tdmi->tdmi_epg_grab, ota, tdmi_link); + TAILQ_REMOVE(&ota->dm->dm_epg_grab, ota, dm_link); TAILQ_REMOVE(&ota->grab->muxes, ota, grab_link); if (ota->destroy) ota->destroy(ota); else { @@ -288,10 +288,10 @@ void epggrab_ota_destroy ( epggrab_ota_mux_t *ota ) /* * Destroy by tdmi */ -void epggrab_ota_destroy_by_tdmi ( th_dvb_mux_instance_t *tdmi ) +void epggrab_ota_destroy_by_dm ( dvb_mux_t *dm ) { epggrab_ota_mux_t *ota; - while ((ota = TAILQ_FIRST(&tdmi->tdmi_epg_grab))) + while ((ota = TAILQ_FIRST(&dm->dm_epg_grab))) epggrab_ota_destroy(ota); } @@ -359,7 +359,7 @@ int epggrab_ota_begin ( epggrab_ota_mux_t *ota ) void epggrab_ota_complete ( epggrab_ota_mux_t *ota ) { - th_dvb_mux_instance_t *tdmi = ota->tdmi; + dvb_mux_t *dm = ota->dm; if (ota->state != EPGGRAB_OTA_MUX_COMPLETE) { tvhlog(LOG_DEBUG, ota->grab->id, "processing complete"); @@ -367,12 +367,13 @@ void epggrab_ota_complete ( epggrab_ota_mux_t *ota ) time(&ota->completed); /* Check others */ - TAILQ_FOREACH(ota, &tdmi->tdmi_epg_grab, tdmi_link) { + TAILQ_FOREACH(ota, &dm->dm_epg_grab, dm_link) { if (ota->is_reg && ota->state == EPGGRAB_OTA_MUX_RUNNING) break; } /* All complete (bring timer forward) */ if (!ota) { + th_dvb_mux_instance_t *tdmi = dm->dm_tdmi; gtimer_arm(&tdmi->tdmi_adapter->tda_mux_scanner_timer, dvb_adapter_mux_scanner, tdmi->tdmi_adapter, 20); } diff --git a/src/epggrab/private.h b/src/epggrab/private.h index a9625862..7ce58ea1 100644 --- a/src/epggrab/private.h +++ b/src/epggrab/private.h @@ -88,7 +88,7 @@ epggrab_module_ota_t *epggrab_module_ota_create ( epggrab_module_ota_t *skel, const char *id, const char *name, int priority, void (*start) (epggrab_module_ota_t*m, - struct th_dvb_mux_instance *tdmi), + struct dvb_mux *dm), int (*enable) (void *m, uint8_t e ), epggrab_channel_tree_t *channels ); @@ -109,9 +109,9 @@ void epggrab_ota_save ( void ); * blocked (i.e. has completed within interval period) */ epggrab_ota_mux_t *epggrab_ota_find - ( epggrab_module_ota_t *mod, struct th_dvb_mux_instance *tdmi ); + ( epggrab_module_ota_t *mod, struct dvb_mux *dm ); epggrab_ota_mux_t *epggrab_ota_create - ( epggrab_module_ota_t *mod, struct th_dvb_mux_instance *tdmi ); + ( epggrab_module_ota_t *mod, struct dvb_mux *dm ); void epggrab_ota_create_and_register_by_id ( epggrab_module_ota_t *mod, int nid, int tsid, int period, int interval, const char *name ); @@ -121,7 +121,7 @@ void epggrab_ota_create_and_register_by_id */ void epggrab_ota_destroy ( epggrab_ota_mux_t *ota ); void epggrab_ota_destroy_by_module ( epggrab_module_ota_t *mod ); -void epggrab_ota_destroy_by_tdmi ( struct th_dvb_mux_instance *tdmi ); +void epggrab_ota_destroy_by_dm ( struct dvb_mux *dm ); /* * Register interest From f991e1376e110b9c159ad465d8f7299be3a6cdac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20=C3=96man?= Date: Wed, 5 Dec 2012 13:09:41 +0100 Subject: [PATCH 16/31] Migrate tables into dvb_mux. Also let some parts of the tuning work with dvb_mux --- Makefile | 1 + src/dvb/dvb.h | 49 ++++++++++------- src/dvb/dvb_adapter.c | 21 +++----- src/dvb/dvb_fe.c | 60 +++++++++++---------- src/dvb/dvb_input_filtered.c | 36 +++++++------ src/dvb/dvb_input_raw.c | 21 ++++---- src/dvb/dvb_multiplex.c | 57 ++++++++++---------- src/dvb/dvb_network.c | 102 +++++++++++++++++++++++++++++++++++ src/dvb/dvb_service.c | 4 +- src/dvb/dvb_tables.c | 35 ++++++------ src/epggrab.h | 4 +- src/epggrab/otamux.c | 10 ++-- 12 files changed, 259 insertions(+), 141 deletions(-) create mode 100644 src/dvb/dvb_network.c diff --git a/Makefile b/Makefile index 3da26556..a4e63011 100644 --- a/Makefile +++ b/Makefile @@ -153,6 +153,7 @@ SRCS-${CONFIG_LINUXDVB} += \ src/dvb/dvb_tables.c \ src/dvb/diseqc.c \ src/dvb/dvb_adapter.c \ + src/dvb/dvb_network.c \ src/dvb/dvb_multiplex.c \ src/dvb/dvb_service.c \ src/dvb/dvb_preconf.c \ diff --git a/src/dvb/dvb.h b/src/dvb/dvb.h index 806360e4..c1bc22f9 100644 --- a/src/dvb/dvb.h +++ b/src/dvb/dvb.h @@ -40,6 +40,7 @@ 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); LIST_HEAD(dvb_mux_list, dvb_mux); +TAILQ_HEAD(dvb_mux_queue, dvb_mux); /** * Satconf @@ -90,7 +91,7 @@ typedef struct dvb_network { struct th_dvb_mux_instance_list dn_mux_instances; // Should go away - struct th_dvb_mux_instance_queue dn_initial_scan_queue; + struct dvb_mux_queue dn_initial_scan_queue; int dn_initial_num_mux; struct dvb_mux *dn_mux_epg; @@ -99,6 +100,8 @@ typedef struct dvb_network { struct dvb_mux_list dn_muxes; + gtimer_t dn_mux_scanner_timer; + } dvb_network_t; @@ -124,6 +127,17 @@ typedef struct dvb_mux { struct th_dvb_mux_instance *dm_tdmi; // wrong + TAILQ_ENTRY(dvb_mux) dm_scan_link; + struct dvb_mux_queue *dm_scan_queue; + + LIST_HEAD(, th_dvb_table) dm_tables; + int dm_num_tables; + + TAILQ_HEAD(, th_dvb_table) dm_table_queue; + int dm_table_initial; + + struct th_dvb_mux_instance *dm_current_tdmi; + } dvb_mux_t; @@ -150,11 +164,6 @@ typedef struct th_dvb_mux_instance { uint32_t tdmi_fec_err_histogram[TDMI_FEC_ERR_HISTOGRAM_SIZE]; int tdmi_fec_err_ptr; - LIST_HEAD(, th_dvb_table) tdmi_tables; - int tdmi_num_tables; - - TAILQ_HEAD(, th_dvb_table) tdmi_table_queue; - int tdmi_table_initial; enum { TDMI_FE_UNKNOWN, @@ -173,9 +182,6 @@ typedef struct th_dvb_mux_instance { char *tdmi_identifier; - TAILQ_ENTRY(th_dvb_mux_instance) tdmi_scan_link; - struct th_dvb_mux_instance_queue *tdmi_scan_queue; - struct th_subscription_list tdmi_subscriptions; } th_dvb_mux_instance_t; @@ -210,7 +216,7 @@ typedef struct th_dvb_adapter { dvb_network_t *tda_dn; - th_dvb_mux_instance_t *tda_mux_current; + th_dvb_mux_instance_t *tda_current_tdmi; char *tda_tune_reason; // Reason for last tune int tda_table_epollfd; @@ -246,8 +252,6 @@ typedef struct th_dvb_adapter { int tda_hostconnection; - gtimer_t tda_mux_scanner_timer; - pthread_mutex_t tda_delivery_mutex; struct service_list tda_transports; /* Currently bound transports */ @@ -268,8 +272,8 @@ typedef struct th_dvb_adapter { void (*tda_open_service)(struct th_dvb_adapter *tda, struct service *s); void (*tda_close_service)(struct th_dvb_adapter *tda, struct service *s); - void (*tda_open_table)(struct th_dvb_mux_instance *tdmi, struct th_dvb_table *s); - void (*tda_close_table)(struct th_dvb_mux_instance *tdmi, struct th_dvb_table *s); + void (*tda_open_table)(struct dvb_mux *dm, struct th_dvb_table *s); + void (*tda_close_table)(struct dvb_mux *dm, struct th_dvb_table *s); int tda_rawmode; @@ -346,8 +350,6 @@ void dvb_init(uint32_t adapter_mask, const char *rawfile); */ void dvb_adapter_init(uint32_t adapter_mask, const char *rawfile); -void dvb_adapter_mux_scanner(void *aux); - void dvb_adapter_start (th_dvb_adapter_t *tda); void dvb_adapter_stop (th_dvb_adapter_t *tda); @@ -493,9 +495,9 @@ htsmsg_t *dvb_service_build_msg(struct service *t); /** * DVB Frontend */ -int dvb_fe_tune(th_dvb_mux_instance_t *tdmi, const char *reason); +int dvb_fe_tune(dvb_mux_t *dm, const char *reason); -void dvb_fe_stop(th_dvb_mux_instance_t *tdmi, int retune); +void dvb_fe_stop(th_dvb_adapter_t *tda, int retune); /** @@ -505,7 +507,7 @@ void dvb_table_init(th_dvb_adapter_t *tda); void dvb_table_add_default(dvb_mux_t *dm); -void dvb_table_flush_all(th_dvb_mux_instance_t *tdmi); +void dvb_table_flush_all(dvb_mux_t *dm); void dvb_table_add_pmt(dvb_mux_t *dm, int pmt_pid); @@ -528,6 +530,15 @@ void dvb_table_dispatch(uint8_t *sec, int r, th_dvb_table_t *tdt); void dvb_table_release(th_dvb_table_t *tdt); + +/** + * + */ +dvb_network_t *dvb_network_create(int fe_type); + +void dvb_network_mux_scanner(void *aux); + + /** * Satellite configuration */ diff --git a/src/dvb/dvb_adapter.c b/src/dvb/dvb_adapter.c index d1d12bb7..eeb9b749 100644 --- a/src/dvb/dvb_adapter.c +++ b/src/dvb/dvb_adapter.c @@ -57,11 +57,7 @@ static th_dvb_adapter_t * tda_alloc(void) { th_dvb_adapter_t *tda = calloc(1, sizeof(th_dvb_adapter_t)); - dvb_network_t *dn = calloc(1, sizeof(dvb_network_t)); pthread_mutex_init(&tda->tda_delivery_mutex, NULL); - - tda->tda_dn = dn; - TAILQ_INIT(&dn->dn_initial_scan_queue); TAILQ_INIT(&tda->tda_satconfs); streaming_pad_init(&tda->tda_streaming_pad); return tda; @@ -467,7 +463,7 @@ tda_add(int adapter_num) close(fe); tda->tda_fe_type = tda->tda_fe_info->type; - tda->tda_dn->dn_fe_type = tda->tda_fe_type; + tda->tda_dn = dvb_network_create(tda->tda_fe_type); snprintf(buf, sizeof(buf), "%s_%s", tda->tda_rootpath, tda->tda_fe_info->name); @@ -495,8 +491,6 @@ tda_add(int adapter_num) hostconnection2str(tda->tda_hostconnection)); TAILQ_INSERT_TAIL(&dvb_adapters, tda, tda_global_link); - - gtimer_arm(&tda->tda_mux_scanner_timer, dvb_adapter_mux_scanner, tda, 1); } @@ -587,7 +581,7 @@ dvb_adapter_start ( th_dvb_adapter_t *tda ) void dvb_adapter_stop ( th_dvb_adapter_t *tda ) { - assert(tda->tda_mux_current == NULL); + assert(tda->tda_current_tdmi == NULL); /* Poweroff */ dvb_adapter_poweroff(tda); @@ -696,7 +690,7 @@ dvb_adapter_init(uint32_t adapter_mask, const char *rawfile) } } - +#if 0 /** * If nobody is subscribing, cycle thru all muxes to get some stats * and EIT updates @@ -757,6 +751,7 @@ dvb_adapter_mux_scanner(void *aux) if (tda->tda_mux_current) dvb_fe_stop(tda->tda_mux_current, 0); } +#endif /** * @@ -945,7 +940,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_mux_current) + if(t->s_dvb_mux_instance == tda->tda_current_tdmi) ts_recv_packet1(t, tsb + i, NULL); } @@ -1009,10 +1004,10 @@ dvb_adapter_build_msg(th_dvb_adapter_t *tda) htsmsg_add_u32(m, "muxes", nummux); htsmsg_add_u32(m, "initialMuxes", tda->tda_dn->dn_initial_num_mux); - if(tda->tda_mux_current != NULL) { - th_dvb_mux_instance_t *tdmi = tda->tda_mux_current; + if(tda->tda_current_tdmi != NULL) { + th_dvb_mux_instance_t *tdmi = tda->tda_current_tdmi; - dvb_mux_nicename(buf, sizeof(buf), tda->tda_mux_current); + dvb_mux_nicename(buf, sizeof(buf), tda->tda_current_tdmi); htsmsg_add_str(m, "currentMux", buf); htsmsg_add_u32(m, "signal", MIN(tdmi->tdmi_signal * 100 / 65535, 100)); diff --git a/src/dvb/dvb_fe.c b/src/dvb/dvb_fe.c index 97c1c042..09d52098 100644 --- a/src/dvb/dvb_fe.c +++ b/src/dvb/dvb_fe.c @@ -91,7 +91,7 @@ dvb_fe_monitor(void *aux) th_dvb_adapter_t *tda = aux; fe_status_t fe_status; int status, v, vv, i, fec, q; - th_dvb_mux_instance_t *tdmi = tda->tda_mux_current; + th_dvb_mux_instance_t *tdmi = tda->tda_current_tdmi; char buf[50]; signal_status_t sigstat; streaming_message_t sm; @@ -245,7 +245,8 @@ dvb_fe_monitor(void *aux) 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_mux_current && t->s_status == SERVICE_RUNNING ) { + 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); @@ -258,31 +259,32 @@ dvb_fe_monitor(void *aux) * Stop the given TDMI */ void -dvb_fe_stop(th_dvb_mux_instance_t *tdmi, int retune) +dvb_fe_stop(th_dvb_adapter_t *tda, int retune) { - th_dvb_adapter_t *tda = tdmi->tdmi_adapter; - lock_assert(&global_lock); - assert(tdmi == tda->tda_mux_current); - tda->tda_mux_current = NULL; + th_dvb_mux_instance_t *tdmi = tda->tda_current_tdmi; + assert(tdmi != NULL); + dvb_mux_t *dm = tdmi->tdmi_mux; - if(tdmi->tdmi_table_initial) { - tdmi->tdmi_table_initial = 0; - tda->tda_dn->dn_initial_num_mux--; - dvb_mux_save(tdmi); + if(dm->dm_table_initial) { + dm->dm_table_initial = 0; + dm->dm_dn->dn_initial_num_mux--; + dvb_mux_save(dm->dm_tdmi); } - dvb_table_flush_all(tdmi); + dvb_table_flush_all(dm); - assert(tdmi->tdmi_scan_queue == NULL); + assert(dm->dm_scan_queue == NULL); - epggrab_mux_stop(tdmi->tdmi_mux, 0); + epggrab_mux_stop(dm, 0); - if (!retune) { +#if 0 /// XXX(dvbreorg) + if(!retune) { gtimer_disarm(&tda->tda_fe_monitor_timer); dvb_adapter_stop(tda); } +#endif } #if DVB_API_VERSION >= 5 @@ -391,12 +393,14 @@ dvb_fe_tune_s2(th_dvb_mux_instance_t *tdmi, dvb_mux_conf_t *dmc) * */ int -dvb_fe_tune(th_dvb_mux_instance_t *tdmi, const char *reason) +dvb_fe_tune(dvb_mux_t *dm, const char *reason) { - th_dvb_adapter_t *tda = tdmi->tdmi_adapter; + 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; // copy dmc, cause frequency may be change with FE_QPSK - const dvb_mux_t *dm = tdmi->tdmi_mux; dvb_mux_conf_t dmc = dm->dm_conf; dvb_frontend_parameters_t* p = &dmc.dmc_fe_params; @@ -409,18 +413,18 @@ dvb_fe_tune(th_dvb_mux_instance_t *tdmi, const char *reason) free(tda->tda_tune_reason); tda->tda_tune_reason = strdup(reason); - if(tda->tda_mux_current == tdmi) { + if(tda->tda_current_tdmi == tdmi) { dvb_adapter_notify(tda); return 0; } - if(tdmi->tdmi_scan_queue != NULL) { - TAILQ_REMOVE(tdmi->tdmi_scan_queue, tdmi, tdmi_scan_link); - tdmi->tdmi_scan_queue = NULL; + if(dm->dm_scan_queue != NULL) { + TAILQ_REMOVE(dm->dm_scan_queue, dm, dm_scan_link); + dm->dm_scan_queue = NULL; } - if(tda->tda_mux_current != NULL) - dvb_fe_stop(tda->tda_mux_current, 1); + if(tda->tda_current_tdmi != NULL) + dvb_fe_stop(tda, 1); else dvb_adapter_start(tda); @@ -497,9 +501,9 @@ dvb_fe_tune(th_dvb_mux_instance_t *tdmi, const char *reason) tda->tda_rootpath, buf, strerror(errno), p->frequency); /* Remove from initial scan set */ - if(tdmi->tdmi_table_initial) { - tdmi->tdmi_table_initial = 0; - tda->tda_dn->dn_initial_num_mux--; + if(dm->dm_table_initial) { + dm->dm_table_initial = 0; + dn->dn_initial_num_mux--; } /* Mark as bad */ @@ -507,7 +511,7 @@ dvb_fe_tune(th_dvb_mux_instance_t *tdmi, const char *reason) return SM_CODE_TUNING_FAILED; } - tda->tda_mux_current = tdmi; + tda->tda_current_tdmi = tdmi; gtimer_arm(&tda->tda_fe_monitor_timer, dvb_fe_monitor, tda, 1); diff --git a/src/dvb/dvb_input_filtered.c b/src/dvb/dvb_input_filtered.c index a4dddf26..2943e4e1 100644 --- a/src/dvb/dvb_input_filtered.c +++ b/src/dvb/dvb_input_filtered.c @@ -110,9 +110,9 @@ close_service(th_dvb_adapter_t *tda, service_t *s) * */ static void -open_table(th_dvb_mux_instance_t *tdmi, th_dvb_table_t *tdt) +open_table(dvb_mux_t *dm, th_dvb_table_t *tdt) { - th_dvb_adapter_t *tda = tdmi->tdmi_adapter; + th_dvb_adapter_t *tda = dm->dm_current_tdmi->tdmi_adapter; struct epoll_event e; static int tdt_id_tally; @@ -148,7 +148,7 @@ open_table(th_dvb_mux_instance_t *tdmi, th_dvb_table_t *tdt) } if(tdt->tdt_fd == -1) - TAILQ_INSERT_TAIL(&tdmi->tdmi_table_queue, tdt, tdt_pending_link); + TAILQ_INSERT_TAIL(&dm->dm_table_queue, tdt, tdt_pending_link); } @@ -156,9 +156,9 @@ open_table(th_dvb_mux_instance_t *tdmi, th_dvb_table_t *tdt) * Close FD for the given table and put table on the pending list */ static void -tdt_close_fd(th_dvb_mux_instance_t *tdmi, th_dvb_table_t *tdt) +tdt_close_fd(dvb_mux_t *dm, th_dvb_table_t *tdt) { - th_dvb_adapter_t *tda = tdmi->tdmi_adapter; + th_dvb_adapter_t *tda = dm->dm_current_tdmi->tdmi_adapter; assert(tdt->tdt_fd != -1); @@ -166,7 +166,7 @@ tdt_close_fd(th_dvb_mux_instance_t *tdmi, th_dvb_table_t *tdt) close(tdt->tdt_fd); tdt->tdt_fd = -1; - TAILQ_INSERT_TAIL(&tdmi->tdmi_table_queue, tdt, tdt_pending_link); + TAILQ_INSERT_TAIL(&dm->dm_table_queue, tdt, tdt_pending_link); } @@ -181,7 +181,7 @@ dvb_table_input(void *aux) int r, i, tid, fd, x; struct epoll_event ev[1]; uint8_t sec[4096]; - th_dvb_mux_instance_t *tdmi; + dvb_mux_t *dm; th_dvb_table_t *tdt; int64_t cycle_barrier = 0; @@ -200,8 +200,8 @@ dvb_table_input(void *aux) continue; pthread_mutex_lock(&global_lock); - if((tdmi = tda->tda_mux_current) != NULL) { - LIST_FOREACH(tdt, &tdmi->tdmi_tables, tdt_link) + if((dm = tda->tda_current_tdmi->tdmi_mux) != NULL) { + LIST_FOREACH(tdt, &dm->dm_tables, tdt_link) if(tdt->tdt_id == tid) break; @@ -209,15 +209,15 @@ dvb_table_input(void *aux) dvb_table_dispatch(sec, r, tdt); /* Any tables pending (that wants a filter/fd), close this one */ - if(TAILQ_FIRST(&tdmi->tdmi_table_queue) != NULL && + if(TAILQ_FIRST(&dm->dm_table_queue) != NULL && cycle_barrier < getmonoclock()) { - tdt_close_fd(tdmi, tdt); + tdt_close_fd(dm, tdt); cycle_barrier = getmonoclock() + 100000; - tdt = TAILQ_FIRST(&tdmi->tdmi_table_queue); + tdt = TAILQ_FIRST(&dm->dm_table_queue); assert(tdt != NULL); - TAILQ_REMOVE(&tdmi->tdmi_table_queue, tdt, tdt_pending_link); + TAILQ_REMOVE(&dm->dm_table_queue, tdt, tdt_pending_link); - open_table(tdmi, tdt); + open_table(dm, tdt); } } } @@ -229,13 +229,15 @@ dvb_table_input(void *aux) static void -close_table(th_dvb_mux_instance_t *tdmi, th_dvb_table_t *tdt) +close_table(dvb_mux_t *dm, th_dvb_table_t *tdt) { - th_dvb_adapter_t *tda = tdmi->tdmi_adapter; if(tdt->tdt_fd == -1) { - TAILQ_REMOVE(&tdmi->tdmi_table_queue, tdt, tdt_pending_link); + TAILQ_REMOVE(&dm->dm_table_queue, tdt, tdt_pending_link); } else { + th_dvb_mux_instance_t *tdmi = dm->dm_current_tdmi; + th_dvb_adapter_t *tda = tdmi->tdmi_adapter; + epoll_ctl(tda->tda_table_epollfd, EPOLL_CTL_DEL, tdt->tdt_fd, NULL); close(tdt->tdt_fd); } diff --git a/src/dvb/dvb_input_raw.c b/src/dvb/dvb_input_raw.c index 0c3f2a56..7176e0ef 100644 --- a/src/dvb/dvb_input_raw.c +++ b/src/dvb/dvb_input_raw.c @@ -62,8 +62,9 @@ close_service(th_dvb_adapter_t *tda, service_t *s) * */ static void -open_table(th_dvb_mux_instance_t *tdmi, th_dvb_table_t *tdt) +open_table(dvb_mux_t *dm, th_dvb_table_t *tdt) { + th_dvb_mux_instance_t *tdmi = dm->dm_current_tdmi; th_dvb_adapter_t *tda = tdmi->tdmi_adapter; assert(tdt->tdt_pid < 0x2000); tda->tda_table_filter[tdt->tdt_pid] = 1; @@ -74,8 +75,9 @@ open_table(th_dvb_mux_instance_t *tdmi, th_dvb_table_t *tdt) * */ static void -close_table(th_dvb_mux_instance_t *tdmi, th_dvb_table_t *tdt) +close_table(dvb_mux_t *dm, th_dvb_table_t *tdt) { + th_dvb_mux_instance_t *tdmi = dm->dm_current_tdmi; th_dvb_adapter_t *tda = tdmi->tdmi_adapter; assert(tdt->tdt_pid < 0x2000); tda->tda_table_filter[tdt->tdt_pid] = 0; @@ -99,18 +101,17 @@ got_section(const uint8_t *data, size_t len, void *opaque) * so we need to be a bit careful here */ static void -dvb_table_raw_dispatch(th_dvb_mux_instance_t *tdmi, - const dvb_table_feed_t *dtf) +dvb_table_raw_dispatch(dvb_mux_t *dm, const dvb_table_feed_t *dtf) { int pid = (dtf->dtf_tsb[1] & 0x1f) << 8 | dtf->dtf_tsb[2]; - th_dvb_table_t *vec[tdmi->tdmi_num_tables], *tdt; + th_dvb_table_t *vec[dm->dm_num_tables], *tdt; int i = 0; - LIST_FOREACH(tdt, &tdmi->tdmi_tables, tdt_link) { + LIST_FOREACH(tdt, &dm->dm_tables, tdt_link) { vec[i++] = tdt; tdt->tdt_refcount++; } - assert(i == tdmi->tdmi_num_tables); - int len = tdmi->tdmi_num_tables; // can change during callbacks + assert(i == dm->dm_num_tables); + int len = dm->dm_num_tables; // can change during callbacks for(i = 0; i < len; i++) { tdt = vec[i]; if(!tdt->tdt_destroyed) { @@ -144,8 +145,8 @@ dvb_table_input(void *aux) pthread_mutex_lock(&global_lock); - if((tdmi = tda->tda_mux_current) != NULL) - dvb_table_raw_dispatch(tdmi, dtf); + if((tdmi = tda->tda_current_tdmi) != NULL) + dvb_table_raw_dispatch(tdmi->tdmi_mux, dtf); pthread_mutex_unlock(&global_lock); free(dtf); diff --git a/src/dvb/dvb_multiplex.c b/src/dvb/dvb_multiplex.c index a85bf6fc..c3e1d096 100644 --- a/src/dvb/dvb_multiplex.c +++ b/src/dvb/dvb_multiplex.c @@ -65,16 +65,12 @@ static void tdmi_set_enable(th_dvb_mux_instance_t *tdmi, int enabled); * */ static void -mux_link_initial(th_dvb_adapter_t *tda, th_dvb_mux_instance_t *tdmi) +mux_link_initial(dvb_network_t *dn, dvb_mux_t *dm) { - int was_empty = TAILQ_FIRST(&tda->tda_dn->dn_initial_scan_queue) == NULL; + dm->dm_scan_queue = &dn->dn_initial_scan_queue; + TAILQ_INSERT_TAIL(dm->dm_scan_queue, dm, dm_scan_link); - tdmi->tdmi_scan_queue = &tda->tda_dn->dn_initial_scan_queue; - TAILQ_INSERT_TAIL(tdmi->tdmi_scan_queue, tdmi, tdmi_scan_link); - - if(was_empty && (tda->tda_mux_current == NULL || - tda->tda_mux_current->tdmi_table_initial == 0)) - gtimer_arm(&tda->tda_mux_scanner_timer, dvb_adapter_mux_scanner, tda, 0); + gtimer_arm(&dn->dn_mux_scanner_timer, dvb_network_mux_scanner, dn, 0); } /** @@ -155,6 +151,7 @@ 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_network_t *dn = tda->tda_dn; th_dvb_mux_instance_t *tdmi, *c; char buf[200]; @@ -229,6 +226,7 @@ dvb_mux_create(th_dvb_adapter_t *tda, const struct dvb_mux_conf *dmc, dm->dm_transport_stream_id = tsid; dm->dm_network_name = network ? strdup(network) : NULL; 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); @@ -269,7 +267,6 @@ dvb_mux_create(th_dvb_adapter_t *tda, const struct dvb_mux_conf *dmc, tdmi->tdmi_enabled = enabled; - TAILQ_INIT(&tdmi->tdmi_table_queue); tdmi->tdmi_adapter = tda; @@ -278,7 +275,7 @@ dvb_mux_create(th_dvb_adapter_t *tda, const struct dvb_mux_conf *dmc, 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); - tdmi->tdmi_table_initial = initialscan; + dm->dm_table_initial = initialscan; if(source != NULL) { dvb_mux_nicename(buf, sizeof(buf), tdmi); @@ -291,9 +288,9 @@ dvb_mux_create(th_dvb_adapter_t *tda, const struct dvb_mux_conf *dmc, dvb_service_load(tdmi, identifier); dvb_mux_notify(tdmi); - if(enabled && tdmi->tdmi_table_initial) { - tda->tda_dn->dn_initial_num_mux++; - mux_link_initial(tda, tdmi); + if(enabled && dm->dm_table_initial) { + dn->dn_initial_num_mux++; + mux_link_initial(dn, dm); } return tdmi; @@ -306,6 +303,7 @@ void dvb_mux_destroy(th_dvb_mux_instance_t *tdmi) { th_dvb_adapter_t *tda = tdmi->tdmi_adapter; + dvb_mux_t *dm = tdmi->tdmi_mux; service_t *t; lock_assert(&global_lock); @@ -322,19 +320,19 @@ dvb_mux_destroy(th_dvb_mux_instance_t *tdmi) dvb_service_notify_by_adapter(tda); - if(tda->tda_mux_current == tdmi) - dvb_fe_stop(tda->tda_mux_current, 0); + 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); - if(tdmi->tdmi_scan_queue != NULL) - TAILQ_REMOVE(tdmi->tdmi_scan_queue, tdmi, tdmi_scan_link); + if(dm->dm_scan_queue != NULL) + TAILQ_REMOVE(dm->dm_scan_queue, dm, dm_scan_link); - if(tdmi->tdmi_table_initial) - tda->tda_dn->dn_initial_num_mux--; + if(dm->dm_table_initial) + dm->dm_dn->dn_initial_num_mux--; - epggrab_mux_delete(tdmi->tdmi_mux); // XXX(dvbreorg) + epggrab_mux_delete(dm); hts_settings_remove("dvbmuxes/%s", tdmi->tdmi_identifier); @@ -562,7 +560,7 @@ dvb_mux_save(th_dvb_mux_instance_t *tdmi) htsmsg_add_u32(m, "frequency", f->frequency); - htsmsg_add_u32(m, "initialscan", tdmi->tdmi_table_initial); + htsmsg_add_u32(m, "initialscan", tdmi->tdmi_mux->dm_table_initial); if(tdmi->tdmi_mux->dm_default_authority) htsmsg_add_str(m, "default_authority", tdmi->tdmi_mux->dm_default_authority); @@ -877,26 +875,27 @@ dvb_mux_set_onid(dvb_mux_t *dm, uint16_t onid) static void tdmi_set_enable(th_dvb_mux_instance_t *tdmi, int enabled) { + dvb_mux_t *dm = tdmi->tdmi_mux; th_dvb_adapter_t *tda = tdmi->tdmi_adapter; - + if(tdmi->tdmi_enabled == enabled) return; if(tdmi->tdmi_enabled) { - if(tda->tda_mux_current == tdmi) - dvb_fe_stop(tdmi, 0); + if(tda->tda_current_tdmi == tdmi) + dvb_fe_stop(tda, 0); - if(tdmi->tdmi_scan_queue != NULL) { - TAILQ_REMOVE(tdmi->tdmi_scan_queue, tdmi, tdmi_scan_link); - tdmi->tdmi_scan_queue = NULL; + if(dm->dm_scan_queue != NULL) { + TAILQ_REMOVE(dm->dm_scan_queue, dm, dm_scan_link); + dm->dm_scan_queue = NULL; } } tdmi->tdmi_enabled = enabled; if(enabled) - mux_link_initial(tda, tdmi); + mux_link_initial(tda->tda_dn, dm); subscription_reschedule(); } @@ -1275,7 +1274,7 @@ 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, "Full mux subscription"); + dvb_fe_tune(tdmi->tdmi_mux, "Full mux subscription"); pthread_mutex_lock(&tda->tda_delivery_mutex); streaming_target_connect(&tda->tda_streaming_pad, &s->ths_input); diff --git a/src/dvb/dvb_network.c b/src/dvb/dvb_network.c new file mode 100644 index 00000000..9dd2239a --- /dev/null +++ b/src/dvb/dvb_network.c @@ -0,0 +1,102 @@ +/* + * TV Input - Linux DVB interface + * Copyright (C) 2007 - 2012 Andreas Öman + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "tvheadend.h" +#include "packet.h" +#include "dvb.h" +#include "epggrab.h" + + + +/** + * + */ +dvb_network_t * +dvb_network_create(int fe_type) +{ + dvb_network_t *dn = calloc(1, sizeof(dvb_network_t)); + 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); + return dn; +} + + + +/** + * + */ +void +dvb_network_mux_scanner(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; + } +#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 +} diff --git a/src/dvb/dvb_service.c b/src/dvb/dvb_service.c index b5d55794..2399e50d 100644 --- a/src/dvb/dvb_service.c +++ b/src/dvb/dvb_service.c @@ -59,7 +59,7 @@ dvb_service_start(service_t *t, unsigned int weight, int force_start) { int w, r; th_dvb_adapter_t *tda = t->s_dvb_mux_instance->tdmi_adapter; - th_dvb_mux_instance_t *tdmi = tda->tda_mux_current; + th_dvb_mux_instance_t *tdmi = tda->tda_current_tdmi; lock_assert(&global_lock); @@ -88,7 +88,7 @@ dvb_service_start(service_t *t, unsigned int weight, int force_start) pthread_mutex_lock(&tda->tda_delivery_mutex); - r = dvb_fe_tune(t->s_dvb_mux_instance, "Transport start"); + r = dvb_fe_tune(t->s_dvb_mux_instance->tdmi_mux, "Transport start"); if(!r) LIST_INSERT_HEAD(&tda->tda_transports, t, s_active_link); diff --git a/src/dvb/dvb_tables.c b/src/dvb/dvb_tables.c index 3708d025..ff25f37d 100644 --- a/src/dvb/dvb_tables.c +++ b/src/dvb/dvb_tables.c @@ -51,24 +51,26 @@ 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(!tdmi->tdmi_table_initial) + if(!dm->dm_table_initial) return; - LIST_FOREACH(tdt, &tdmi->tdmi_tables, tdt_link) + LIST_FOREACH(tdt, &dm->dm_tables, tdt_link) if((tdt->tdt_flags & TDT_QUICKREQ) && tdt->tdt_count == 0) return; - tdmi->tdmi_table_initial = 0; - tda->tda_dn->dn_initial_num_mux--; + dm->dm_table_initial = 0; + dn->dn_initial_num_mux--; dvb_mux_save(tdmi); dvb_mux_nicename(buf, sizeof(buf), tdmi); tvhlog(LOG_DEBUG, "dvb", "\"%s\" initial scan completed for \"%s\"", tda->tda_rootpath, buf); - dvb_adapter_mux_scanner(tda); + dvb_network_mux_scanner(dn); } @@ -140,11 +142,12 @@ static void dvb_tdt_destroy(th_dvb_adapter_t *tda, th_dvb_mux_instance_t *tdmi, th_dvb_table_t *tdt) { + dvb_mux_t *dm = tdmi->tdmi_mux; lock_assert(&global_lock); assert(tdt->tdt_tdmi == tdmi); LIST_REMOVE(tdt, tdt_link); - tdmi->tdmi_num_tables--; - tda->tda_close_table(tdmi, tdt); + dm->dm_num_tables--; + tda->tda_close_table(dm, tdt); free(tdt->tdt_name); tdt->tdt_destroyed = 1; dvb_table_release(tdt); @@ -167,7 +170,7 @@ tdt_add(dvb_mux_t *dm, int tableid, int mask, // TODO: this could mean reading the same data multiple times, and not // sure how well this will work! I know Andreas has some thoughts on // this - LIST_FOREACH(t, &tdmi->tdmi_tables, tdt_link) { + LIST_FOREACH(t, &dm->dm_tables, tdt_link) { if(pid == t->tdt_pid && t->tdt_callback == callback && t->tdt_opaque == opaque) { return; @@ -184,11 +187,11 @@ tdt_add(dvb_mux_t *dm, int tableid, int mask, tdt->tdt_table = tableid; tdt->tdt_mask = mask; tdt->tdt_tdmi = tdmi; - LIST_INSERT_HEAD(&tdmi->tdmi_tables, tdt, tdt_link); - tdmi->tdmi_num_tables++; + LIST_INSERT_HEAD(&dm->dm_tables, tdt, tdt_link); + dm->dm_num_tables++; tdt->tdt_fd = -1; - tdmi->tdmi_adapter->tda_open_table(tdmi, tdt); + tdmi->tdmi_adapter->tda_open_table(dm, tdt); } /** @@ -1095,7 +1098,7 @@ dvb_table_rem_pmt(dvb_mux_t *dm, int pmt_pid) th_dvb_mux_instance_t *tdmi = dm->dm_tdmi; th_dvb_adapter_t *tda = tdmi->tdmi_adapter; th_dvb_table_t *tdt = NULL; - LIST_FOREACH(tdt, &tdmi->tdmi_tables, tdt_link) + LIST_FOREACH(tdt, &dm->dm_tables, tdt_link) if (tdt->tdt_pid == pmt_pid && tdt->tdt_callback == dvb_pmt_callback) break; if (tdt) @@ -1107,12 +1110,12 @@ dvb_table_rem_pmt(dvb_mux_t *dm, int pmt_pid) * */ void -dvb_table_flush_all(th_dvb_mux_instance_t *tdmi) +dvb_table_flush_all(dvb_mux_t *dm) { - th_dvb_adapter_t *tda = tdmi->tdmi_adapter; + th_dvb_adapter_t *tda = dm->dm_tdmi->tdmi_adapter; th_dvb_table_t *tdt; - while((tdt = LIST_FIRST(&tdmi->tdmi_tables)) != NULL) - dvb_tdt_destroy(tda, tdmi, tdt); + while((tdt = LIST_FIRST(&dm->dm_tables)) != NULL) + dvb_tdt_destroy(tda, dm->dm_tdmi, tdt); } diff --git a/src/epggrab.h b/src/epggrab.h index d72f98d6..cfc47ae0 100644 --- a/src/epggrab.h +++ b/src/epggrab.h @@ -26,7 +26,7 @@ * *************************************************************************/ struct th_dvb_mux_instance; -struct th_dvb_adapter; +struct dvb_network; typedef struct epggrab_module epggrab_module_t; typedef struct epggrab_module_int epggrab_module_int_t; @@ -263,7 +263,7 @@ void epggrab_mux_start ( struct dvb_mux *tdmi ); void epggrab_mux_stop ( struct dvb_mux *tdmi, int timeout ); void epggrab_mux_delete ( struct dvb_mux *tdmi ); int epggrab_mux_period ( struct dvb_mux *tdmi ); -struct dvb_mux *epggrab_mux_next ( struct th_dvb_adapter *tda ); +struct dvb_mux *epggrab_mux_next ( struct dvb_network *dn ); /* * Re-schedule diff --git a/src/epggrab/otamux.c b/src/epggrab/otamux.c index 9fa07b67..93e4431d 100644 --- a/src/epggrab/otamux.c +++ b/src/epggrab/otamux.c @@ -83,7 +83,7 @@ int epggrab_mux_period ( dvb_mux_t *dm ) return period; } -dvb_mux_t *epggrab_mux_next ( th_dvb_adapter_t *tda ) +dvb_mux_t *epggrab_mux_next ( dvb_network_t *dn ) { time_t now; epggrab_ota_mux_t *ota; @@ -91,7 +91,7 @@ dvb_mux_t *epggrab_mux_next ( th_dvb_adapter_t *tda ) TAILQ_FOREACH(ota, &ota_mux_all, glob_link) { if (ota->interval + ota->completed > now) return NULL; if (!ota->is_reg) return NULL; - if (ota->dm->dm_tdmi->tdmi_adapter == tda) break; + if (ota->dm->dm_dn == dn) break; } return ota ? ota->dm : NULL; } @@ -373,9 +373,9 @@ void epggrab_ota_complete ( epggrab_ota_mux_t *ota ) /* All complete (bring timer forward) */ if (!ota) { - th_dvb_mux_instance_t *tdmi = dm->dm_tdmi; - gtimer_arm(&tdmi->tdmi_adapter->tda_mux_scanner_timer, - dvb_adapter_mux_scanner, tdmi->tdmi_adapter, 20); + dvb_network_t *dn = dm->dm_dn; + gtimer_arm(&dn->dn_mux_scanner_timer, + dvb_network_mux_scanner, dn, 20); } } } From 963a0502d3ab637821fe1c7406ab07bdf9e82417 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20=C3=96man?= Date: Fri, 7 Dec 2012 13:43:32 +0100 Subject: [PATCH 17/31] Moved almost everything out from tdmi --- src/capmt.c | 4 +- src/dvb/dvb.h | 97 +++++---- src/dvb/dvb_adapter.c | 99 +-------- src/dvb/dvb_fe.c | 37 ++-- src/dvb/dvb_input_filtered.c | 4 +- src/dvb/dvb_multiplex.c | 394 ++++++++++++++--------------------- src/dvb/dvb_network.c | 89 +++++++- src/dvb/dvb_preconf.c | 12 +- src/dvb/dvb_preconf.h | 2 +- src/dvb/dvb_service.c | 181 +++++++--------- src/dvb/dvb_support.c | 5 +- src/dvb/dvb_support.h | 2 +- src/dvb/dvb_tables.c | 51 ++--- src/epggrab/module/eit.c | 13 +- src/epggrab/otamux.c | 9 +- src/iptv_input.c | 44 ++-- src/rawtsinput.c | 14 +- src/service.c | 164 +++++---------- src/service.h | 51 +++-- src/serviceprobe.c | 7 +- src/settings.c | 63 ++++-- src/settings.h | 2 + src/subscriptions.c | 10 +- src/tvheadend.h | 1 + src/v4l.c | 6 +- src/webui/extjs.c | 4 +- src/webui/extjs_dvb.c | 11 +- src/webui/statedump.c | 14 +- src/webui/webui.c | 4 +- 29 files changed, 624 insertions(+), 770 deletions(-) diff --git a/src/capmt.c b/src/capmt.c index 1bfc0300..1565309a 100644 --- a/src/capmt.c +++ b/src/capmt.c @@ -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; diff --git a/src/dvb/dvb.h b/src/dvb/dvb.h index c1bc22f9..4c4594b2 100644 --- a/src/dvb/dvb.h +++ b/src/dvb/dvb.h @@ -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); diff --git a/src/dvb/dvb_adapter.c b/src/dvb/dvb_adapter.c index eeb9b749..b7029fb3 100644 --- a/src/dvb/dvb_adapter.c +++ b/src/dvb/dvb_adapter.c @@ -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)); diff --git a/src/dvb/dvb_fe.c b/src/dvb/dvb_fe.c index 09d52098..dafca714 100644 --- a/src/dvb/dvb_fe.c +++ b/src/dvb/dvb_fe.c @@ -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; diff --git a/src/dvb/dvb_input_filtered.c b/src/dvb/dvb_input_filtered.c index 2943e4e1..68abf7bf 100644 --- a/src/dvb/dvb_input_filtered.c +++ b/src/dvb/dvb_input_filtered.c @@ -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; diff --git a/src/dvb/dvb_multiplex.c b/src/dvb/dvb_multiplex.c index c3e1d096..69424837 100644 --- a/src/dvb/dvb_multiplex.c +++ b/src/dvb/dvb_multiplex.c @@ -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; } diff --git a/src/dvb/dvb_network.c b/src/dvb/dvb_network.c index 9dd2239a..ed140fdb 100644 --- a/src/dvb/dvb_network.c +++ b/src/dvb/dvb_network.c @@ -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 /** diff --git a/src/dvb/dvb_preconf.c b/src/dvb/dvb_preconf.c index 1dfb5234..bbcd3deb 100644 --- a/src/dvb/dvb_preconf.c +++ b/src/dvb/dvb_preconf.c @@ -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 = ®ions_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; } } diff --git a/src/dvb/dvb_preconf.h b/src/dvb/dvb_preconf.h index a76f3a7e..a3c14da3 100644 --- a/src/dvb/dvb_preconf.h +++ b/src/dvb/dvb_preconf.h @@ -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 */ diff --git a/src/dvb/dvb_service.c b/src/dvb/dvb_service.c index 2399e50d..e771d898 100644 --- a/src/dvb/dvb_service.c +++ b/src/dvb/dvb_service.c @@ -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); -} diff --git a/src/dvb/dvb_support.c b/src/dvb/dvb_support.c index 91a9bb2a..c40cc755 100644 --- a/src/dvb/dvb_support.c +++ b/src/dvb/dvb_support.c @@ -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, diff --git a/src/dvb/dvb_support.h b/src/dvb/dvb_support.h index 3d6aabe7..ab5ece28 100644 --- a/src/dvb/dvb_support.h +++ b/src/dvb/dvb_support.h @@ -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); diff --git a/src/dvb/dvb_tables.c b/src/dvb/dvb_tables.c index ff25f37d..6cd5e451 100644 --- a/src/dvb/dvb_tables.c +++ b/src/dvb/dvb_tables.c @@ -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); } diff --git a/src/epggrab/module/eit.c b/src/epggrab/module/eit.c index a2663af6..f19c447a 100644 --- a/src/epggrab/module/eit.c +++ b/src/epggrab/module/eit.c @@ -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 */ diff --git a/src/epggrab/otamux.c b/src/epggrab/otamux.c index 93e4431d..b02e17fc 100644 --- a/src/epggrab/otamux.c +++ b/src/epggrab/otamux.c @@ -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 || diff --git a/src/iptv_input.c b/src/iptv_input.c index 314e5b59..8705e71d 100644 --- a/src/iptv_input.c +++ b/src/iptv_input.c @@ -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; diff --git a/src/rawtsinput.c b/src/rawtsinput.c index bd4a5098..256d476d 100644 --- a/src/rawtsinput.c +++ b/src/rawtsinput.c @@ -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); diff --git a/src/service.c b/src/service.c index 6548f104..90b8a4d7 100644 --- a/src/service.c +++ b/src/service.c @@ -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); diff --git a/src/service.h b/src/service.h index 11e39b5d..e63dfbff 100644 --- a/src/service.h +++ b/src/service.h @@ -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); diff --git a/src/serviceprobe.c b/src/serviceprobe.c index 62dcc211..2bdb5048 100644 --- a/src/serviceprobe.c +++ b/src/serviceprobe.c @@ -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); diff --git a/src/settings.c b/src/settings.c index 8f0de39b..8a98cad6 100644 --- a/src/settings.c +++ b/src/settings.c @@ -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; +} + /** * */ diff --git a/src/settings.h b/src/settings.h index 7f0bb8d0..2ab52083 100644 --- a/src/settings.h +++ b/src/settings.h @@ -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); diff --git a/src/subscriptions.c b/src/subscriptions.c index 2f56825b..e7026080 100644 --- a/src/subscriptions.c +++ b/src/subscriptions.c @@ -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 ?: "", si.si_network ?: "", si.si_mux ?: "", si.si_provider ?: "", - si.si_service ?: "", - s->ths_service->s_quality_index(s->ths_service)); + si.si_service ?: ""); 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 ?: "", si.si_network ?: "", si.si_mux ?: "", si.si_provider ?: "", - si.si_service ?: "", - t->s_quality_index(t)); + si.si_service ?: ""); service_source_info_free(&si); subscription_link_service(s, t); diff --git a/src/tvheadend.h b/src/tvheadend.h index e117f6ab..e401d582 100644 --- a/src/tvheadend.h +++ b/src/tvheadend.h @@ -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) { diff --git a/src/v4l.c b/src/v4l.c index a7b86075..9ad9a5c6 100644 --- a/src/v4l.c +++ b/src/v4l.c @@ -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; diff --git a/src/webui/extjs.c b/src/webui/extjs.c index df1ce74e..98d12426 100644 --- a/src/webui/extjs.c +++ b/src/webui/extjs.c @@ -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 diff --git a/src/webui/extjs_dvb.c b/src/webui/extjs_dvb.c index 211602f1..c6aebc41 100644 --- a/src/webui/extjs_dvb.c +++ b/src/webui/extjs_dvb.c @@ -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 diff --git a/src/webui/statedump.c b/src/webui/statedump.c index ff7e4ef9..96df49a8 100644 --- a/src/webui/statedump.c +++ b/src/webui/statedump.c @@ -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 diff --git a/src/webui/webui.c b/src/webui/webui.c index 6e5ab39c..f72a865d 100644 --- a/src/webui/webui.c +++ b/src/webui/webui.c @@ -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) { From fef5755fe7b8e2fe327e45a34cce221e994eba87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20=C3=96man?= Date: Thu, 17 Jan 2013 16:21:55 +0100 Subject: [PATCH 18/31] 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 --- Makefile | 1 + src/dvb/dvb.c | 1 + src/dvb/dvb.h | 49 ++++-- src/dvb/dvb_adapter.c | 17 +- src/dvb/dvb_fe.c | 188 ++++++++++++++++----- src/dvb/dvb_input_filtered.c | 4 +- src/dvb/dvb_multiplex.c | 158 ++++++++++++++---- src/dvb/dvb_network.c | 241 ++++++++++++++++++++------- src/dvb/dvb_service.c | 62 +++---- src/dvb/dvb_tables.c | 8 +- src/epggrab/otamux.c | 3 +- src/filebundle.c | 2 +- src/idnode.c | 158 ++++++++++++++++++ src/idnode.h | 29 ++++ src/iptv_input.c | 30 ++-- src/main.c | 4 + src/service.c | 44 ++--- src/service.h | 12 +- src/streaming.c | 4 +- src/tvheadend.h | 2 +- src/webui/extjs.c | 4 +- src/webui/extjs_dvb.c | 61 +++---- src/webui/static/app/dvb_networks.js | 25 +++ src/webui/webui.c | 2 +- 24 files changed, 825 insertions(+), 284 deletions(-) create mode 100644 src/idnode.c create mode 100644 src/idnode.h create mode 100644 src/webui/static/app/dvb_networks.js diff --git a/Makefile b/Makefile index a4e63011..37145763 100644 --- a/Makefile +++ b/Makefile @@ -63,6 +63,7 @@ endif # Core # SRCS = src/main.c \ + src/idnode.c \ src/utils.c \ src/wrappers.c \ src/version.c \ diff --git a/src/dvb/dvb.c b/src/dvb/dvb.c index 9e3775b3..44e905d5 100644 --- a/src/dvb/dvb.c +++ b/src/dvb/dvb.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); } diff --git a/src/dvb/dvb.h b/src/dvb/dvb.h index 4c4594b2..aa08aff0 100644 --- a/src/dvb/dvb.h +++ b/src/dvb/dvb.h @@ -24,6 +24,7 @@ #include #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); /** diff --git a/src/dvb/dvb_adapter.c b/src/dvb/dvb_adapter.c index b7029fb3..d43938db 100644 --- a/src/dvb/dvb_adapter.c +++ b/src/dvb/dvb_adapter.c @@ -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); diff --git a/src/dvb/dvb_fe.c b/src/dvb/dvb_fe.c index dafca714..ba05ed4f 100644 --- a/src/dvb/dvb_fe.c +++ b/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; diff --git a/src/dvb/dvb_input_filtered.c b/src/dvb/dvb_input_filtered.c index 68abf7bf..9040dcd7 100644 --- a/src/dvb/dvb_input_filtered.c +++ b/src/dvb/dvb_input_filtered.c @@ -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; diff --git a/src/dvb/dvb_multiplex.c b/src/dvb/dvb_multiplex.c index 69424837..49fe59f3 100644 --- a/src/dvb/dvb_multiplex.c +++ b/src/dvb/dvb_multiplex.c @@ -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; +} diff --git a/src/dvb/dvb_network.c b/src/dvb/dvb_network.c index ed140fdb..4bc6d4ad 100644 --- a/src/dvb/dvb_network.c +++ b/src/dvb/dvb_network.c @@ -16,36 +16,129 @@ * along with this program. If not, see . */ +#include + #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; } diff --git a/src/dvb/dvb_service.c b/src/dvb/dvb_service.c index e771d898..109312e2 100644 --- a/src/dvb/dvb_service.c +++ b/src/dvb/dvb_service.c @@ -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 ?: "", 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; } diff --git a/src/dvb/dvb_tables.c b/src/dvb/dvb_tables.c index 6cd5e451..3537cb51 100644 --- a/src/dvb/dvb_tables.c +++ b/src/dvb/dvb_tables.c @@ -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); } diff --git a/src/epggrab/otamux.c b/src/epggrab/otamux.c index b02e17fc..85490585 100644 --- a/src/epggrab/otamux.c +++ b/src/epggrab/otamux.c @@ -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 } } diff --git a/src/filebundle.c b/src/filebundle.c index 82450a37..d2b74515 100644 --- a/src/filebundle.c +++ b/src/filebundle.c @@ -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); diff --git a/src/idnode.c b/src/idnode.c new file mode 100644 index 00000000..58b3bbd4 --- /dev/null +++ b/src/idnode.c @@ -0,0 +1,158 @@ +#include +#include +#include +#include +#include + +#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); +} diff --git a/src/idnode.h b/src/idnode.h new file mode 100644 index 00000000..a49b4382 --- /dev/null +++ b/src/idnode.h @@ -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); diff --git a/src/iptv_input.c b/src/iptv_input.c index 8705e71d..5abc4ef3 100644 --- a/src/iptv_input.c +++ b/src/iptv_input.c @@ -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; } diff --git a/src/main.c b/src/main.c index 580a151c..5e93b94e 100644 --- a/src/main.c +++ b/src/main.c @@ -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 diff --git a/src/service.c b/src/service.c index 90b8a4d7..c625148d 100644 --- a/src/service.c +++ b/src/service.c @@ -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); +} diff --git a/src/service.h b/src/service.h index e63dfbff..294ef695 100644 --- a/src/service.h +++ b/src/service.h @@ -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 */ diff --git a/src/streaming.c b/src/streaming.c index bf1614f8..7a490f53 100755 --- a/src/streaming.c +++ b/src/streaming.c @@ -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: diff --git a/src/tvheadend.h b/src/tvheadend.h index e401d582..6fddae3b 100644 --- a/src/tvheadend.h +++ b/src/tvheadend.h @@ -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 diff --git a/src/webui/extjs.c b/src/webui/extjs.c index 98d12426..841840b8 100644 --- a/src/webui/extjs.c +++ b/src/webui/extjs.c @@ -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 diff --git a/src/webui/extjs_dvb.c b/src/webui/extjs_dvb.c index c6aebc41..f321200a 100644 --- a/src/webui/extjs_dvb.c +++ b/src/webui/extjs_dvb.c @@ -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); diff --git a/src/webui/static/app/dvb_networks.js b/src/webui/static/app/dvb_networks.js new file mode 100644 index 00000000..44b68687 --- /dev/null +++ b/src/webui/static/app/dvb_networks.js @@ -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; +} diff --git a/src/webui/webui.c b/src/webui/webui.c index f72a865d..be97063f 100644 --- a/src/webui/webui.c +++ b/src/webui/webui.c @@ -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); From 2cd41e90e55f1edf8fe89fbe3a6f601e9c32a31a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20=C3=96man?= Date: Thu, 31 Jan 2013 09:32:38 +0100 Subject: [PATCH 19/31] dvbreorg: Various refactoring --- src/dvb/dvb.h | 9 +- src/dvb/dvb_fe.c | 179 +++----------------------------------- src/dvb/dvb_multiplex.c | 187 ++++++++++++++++++++++++++++++++++++---- src/dvb/dvb_network.c | 2 +- src/dvb/dvb_service.c | 16 ++-- src/dvb/dvb_support.c | 67 +++++++------- src/dvb/dvb_support.h | 5 +- src/v4l.c | 15 +--- src/webui/extjs_v4l.c | 2 +- 9 files changed, 231 insertions(+), 251 deletions(-) diff --git a/src/dvb/dvb.h b/src/dvb/dvb.h index aa08aff0..9b528554 100644 --- a/src/dvb/dvb.h +++ b/src/dvb/dvb.h @@ -450,6 +450,8 @@ dvb_mux_t *dvb_mux_create(dvb_network_t *tda, const char *logprefix, int enabled, int initialscan, const char *uuid); +int dvb_mux_tune(dvb_mux_t *dm, const char *reason, int weight); + void dvb_mux_set_networkname(dvb_mux_t *dm, const char *name); void dvb_mux_set_tsid(dvb_mux_t *dm, uint16_t tsid); @@ -490,10 +492,8 @@ dvb_mux_t *dvb_mux_find(dvb_network_t *dn, const char *netname, uint16_t onid, void dvb_mux_initial_scan_done(dvb_mux_t *dm); -/** - * DVB Transport (aka DVB service) - */ -void dvb_tdmi_destroy(th_dvb_mux_instance_t *tdmi); +int dvb_fe_tune_tdmi(th_dvb_mux_instance_t *tdmi); + /** * DVB Transport (aka DVB service) @@ -521,7 +521,6 @@ void dvb_service_notify_by_adapter(th_dvb_adapter_t *tda); /** * DVB Frontend */ -int dvb_fe_tune(dvb_mux_t *dm, const char *reason, int weight); //void dvb_fe_stop(th_dvb_adapter_t *tda, int retune); diff --git a/src/dvb/dvb_fe.c b/src/dvb/dvb_fe.c index ba05ed4f..a01fb598 100644 --- a/src/dvb/dvb_fe.c +++ b/src/dvb/dvb_fe.c @@ -92,7 +92,6 @@ dvb_fe_monitor(void *aux) fe_status_t fe_status; int status, v, vv, i, fec, q; th_dvb_mux_instance_t *tdmi = tda->tda_current_tdmi; - char buf[50]; signal_status_t sigstat; streaming_message_t sm; struct service *t; @@ -191,10 +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->tdmi_mux); tvhlog(LOG_DEBUG, "dvb", "\"%s\" on adapter \"%s\", status changed to %s", - buf, tda->tda_displayname, dvb_mux_status(tdmi)); + dvb_mux_nicename(tdmi->tdmi_mux), tda->tda_displayname, + dvb_mux_status(tdmi)); notify = 1; } @@ -385,147 +384,23 @@ dvb_fe_tune_s2(th_dvb_adapter_t *tda, 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, int weight) +dvb_fe_tune_tdmi(th_dvb_mux_instance_t *tdmi) { - dvb_network_t *dn = dm->dm_dn; - + th_dvb_adapter_t *tda = tdmi->tdmi_adapter; + const dvb_mux_t *dm = tdmi->tdmi_mux; // 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; + char buf[256]; dvb_adapter_start(tda); assert(tda->tda_current_tdmi == NULL); - free(tda->tda_tune_reason); - tda->tda_tune_reason = strdup(reason); - tdmi->tdmi_weight = weight; if(tda->tda_fe_type == FE_QPSK) { @@ -574,52 +449,26 @@ dvb_fe_tune(dvb_mux_t *dm, const char *reason, int weight) tvhlog(LOG_ERR, "dvb", "diseqc setup failed %d\n", r); } - dvb_mux_nicename(buf, sizeof(buf), tdmi->tdmi_mux); - tda->tda_fe_monitor_hold = 4; - #if DVB_API_VERSION >= 5 if (tda->tda_fe_type == FE_QPSK) { tvhlog(LOG_DEBUG, "dvb", "\"%s\" tuning via s2api to \"%s\" (%d, %d Baud, " - "%s, %s, %s) for %s", tda->tda_rootpath, buf, p->frequency, p->u.qpsk.symbol_rate, - dvb_mux_fec2str(p->u.qpsk.fec_inner), dvb_mux_delsys2str(dmc.dmc_fe_delsys), - dvb_mux_qam2str(dmc.dmc_fe_modulation), reason); - + "%s, %s, %s)", tda->tda_rootpath, buf, p->frequency, p->u.qpsk.symbol_rate, + dvb_mux_fec2str(p->u.qpsk.fec_inner), dvb_mux_delsys2str(dmc.dmc_fe_delsys), + dvb_mux_qam2str(dmc.dmc_fe_modulation)); r = dvb_fe_tune_s2(tda, &dmc); } else #endif { - tvhlog(LOG_DEBUG, "dvb", "\"%s\" tuning to \"%s\" (%s) fd:%d", tda->tda_rootpath, buf, reason, tda->tda_fe_fd); + tvhlog(LOG_DEBUG, "dvb", "\"%s\" tuning to \"%s\"", + tda->tda_rootpath, dvb_mux_nicename(dm)); r = ioctl(tda->tda_fe_fd, FE_SET_FRONTEND, p); } - if(r != 0) { - tvhlog(LOG_ERR, "dvb", "\"%s\" tuning to \"%s\"" - " -- Front configuration failed -- %s, frequency: %u", - tda->tda_rootpath, buf, strerror(errno), p->frequency); - /* Mark as bad */ - tdmi->tdmi_tune_failed = 1; - goto retry; - } + if(!r) + gtimer_arm(&tda->tda_fe_monitor_timer, dvb_fe_monitor, tda, 1); - 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(dm); - epggrab_mux_start(dm); - - dvb_adapter_notify(tda); - return 0; + return r; } diff --git a/src/dvb/dvb_multiplex.c b/src/dvb/dvb_multiplex.c index 49fe59f3..00b54484 100644 --- a/src/dvb/dvb_multiplex.c +++ b/src/dvb/dvb_multiplex.c @@ -218,12 +218,10 @@ dvb_mux_create(dvb_network_t *dn, const struct dvb_mux_conf *dmc, } if(save) { - 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); + tvhlog(LOG_DEBUG, "dvb", + "Configuration for mux \"%s\" updated by %s%s", + dvb_mux_nicename(dm), source, buf2); dvb_mux_notify(dm); } @@ -255,9 +253,8 @@ dvb_mux_create(dvb_network_t *dn, const struct dvb_mux_conf *dmc, memcpy(&dm->dm_conf, dmc, sizeof(struct dvb_mux_conf)); if(source != NULL) { - char buf[128]; - dvb_mux_nicename(buf, sizeof(buf), dm); - tvhlog(LOG_NOTICE, "dvb", "New mux \"%s\" created by %s", buf, source); + tvhlog(LOG_NOTICE, "dvb", "New mux \"%s\" created by %s", + dvb_mux_nicename(dm), source); dvb_mux_save(dm); } @@ -276,7 +273,7 @@ dvb_mux_create(dvb_network_t *dn, const struct dvb_mux_conf *dmc, /** * */ -void +static void dvb_tdmi_destroy(th_dvb_mux_instance_t *tdmi) { LIST_REMOVE(tdmi, tdmi_mux_link); @@ -954,8 +951,7 @@ dvb_mux_build_msg(dvb_mux_t *dm) htsmsg_add_u32(m, "enabled", dm->dm_enabled); htsmsg_add_str(m, "network", dm->dm_network_name ?: ""); - dvb_mux_nicefreq(buf, sizeof(buf), dm); - htsmsg_add_str(m, "freq", buf); + htsmsg_add_str(m, "freq", dvb_mux_nicefreq(dm)); dvb_mux_modulation(buf, sizeof(buf), dm); htsmsg_add_str(m, "mod", buf); @@ -1233,7 +1229,7 @@ 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", 99999); + dvb_mux_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); @@ -1254,11 +1250,7 @@ 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); + htsmsg_add_str(m, "text", dvb_mux_nicename(dm)); return m; } @@ -1295,3 +1287,164 @@ dvb_mux_get_childs(struct idnode *self) v[cnt] = NULL; return v; } + + + +/** + * 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; + tvhlog(LOG_DEBUG, "dvb", "Initial scan timed out for \"%s\"", + dvb_mux_nicename(dm)); + + dvb_mux_initial_scan_done(dm); +} + + +/** + * + */ +int +dvb_mux_tune(dvb_mux_t *dm, const char *reason, int weight) +{ + dvb_network_t *dn = dm->dm_dn; + th_dvb_mux_instance_t *tdmi; + 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; + + } + + tdmi->tdmi_weight = weight; + + th_dvb_adapter_t *tda = tdmi->tdmi_adapter; + + free(tda->tda_tune_reason); + tda->tda_tune_reason = strdup(reason); + + r = dvb_fe_tune_tdmi(tdmi); + + if(r != 0) { + tvhlog(LOG_ERR, "dvb", "\"%s\" tuning to \"%s\"" + " -- Front configuration failed -- %s", + tda->tda_rootpath, dvb_mux_nicename(dm), strerror(errno)); + + /* Mark as bad */ + tdmi->tdmi_tune_failed = 1; + 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); + } + + dvb_table_add_default(dm); + epggrab_mux_start(dm); + + dvb_adapter_notify(tda); + return 0; +} diff --git a/src/dvb/dvb_network.c b/src/dvb/dvb_network.c index 4bc6d4ad..c0818446 100644 --- a/src/dvb/dvb_network.c +++ b/src/dvb/dvb_network.c @@ -235,7 +235,7 @@ dvb_network_initial_scan(void *aux) 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)) + if(dvb_mux_tune(dm, "initial scan", 1)) break; assert(dm->dm_scan_status == DM_SCAN_CURRENT); } diff --git a/src/dvb/dvb_service.c b/src/dvb/dvb_service.c index 109312e2..98d14650 100644 --- a/src/dvb/dvb_service.c +++ b/src/dvb/dvb_service.c @@ -276,7 +276,6 @@ static void dvb_service_setsourceinfo(service_t *t, struct source_info *si) { dvb_mux_t *dm = t->s_dvb_mux; - char buf[100]; memset(si, 0, sizeof(struct source_info)); @@ -287,8 +286,7 @@ dvb_service_setsourceinfo(service_t *t, struct source_info *si) if(dm->dm_network_name != NULL) si->si_network = strdup(dm->dm_network_name); - dvb_mux_nicename(buf, sizeof(buf), dm); - si->si_mux = strdup(buf); + si->si_mux = strdup(dvb_mux_nicename(dm)); if(t->s_provider != NULL) si->si_provider = strdup(t->s_provider); @@ -364,7 +362,6 @@ dvb_service_find2(dvb_mux_t *dm, uint16_t sid, int pmt_pid, const char *uuid, int *save) { service_t *t; - char buf[200]; lock_assert(&global_lock); @@ -376,8 +373,8 @@ dvb_service_find2(dvb_mux_t *dm, uint16_t sid, int pmt_pid, if(pmt_pid == 0) return NULL; - dvb_mux_nicename(buf, sizeof(buf), dm); - tvhlog(LOG_DEBUG, "dvb", "Add service \"0x%x\" on \"%s\"", sid, buf); + tvhlog(LOG_DEBUG, "dvb", "Add service \"0x%x\" on \"%s\"", sid, + dvb_mux_nicename(dm)); t = service_create(uuid, S_MPEG_TS); if (save) *save = 1; @@ -396,9 +393,9 @@ dvb_service_find2(dvb_mux_t *dm, uint16_t sid, int pmt_pid, t->s_dvb_mux = dm; LIST_INSERT_HEAD(&dm->dm_services, t, s_group_link); - pthread_mutex_lock(&t->s_stream_mutex); + pthread_mutex_lock(&t->s_stream_mutex); service_make_nicename(t); - pthread_mutex_unlock(&t->s_stream_mutex); + pthread_mutex_unlock(&t->s_stream_mutex); return t; } @@ -434,8 +431,7 @@ dvb_service_serialize(service_t *s, int full) htsmsg_add_str(m, "network", dm->dm_network_name ?: ""); - dvb_mux_nicefreq(buf, sizeof(buf), dm); - htsmsg_add_str(m, "mux", buf); + htsmsg_add_str(m, "mux", dvb_mux_nicefreq(dm)); if(s->s_ch != NULL) htsmsg_add_str(m, "channelname", s->s_ch->ch_name); diff --git a/src/dvb/dvb_support.c b/src/dvb/dvb_support.c index c40cc755..fe994229 100644 --- a/src/dvb/dvb_support.c +++ b/src/dvb/dvb_support.c @@ -444,61 +444,54 @@ dvb_adapter_find_by_identifier(const char *identifier) /** * */ -static const char * -nicenum(char *x, size_t siz, unsigned int v) +static void +nicenum(char *x, size_t siz, unsigned int v, const char *postfix) { if(v < 1000) - snprintf(x, siz, "%d", v); + snprintf(x, siz, "%d%s", v, postfix); else if(v < 1000000) - snprintf(x, siz, "%d,%03d", v / 1000, v % 1000); + snprintf(x, siz, "%d,%03d%s", v / 1000, v % 1000, postfix); else if(v < 1000000000) - snprintf(x, siz, "%d,%03d,%03d", - v / 1000000, (v % 1000000) / 1000, v % 1000); - else - snprintf(x, siz, "%d,%03d,%03d,%03d", + snprintf(x, siz, "%d,%03d,%03d%s", + v / 1000000, (v % 1000000) / 1000, v % 1000, postfix); + else + snprintf(x, siz, "%d,%03d,%03d,%03d%s", v / 1000000000, (v % 1000000000) / 1000000, - (v % 1000000) / 1000, v % 1000); - return x; + (v % 1000000) / 1000, v % 1000, postfix); } /** - * + * */ -void -dvb_mux_nicefreq(char *buf, size_t size, const dvb_mux_t *dm) +const char * +dvb_mux_nicefreq(const dvb_mux_t *dm) { - char freq[50]; - - if(dm->dm_dn->dn_fe_type == FE_QPSK) { - nicenum(freq, sizeof(freq), dm->dm_conf.dmc_fe_params.frequency); - snprintf(buf, size, "%s kHz", freq); - } else { - nicenum(freq, sizeof(freq), - dm->dm_conf.dmc_fe_params.frequency / 1000); - snprintf(buf, size, "%s kHz", freq); - } + static char ret[100]; + int f = dm->dm_conf.dmc_fe_params.frequency; + nicenum(ret, sizeof(ret), dm->dm_dn->dn_fe_type == FE_QPSK ? f : f / 1000, + " kHz"); + return ret; } /** - * + * */ -void -dvb_mux_nicename(char *buf, size_t size, dvb_mux_t *dm) +const char * +dvb_mux_nicename(const dvb_mux_t *dm) { - char freq[50]; + static char ret[100]; const char *n = dm->dm_network_name; - 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, - dvb_polarisation_to_str_long(dm->dm_conf.dmc_polarisation)); - - } else { - nicenum(freq, sizeof(freq), dm->dm_conf.dmc_fe_params.frequency / 1000); - snprintf(buf, size, "%s%s%s kHz", n?:"", n ? ": ":"", freq); - } + snprintf(ret, sizeof(ret), "%s%s%s%s%s", + n ?: "", + n ? ": " : "", + dvb_mux_nicefreq(dm), + dm->dm_dn->dn_fe_type == FE_QPSK ? " " : "", + dm->dm_dn->dn_fe_type == FE_QPSK ? + dvb_polarisation_to_str_long(dm->dm_conf.dmc_polarisation) : + ""); + return ret; } diff --git a/src/dvb/dvb_support.h b/src/dvb/dvb_support.h index ab5ece28..762eaecb 100644 --- a/src/dvb/dvb_support.h +++ b/src/dvb/dvb_support.h @@ -79,10 +79,11 @@ 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, 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); + +const char *dvb_mux_nicefreq(const dvb_mux_t *dm); +const char *dvb_mux_nicename(const dvb_mux_t *dm); void atsc_utf16_to_utf8(uint8_t *src, int len, char *buf, int buflen); diff --git a/src/v4l.c b/src/v4l.c index 9ad9a5c6..6fae6750 100644 --- a/src/v4l.c +++ b/src/v4l.c @@ -289,22 +289,12 @@ 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_uuid); + va->va_identifier, idnode_uuid_as_str(&t->s_id)); htsmsg_destroy(m); } -/** - * - */ -static int -v4l_service_quality(service_t *t) -{ - return 100; -} - - /** * */ @@ -349,7 +339,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_uuid, id)) + if(!strcmp(idnode_uuid_as_str(&t->s_id), id)) return t; } @@ -371,7 +361,6 @@ v4l_service_find(v4l_adapter_t *va, const char *id, int create) t->s_stop_feed = v4l_service_stop; t->s_config_save = v4l_service_save; t->s_setsourceinfo = v4l_service_setsourceinfo; - t->s_quality_index = v4l_service_quality; t->s_grace_period = v4l_grace_period; t->s_iptv_fd = -1; t->s_v4l_adapter = va; diff --git a/src/webui/extjs_v4l.c b/src/webui/extjs_v4l.c index f7e02630..ad1d4833 100644 --- a/src/webui/extjs_v4l.c +++ b/src/webui/extjs_v4l.c @@ -170,7 +170,7 @@ build_record_v4l(service_t *t) { htsmsg_t *r = htsmsg_create_map(); - htsmsg_add_str(r, "id", t->s_identifier); + // htsmsg_add_str(r, "id", t->s_identifier); // XXX(dvbreorg) htsmsg_add_str(r, "channelname", t->s_ch ? t->s_ch->ch_name : ""); htsmsg_add_u32(r, "frequency", t->s_v4l_frequency); From 6f6f422bdff913d4cf2eea0c1eb8074cc8b67c30 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20=C3=96man?= Date: Wed, 6 Feb 2013 11:34:49 +0100 Subject: [PATCH 20/31] dvbreorg: Service subscription now possible --- src/dvb/dvb.h | 15 ++- src/dvb/dvb_adapter.c | 107 +------------------- src/dvb/dvb_fe.c | 70 ++++++++------ src/dvb/dvb_multiplex.c | 127 ++++++++++++------------ src/dvb/dvb_service.c | 114 ++++++++++++---------- src/iptv_input.c | 2 +- src/service.c | 140 ++++++++++++++++++++++----- src/service.h | 58 ++++++----- src/subscriptions.c | 31 +++--- src/subscriptions.h | 8 ++ src/v4l.c | 2 +- src/webui/extjs_dvb.c | 14 +-- src/webui/static/app/dvb.js | 3 + src/webui/static/app/dvb_networks.js | 7 +- 14 files changed, 377 insertions(+), 321 deletions(-) diff --git a/src/dvb/dvb.h b/src/dvb/dvb.h index 9b528554..cfb42e1a 100644 --- a/src/dvb/dvb.h +++ b/src/dvb/dvb.h @@ -199,8 +199,6 @@ 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; @@ -231,6 +229,9 @@ typedef struct dvb_table_feed { typedef struct th_dvb_adapter { + int tda_instance; + + TAILQ_ENTRY(th_dvb_adapter) tda_global_link; dvb_network_t *tda_dn; @@ -403,8 +404,6 @@ void dvb_adapter_set_full_mux_rx(th_dvb_adapter_t *tda, int r); void dvb_adapter_clone(th_dvb_adapter_t *dst, th_dvb_adapter_t *src); -void dvb_adapter_clean(th_dvb_adapter_t *tda); - int dvb_adapter_destroy(th_dvb_adapter_t *tda); void dvb_adapter_notify(th_dvb_adapter_t *tda); @@ -490,9 +489,15 @@ dvb_mux_t *dvb_mux_find(dvb_network_t *dn, const char *netname, uint16_t onid, uint16_t tsid, int enabled); +void dvb_mux_stop(th_dvb_mux_instance_t *tdmi); + void dvb_mux_initial_scan_done(dvb_mux_t *dm); -int dvb_fe_tune_tdmi(th_dvb_mux_instance_t *tdmi); +int dvb_fe_tune_tdmi(th_dvb_mux_instance_t *tdmi, const char *reason); + +void dvb_create_tdmis(dvb_mux_t *dm); + +int tdmi_current_weight(const th_dvb_mux_instance_t *tdmi); /** diff --git a/src/dvb/dvb_adapter.c b/src/dvb/dvb_adapter.c index d43938db..03cc15a2 100644 --- a/src/dvb/dvb_adapter.c +++ b/src/dvb/dvb_adapter.c @@ -47,7 +47,7 @@ struct th_dvb_adapter_queue dvb_adapters; static void *dvb_adapter_input_dvr(void *aux); - +static int dvb_adapter_instance_generator; /** * @@ -59,6 +59,7 @@ tda_alloc(void) pthread_mutex_init(&tda->tda_delivery_mutex, NULL); TAILQ_INIT(&tda->tda_satconfs); streaming_pad_init(&tda->tda_streaming_pad); + tda->tda_instance = ++dvb_adapter_instance_generator; return tda; } @@ -631,87 +632,6 @@ dvb_adapter_init(uint32_t adapter_mask, const char *rawfile) } } -#if 0 -/** - * If nobody is subscribing, cycle thru all muxes to get some stats - * and EIT updates - */ -void -dvb_adapter_mux_scanner(void *aux) -{ - th_dvb_adapter_t *tda = aux; - th_dvb_mux_instance_t *tdmi; - - if(tda->tda_rootpath == NULL) - return; // No hardware - - // default period - gtimer_arm(&tda->tda_mux_scanner_timer, dvb_adapter_mux_scanner, tda, 20); - - /* No muxes */ - if(LIST_FIRST(&tda->tda_dn->dn_mux_instances) == NULL) { - dvb_adapter_poweroff(tda); - return; - } - - /* Someone is actively using */ - if(service_compute_weight(&tda->tda_transports) > 0) - return; - - if(tda->tda_mux_current != NULL && - LIST_FIRST(&tda->tda_mux_current->tdmi_subscriptions) != NULL) - return; // Someone is doing full mux dump - - /* Check if we have muxes pending for quickscan, if so, choose them */ - if((tdmi = TAILQ_FIRST(&tda->tda_dn->dn_initial_scan_queue)) != NULL) { - dvb_fe_tune(tdmi, "Initial autoscan"); - return; - } - - /* Check EPG */ - if (tda->tda_dn->dn_mux_epg) { - // timeout anything not complete - epggrab_mux_stop(tda->tda_dn->dn_mux_epg, 1); - tda->tda_dn->dn_mux_epg = NULL; // skip this time - } else { - tda->tda_dn->dn_mux_epg = epggrab_mux_next(tda); - } - - /* EPG */ - if (tda->tda_dn->dn_mux_epg) { - int period = epggrab_mux_period(tda->tda_dn->dn_mux_epg); - if (period > 20) - gtimer_arm(&tda->tda_mux_scanner_timer, - dvb_adapter_mux_scanner, tda, period); - dvb_fe_tune(tda->tda_dn->dn_mux_epg->dm_tdmi, "EPG scan"); - return; - - } - - /* Ensure we stop current mux and power off (if required) */ - if (tda->tda_mux_current) - dvb_fe_stop(tda->tda_mux_current, 0); -} -#endif - -/** - * - */ -void -dvb_adapter_clone(th_dvb_adapter_t *dst, th_dvb_adapter_t *src) -{ -#if 0 - th_dvb_mux_instance_t *tdmi_src, *tdmi_dst; - - lock_assert(&global_lock); - - while((tdmi_dst = LIST_FIRST(&dst->tda_dn->dn_mux_instances)) != NULL) - dvb_mux_destroy(tdmi_dst); - - tda_save(dst); -#endif - abort(); // XXX(dvbreorg) -} /** @@ -746,24 +666,6 @@ dvb_adapter_destroy(th_dvb_adapter_t *tda) #endif -/** - * - */ -void -dvb_adapter_clean(th_dvb_adapter_t *tda) -{ - service_t *t; - - lock_assert(&global_lock); - - while((t = LIST_FIRST(&tda->tda_transports)) != NULL) - /* Flush all subscribers */ - service_remove_subscriber(t, NULL, SM_CODE_SUBSCRIPTION_OVERRIDDEN); -} - - - - /** * */ @@ -921,7 +823,6 @@ dvb_adapter_input_dvr(void *aux) htsmsg_t * dvb_adapter_build_msg(th_dvb_adapter_t *tda) { - char buf[100]; htsmsg_t *m = htsmsg_create_map(); int fdiv; @@ -933,8 +834,8 @@ dvb_adapter_build_msg(th_dvb_adapter_t *tda) 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->tdmi_mux); - htsmsg_add_str(m, "currentMux", buf); + htsmsg_add_str(m, "currentMux", + dvb_mux_nicename(tda->tda_current_tdmi->tdmi_mux)); htsmsg_add_u32(m, "signal", MIN(tdmi->tdmi_signal * 100 / 65535, 100)); htsmsg_add_u32(m, "snr", tdmi->tdmi_snr); diff --git a/src/dvb/dvb_fe.c b/src/dvb/dvb_fe.c index a01fb598..916fe523 100644 --- a/src/dvb/dvb_fe.c +++ b/src/dvb/dvb_fe.c @@ -254,32 +254,6 @@ dvb_fe_monitor(void *aux) } -#if 0 -/** - * Stop the given TDMI - */ -void -dvb_fe_stop(th_dvb_adapter_t *tda, int retune) -{ - lock_assert(&global_lock); - - th_dvb_mux_instance_t *tdmi = tda->tda_current_tdmi; - assert(tdmi != NULL); - dvb_mux_t *dm = tdmi->tdmi_mux; - - dvb_table_flush_all(dm); - - epggrab_mux_stop(dm, 0); - -#if 0 /// XXX(dvbreorg) - if(!retune) { - gtimer_disarm(&tda->tda_fe_monitor_timer); - dvb_adapter_stop(tda); - } -#endif -} -#endif - #if DVB_API_VERSION >= 5 @@ -385,23 +359,42 @@ dvb_fe_tune_s2(th_dvb_adapter_t *tda, dvb_mux_conf_t *dmc) +/** + * + */ int -dvb_fe_tune_tdmi(th_dvb_mux_instance_t *tdmi) +dvb_fe_tune_tdmi(th_dvb_mux_instance_t *tdmi, const char *reason) { th_dvb_adapter_t *tda = tdmi->tdmi_adapter; - const dvb_mux_t *dm = tdmi->tdmi_mux; + dvb_mux_t *dm = tdmi->tdmi_mux; // 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; int r; char buf[256]; + if(tda->tda_current_tdmi != NULL) { + + if(tda->tda_current_tdmi == tdmi) + return 0; // Already currently tuned + + /* + * Adapter tuned to something else. + * But at this stage we're no longer caring about such things. + * That should have been sorted out by our callers. + * So let's just kick it out the current occupant + */ + dvb_mux_stop(tda->tda_current_tdmi); + } + + free(tda->tda_tune_reason); + tda->tda_tune_reason = strdup(reason); + dvb_adapter_start(tda); + // Make sure dvb_mux_stop() did the right thing assert(tda->tda_current_tdmi == NULL); - - if(tda->tda_fe_type == FE_QPSK) { /* DVB-S */ @@ -467,8 +460,23 @@ dvb_fe_tune_tdmi(th_dvb_mux_instance_t *tdmi) } - if(!r) + if(!r) { gtimer_arm(&tda->tda_fe_monitor_timer, dvb_fe_monitor, tda, 1); + tda->tda_current_tdmi = tdmi; + dm->dm_current_tdmi = tdmi; + + dvb_table_add_default(dm); + epggrab_mux_start(dm); + dvb_adapter_notify(tda); + + } else { + + tvhlog(LOG_ERR, "dvb", "\"%s\" tuning to \"%s\"" + " -- Front configuration failed -- %s", + tda->tda_rootpath, dvb_mux_nicename(dm), strerror(errno)); + /* Mark as bad */ + tdmi->tdmi_tune_failed = 1; + } return r; } diff --git a/src/dvb/dvb_multiplex.c b/src/dvb/dvb_multiplex.c index 00b54484..b7f11589 100644 --- a/src/dvb/dvb_multiplex.c +++ b/src/dvb/dvb_multiplex.c @@ -1293,7 +1293,7 @@ dvb_mux_get_childs(struct idnode *self) /** * These are created on the fly */ -static void +void dvb_create_tdmis(dvb_mux_t *dm) { th_dvb_mux_instance_t *tdmi; @@ -1322,36 +1322,64 @@ dvb_create_tdmis(dvb_mux_t *dm) /** * */ -static void +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; + service_t *s; + assert(dm->dm_current_tdmi == tdmi); assert(tda->tda_current_tdmi == tdmi); + lock_assert(&global_lock); + + /* Flush all subscribers */ + while((s = LIST_FIRST(&tda->tda_transports)) != NULL) + service_remove_subscriber(s, NULL, SM_CODE_SUBSCRIPTION_OVERRIDDEN); + dvb_table_flush_all(dm); epggrab_mux_stop(dm, 0); - assert(dm->dm_scan_status == DM_SCAN_DONE); + if(dm->dm_scan_status == DM_SCAN_CURRENT) { + /* + * If we were currently doing initial scan but lost the adapter + * before finishing, put us back on the pending queue + */ + dvb_network_t *dn = dm->dm_dn; + TAILQ_REMOVE(&dn->dn_initial_scan_current_queue, dm, dm_scan_link); + dm->dm_scan_status = DM_SCAN_PENDING; + TAILQ_INSERT_TAIL(&dn->dn_initial_scan_pending_queue, dm, dm_scan_link); + dvb_network_schedule_initial_scan(dn); + } 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) +int +tdmi_current_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; + int w = 0; + th_dvb_adapter_t *tda = tdmi->tdmi_adapter; + const service_t *s; + + + // This max weight of all subscriptions could be kept in the adapter struct + pthread_mutex_lock(&tda->tda_delivery_mutex); + LIST_FOREACH(s, &tda->tda_transports, s_active_link) { + const th_subscription_t *ths; + LIST_FOREACH(ths, &s->s_subscriptions, ths_service_link) + w = MAX(w, ths->ths_weight); + } + pthread_mutex_unlock(&tda->tda_delivery_mutex); + + w = MAX(w, tdmi->tdmi_mux->dm_scan_status == DM_SCAN_CURRENT); + return w; } @@ -1379,61 +1407,44 @@ dvb_mux_tune(dvb_mux_t *dm, const char *reason, int weight) th_dvb_mux_instance_t *tdmi; int r; - assert(dm->dm_current_tdmi == NULL); - lock_assert(&global_lock); - dvb_create_tdmis(dm); + if(dm->dm_current_tdmi == NULL) { - 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; + dvb_create_tdmis(dm); - 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; + while(1) { + // 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; - 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 == NULL) { + // None available, need to strike one out + LIST_FOREACH(tdmi, &dm->dm_tdmis, tdmi_mux_link) { + if(tdmi->tdmi_tune_failed) + continue; - if(tdmi_compute_weight(t2) < weight) { - dvb_mux_stop(t2); - break; + 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_current_weight(t2) < weight) { + break; + } + } + + if(tdmi == NULL) + return SM_CODE_NO_FREE_ADAPTER; } + + r = dvb_fe_tune_tdmi(tdmi, reason); + if(!r) + break; } - - if(tdmi == NULL) - return SM_CODE_NO_FREE_ADAPTER; - } - tdmi->tdmi_weight = weight; - - th_dvb_adapter_t *tda = tdmi->tdmi_adapter; - - free(tda->tda_tune_reason); - tda->tda_tune_reason = strdup(reason); - - r = dvb_fe_tune_tdmi(tdmi); - - if(r != 0) { - tvhlog(LOG_ERR, "dvb", "\"%s\" tuning to \"%s\"" - " -- Front configuration failed -- %s", - tda->tda_rootpath, dvb_mux_nicename(dm), strerror(errno)); - - /* Mark as bad */ - tdmi->tdmi_tune_failed = 1; - 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; @@ -1442,9 +1453,5 @@ dvb_mux_tune(dvb_mux_t *dm, const char *reason, int weight) gtimer_arm(&dm->dm_initial_scan_timeout, dvb_mux_initial_scan_timeout, dm, 10); } - dvb_table_add_default(dm); - epggrab_mux_start(dm); - - dvb_adapter_notify(tda); return 0; } diff --git a/src/dvb/dvb_service.c b/src/dvb/dvb_service.c index 98d14650..8b8e1ffb 100644 --- a/src/dvb/dvb_service.c +++ b/src/dvb/dvb_service.c @@ -55,54 +55,48 @@ static htsmsg_t *dvb_service_serialize(service_t *s, int full); * transports that is subscribing to the adapter */ static int -dvb_service_start(service_t *t, unsigned int weight, int force_start) +dvb_service_start(service_t *s, int instance) { -#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; + int r; + dvb_mux_t *dm = s->s_dvb_mux; + th_dvb_mux_instance_t *tdmi; + + assert(s->s_status == SERVICE_IDLE); lock_assert(&global_lock); - if(tda->tda_rootpath == NULL) - return SM_CODE_NO_HW_ATTACHED; + LIST_FOREACH(tdmi, &dm->dm_tdmis, tdmi_mux_link) + if(tdmi->tdmi_adapter->tda_instance == instance) + break; - if(t->s_dvb_mux_instance && !t->s_dvb_mux_instance->tdmi_enabled) - return SM_CODE_MUX_NOT_ENABLED; /* Mux is disabled */ + assert(tdmi != NULL); // We should always find this instance - /* Check if adapter is idle, or already tuned */ + r = dvb_fe_tune_tdmi(tdmi, "service start"); - if(tdmi != NULL && - (tdmi != t->s_dvb_mux_instance || - tda->tda_hostconnection == HOSTCONNECTION_USB12)) { - - w = service_compute_weight(&tda->tda_transports); - if(w && w >= weight && !force_start) - /* We are outranked by weight, cant use it */ - return SM_CODE_NOT_FREE; - - if(LIST_FIRST(&tdmi->tdmi_subscriptions) != NULL) - return SM_CODE_NOT_FREE; - - dvb_adapter_clean(tda); + if(!r) { + th_dvb_adapter_t *tda = dm->dm_current_tdmi->tdmi_adapter; + pthread_mutex_lock(&tda->tda_delivery_mutex); + LIST_INSERT_HEAD(&tda->tda_transports, s, s_active_link); + pthread_mutex_unlock(&tda->tda_delivery_mutex); + tda->tda_open_service(tda, s); + dvb_table_add_pmt(dm, s->s_pmt_pid); } - pthread_mutex_lock(&tda->tda_delivery_mutex); - - r = dvb_fe_tune(t->s_dvb_mux_instance->tdmi_mux, "Transport start"); - if(!r) - LIST_INSERT_HEAD(&tda->tda_transports, t, s_active_link); - - pthread_mutex_unlock(&tda->tda_delivery_mutex); - - if(!r) - tda->tda_open_service(tda, t); - - dvb_table_add_pmt(t->s_dvb_mux_instance->tdmi_mux, t->s_pmt_pid); - return r; -#endif - return SM_CODE_NO_FREE_ADAPTER; +} + + +/** + * + */ +static th_dvb_adapter_t * +dvb_service_get_tda(service_t *s) +{ + dvb_mux_t *dm = s->s_dvb_mux; + assert(dm->dm_current_tdmi != NULL); + th_dvb_adapter_t *tda = dm->dm_current_tdmi->tdmi_adapter; + assert(tda != NULL); + return tda; } @@ -110,21 +104,18 @@ dvb_service_start(service_t *t, unsigned int weight, int force_start) * */ static void -dvb_service_stop(service_t *t) +dvb_service_stop(service_t *s) { -#if 0 - th_dvb_adapter_t *tda = t->s_dvb_mux_instance->tdmi_adapter; - + th_dvb_adapter_t *tda = dvb_service_get_tda(s); lock_assert(&global_lock); pthread_mutex_lock(&tda->tda_delivery_mutex); - LIST_REMOVE(t, s_active_link); + LIST_REMOVE(s, s_active_link); pthread_mutex_unlock(&tda->tda_delivery_mutex); - tda->tda_close_service(tda, t); + tda->tda_close_service(tda, s); - t->s_status = SERVICE_IDLE; -#endif + s->s_status = SERVICE_IDLE; } @@ -132,14 +123,32 @@ dvb_service_stop(service_t *t) * */ static void -dvb_service_refresh(service_t *t) +dvb_service_refresh(service_t *s) { -#if 0 - th_dvb_adapter_t *tda = t->s_dvb_mux_instance->tdmi_adapter; - + th_dvb_adapter_t *tda = dvb_service_get_tda(s); lock_assert(&global_lock); - tda->tda_open_service(tda, t); -#endif + tda->tda_open_service(tda, s); +} + + +/** + * + */ +static void +dvb_service_enlist(struct service *s, struct service_instance_list *sil) +{ + dvb_mux_t *dm = s->s_dvb_mux; + th_dvb_mux_instance_t *tdmi; + + dvb_create_tdmis(dm); + + LIST_FOREACH(tdmi, &dm->dm_tdmis, tdmi_mux_link) { + if(tdmi->tdmi_tune_failed) + continue; // The hardware is not able to tune to this frequency, never consider it + + service_instance_add(sil, s, tdmi->tdmi_adapter->tda_instance, 100, + tdmi_current_weight(tdmi)); + } } @@ -389,6 +398,7 @@ dvb_service_find2(dvb_mux_t *dm, uint16_t sid, int pmt_pid, t->s_setsourceinfo = dvb_service_setsourceinfo; t->s_grace_period = dvb_grace_period; t->s_serialize = dvb_service_serialize; + t->s_enlist = dvb_service_enlist; t->s_dvb_mux = dm; LIST_INSERT_HEAD(&dm->dm_services, t, s_group_link); diff --git a/src/iptv_input.c b/src/iptv_input.c index 5abc4ef3..57c994e9 100644 --- a/src/iptv_input.c +++ b/src/iptv_input.c @@ -198,7 +198,7 @@ iptv_thread(void *aux) * */ static int -iptv_service_start(service_t *t, unsigned int weight, int force_start) +iptv_service_start(service_t *t, int instance) { pthread_t tid; int fd; diff --git a/src/service.c b/src/service.c index c625148d..220f4cbc 100644 --- a/src/service.c +++ b/src/service.c @@ -176,7 +176,7 @@ service_stop(service_t *t) */ void service_remove_subscriber(service_t *t, th_subscription_t *s, - int reason) + int reason) { lock_assert(&global_lock); @@ -197,7 +197,7 @@ service_remove_subscriber(service_t *t, th_subscription_t *s, * */ int -service_start(service_t *t, unsigned int weight, int force_start) +service_start(service_t *t, int instance) { elementary_stream_t *st; int r, timeout = 2; @@ -208,7 +208,7 @@ service_start(service_t *t, unsigned int weight, int force_start) t->s_streaming_status = 0; t->s_pcr_drift = 0; - if((r = t->s_start_feed(t, weight, force_start))) + if((r = t->s_start_feed(t, instance))) return r; cwc_service_start(t); @@ -234,12 +234,73 @@ service_start(service_t *t, unsigned int weight, int force_start) return 0; } + +/** + * Main entry point for starting a service based on a channel + */ +service_instance_t * +service_find_instance(channel_t *ch, struct service_instance_list *sil, + int *error, int weight) +{ + service_t *s; + service_instance_t *si, *next; + + lock_assert(&global_lock); + + // First, update list of candidates + + LIST_FOREACH(si, sil, si_link) + si->si_mark = 1; + + LIST_FOREACH(s, &ch->ch_services, s_ch_link) + s->s_enlist(s, sil); + + for(si = LIST_FIRST(sil); si != NULL; si = next) { + next = LIST_NEXT(si, si_link); + if(si->si_mark) + service_instance_destroy(si); + } + + printf("Service start, enlisted candidates\n"); + LIST_FOREACH(si, sil, si_link) + printf(" %s i:%d w:%d p:%d\n", si->si_s->s_nicename, si->si_instance, si->si_weight, si->si_prio); + + + // Check if any service is already running, if so, use that + LIST_FOREACH(si, sil, si_link) + if(si->si_s->s_status == SERVICE_RUNNING) + return si; + + // Check if any is idle + LIST_FOREACH(si, sil, si_link) + if(si->si_weight == 0 && si->si_error == 0) + break; + + // Check if to kick someone out + if(si == NULL) { + LIST_FOREACH(si, sil, si_link) { + if(si->si_weight < weight && si->si_error == 0) + break; + } + } + + if(si == NULL) { + *error = SM_CODE_NO_FREE_ADAPTER; + return NULL; + } + + service_start(si->si_s, si->si_instance); + return NULL; +} + + + +#if 0 /** * */ service_t * -service_find(channel_t *ch, unsigned int weight, const char *loginfo, - int *errorp, service_t *skip) +service_enlist(channel_t *ch) { service_t *t, **vec; int cnt = 0, i, r, off; @@ -321,6 +382,7 @@ service_find(channel_t *ch, unsigned int weight, const char *loginfo, *errorp = SM_CODE_NO_SERVICE; return NULL; } +#endif /** @@ -1031,38 +1093,66 @@ service_refresh_channel(service_t *t) * */ static int -ssc_cmp(const service_start_cand_t *a, - const service_start_cand_t *b) +si_cmp(const service_instance_t *a, const service_instance_t *b) { - return a->ssc_prio - b->ssc_prio; + return a->si_prio - b->si_prio; } /** * */ -service_start_cand_t * -service_find_cand(struct service_start_cand_list *sscl, - struct service *s, int instance, int prio) +service_instance_t * +service_instance_add(struct service_instance_list *sil, + struct service *s, int instance, int prio, + int weight) { - service_start_cand_t *ssc; - LIST_FOREACH(ssc, sscl, ssc_link) { - if(ssc->ssc_s == s && ssc->ssc_instance == instance) + service_instance_t *si; + LIST_FOREACH(si, sil, si_link) + if(si->si_s == s && si->si_instance == instance) break; - } - if(ssc != NULL) { - ssc = calloc(1, sizeof(service_start_cand_t)); - ssc->ssc_s = s; + if(si == NULL) { + si = calloc(1, sizeof(service_instance_t)); + si->si_s = s; service_ref(s); - ssc->ssc_instance = instance; + si->si_instance = instance; + si->si_weight = weight; } else { - if(ssc->ssc_prio == prio) - return ssc; - LIST_REMOVE(ssc, ssc_link); + si->si_mark = 0; + if(si->si_prio == prio && si->si_weight == weight) + return si; + LIST_REMOVE(si, si_link); } - ssc->ssc_prio = prio; - LIST_INSERT_SORTED(sscl, ssc, ssc_link, ssc_cmp); - return ssc; + si->si_weight = weight; + si->si_prio = prio; + LIST_INSERT_SORTED(sil, si, si_link, si_cmp); + return si; +} + + +/** + * + */ +void +service_instance_destroy(service_instance_t *si) +{ + LIST_REMOVE(si, si_link); + service_unref(si->si_s); + free(si); +} + + +/** + * + */ +void +service_instance_list_clear(struct service_instance_list *sil) +{ + lock_assert(&global_lock); + + service_instance_t *si; + while((si = LIST_FIRST(sil)) != NULL) + service_instance_destroy(si); } diff --git a/src/service.h b/src/service.h index 294ef695..d045231a 100644 --- a/src/service.h +++ b/src/service.h @@ -167,35 +167,49 @@ typedef struct elementary_stream { } elementary_stream_t; -LIST_HEAD(service_start_cand_list, service_start_cand); +LIST_HEAD(service_instance_list, service_instance); /** * */ -typedef struct service_start_cand { +typedef struct service_instance { - LIST_ENTRY(service_start_cand) ssc_link; + LIST_ENTRY(service_instance) si_link; - int ssc_prio; + int si_prio; - struct service *ssc_s; // A reference is held - int ssc_instance; // Discriminator when having multiple adapters, etc + struct service *si_s; // A reference is held + int si_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 si_error; /* Set if subscription layer deem this cand + to be broken. We typically set this if we + have not seen any demuxed packets after + the grace period has expired. + The actual value is current time + */ - int ssc_weight; // Highest weight that holds this cand + time_t si_error_time; -} service_start_cand_t; + + int si_weight; // Highest weight that holds this cand + + int si_mark; // For mark & sweep + +} service_instance_t; /** * */ -service_start_cand_t *service_find_cand(struct service_start_cand_list *sscl, - struct service *s, - int instance, - int prio); +service_instance_t *service_instance_add(struct service_instance_list *sil, + struct service *s, + int instance, + int prio, + int weight); + +void service_instance_destroy(service_instance_t *si); + +void service_instance_list_clear(struct service_instance_list *sil); /** * @@ -285,12 +299,9 @@ typedef struct service { LIST_HEAD(, th_subscription) s_subscriptions; - void (*s_enlist)(struct service *s, - struct service_start_cand_list *sscl); + void (*s_enlist)(struct service *s, struct service_instance_list *sil); - - int (*s_start_feed)(struct service *t, unsigned int weight, - int force_start); + int (*s_start_feed)(struct service *s, int instance); void (*s_refresh_feed)(struct service *t); @@ -540,7 +551,7 @@ void service_init(void); unsigned int service_compute_weight(struct service_list *head); -int service_start(service_t *t, unsigned int weight, int force_start); +int service_start(service_t *t, int instance); service_t *service_create(const char *uuid, int source_type); @@ -552,9 +563,10 @@ service_t *service_find_by_identifier(const char *identifier); void service_map_channel(service_t *t, struct channel *ch, int save); -service_t *service_find(struct channel *ch, unsigned int weight, - const char *loginfo, int *errorp, - service_t *skip); +service_instance_t *service_find_instance(struct channel *ch, + struct service_instance_list *sil, + int *error, + int weight); elementary_stream_t *service_stream_find(service_t *t, int pid); diff --git a/src/subscriptions.c b/src/subscriptions.c index e7026080..28a6cf6a 100644 --- a/src/subscriptions.c +++ b/src/subscriptions.c @@ -155,9 +155,8 @@ void subscription_reschedule(void) { th_subscription_t *s; - service_t *t, *skip; + service_instance_t *si; streaming_message_t *sm; - char buf[128]; int error; lock_assert(&global_lock); @@ -173,19 +172,20 @@ subscription_reschedule(void) /* Already got a service */ if(s->ths_state != SUBSCRIPTION_BAD_SERVICE) - continue; /* And it seems to work ok, so we're happy */ - skip = s->ths_service; - error = s->ths_testing_error; - service_remove_subscriber(s->ths_service, s, s->ths_testing_error); - } else { - error = 0; - skip = NULL; + continue; /* And it not bad, so we're happy */ + + si = s->ths_current_instance; + + assert(si != NULL); + si->si_error = s->ths_testing_error; + time(&si->si_error_time); } - snprintf(buf, sizeof(buf), "Subscription \"%s\"", s->ths_title); - t = service_find(s->ths_channel, s->ths_weight, buf, &error, skip); + si = service_find_instance(s->ths_channel, &s->ths_instances, &error, + s->ths_weight); + s->ths_current_instance = si; - if(t == NULL) { + if(si == NULL) { /* No service available */ sm = streaming_msg_create_code(SMT_NOSTART, error); @@ -193,7 +193,7 @@ subscription_reschedule(void) continue; } - subscription_link_service(s, t); + subscription_link_service(s, si->si_s); } } @@ -207,6 +207,8 @@ subscription_unsubscribe(th_subscription_t *s) lock_assert(&global_lock); + service_instance_list_clear(&s->ths_instances); + LIST_REMOVE(s, ths_global_link); if(s->ths_channel != NULL) { @@ -407,6 +409,7 @@ th_subscription_t * subscription_create_from_service(service_t *t, const char *name, streaming_target_t *st, int flags) { +#if 0 th_subscription_t *s; source_info_t si; int r; @@ -443,6 +446,8 @@ subscription_create_from_service(service_t *t, const char *name, subscription_link_service(s, t); notify_reload("subscriptions"); return s; +#endif + abort(); } diff --git a/src/subscriptions.h b/src/subscriptions.h index 0a88e5f5..f5166f7a 100644 --- a/src/subscriptions.h +++ b/src/subscriptions.h @@ -19,6 +19,8 @@ #ifndef SUBSCRIPTIONS_H #define SUBSCRIPTIONS_H +#include "service.h" + extern struct th_subscription_list subscriptions; #define SUBSCRIPTION_RAW_MPEGTS 0x1 @@ -65,6 +67,12 @@ typedef struct th_subscription { char *ths_username; char *ths_client; + /** + * This is the list of service candidates we have + */ + struct service_instance_list ths_instances; + struct service_instance *ths_current_instance; + // Ugly ugly ugly to refer DVB code here LIST_ENTRY(th_subscription) ths_tdmi_link; diff --git a/src/v4l.c b/src/v4l.c index 6fae6750..1e76ba1a 100644 --- a/src/v4l.c +++ b/src/v4l.c @@ -170,7 +170,7 @@ v4l_thread(void *aux) * */ static int -v4l_service_start(service_t *t, unsigned int weight, int force_start) +v4l_service_start(service_t *t, int instance) { v4l_adapter_t *va = t->s_v4l_adapter; int frequency = t->s_v4l_frequency; diff --git a/src/webui/extjs_dvb.c b/src/webui/extjs_dvb.c index f321200a..408e2d3b 100644 --- a/src/webui/extjs_dvb.c +++ b/src/webui/extjs_dvb.c @@ -221,23 +221,25 @@ extjs_dvbadapter(http_connection_t *hc, const char *remain, void *opaque) out = htsmsg_create_map(); htsmsg_add_u32(out, "success", 1); -#if 0 + } else if(!strcmp(op, "serviceprobe")) { tvhlog(LOG_NOTICE, "web interface", "Service probe started on \"%s\"", tda->tda_displayname); - LIST_FOREACH(tdmi, &tda->tda_dn->dn_mux_instances, tdmi_adapter_link) { - LIST_FOREACH(t, &tdmi->tdmi_mux->dm_services, s_group_link) { - if(t->s_enabled) - serviceprobe_enqueue(t); + dvb_mux_t *dm; + service_t *s; + + LIST_FOREACH(dm, &tda->tda_dn->dn_muxes, dm_network_link) { + LIST_FOREACH(s, &dm->dm_services, s_group_link) { + if(s->s_enabled) + serviceprobe_enqueue(s); } } out = htsmsg_create_map(); htsmsg_add_u32(out, "success", 1); -#endif } else { pthread_mutex_unlock(&global_lock); diff --git a/src/webui/static/app/dvb.js b/src/webui/static/app/dvb.js index bdbc022b..89e6e4cb 100644 --- a/src/webui/static/app/dvb.js +++ b/src/webui/static/app/dvb.js @@ -1266,10 +1266,13 @@ tvheadend.dvb_adapter_general = function(adapterData, satConfStore) { if (r.data.identifier != adapterId) return; infoTemplate.overwrite(infoPanel.body, r.data); + serviceScanBtn.enable(); + if (r.data.services > 0 && r.data.initialMuxes == 0) serviceScanBtn .enable(); else serviceScanBtn.disable(); }); + serviceScanBtn.enable(); return panel; } diff --git a/src/webui/static/app/dvb_networks.js b/src/webui/static/app/dvb_networks.js index 44b68687..378df82b 100644 --- a/src/webui/static/app/dvb_networks.js +++ b/src/webui/static/app/dvb_networks.js @@ -13,7 +13,12 @@ tvheadend.dvb_networks = function() { root : new Ext.tree.AsyncTreeNode({ id : 'root', text: 'DVB Networks' - }) + }), + listeners: { + click: function(n) { + Ext.Msg.alert('Navigation Tree Click', 'You clicked: "' + n.attributes.text + '"'); + } + } }); From 302319220a28c4993ba9017ead6b406ed139110c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20=C3=96man?= Date: Thu, 7 Feb 2013 23:42:25 +0100 Subject: [PATCH 21/31] Add bool type to htsmsg + json parser --- src/htsmsg.c | 32 ++++++++++++++++++++++++++++++++ src/htsmsg.h | 7 +++++++ src/htsmsg_json.c | 8 +++++++- 3 files changed, 46 insertions(+), 1 deletion(-) diff --git a/src/htsmsg.c b/src/htsmsg.c index 935c30b6..794b3e03 100644 --- a/src/htsmsg.c +++ b/src/htsmsg.c @@ -176,6 +176,16 @@ htsmsg_destroy(htsmsg_t *msg) free(msg); } +/* + * + */ +void +htsmsg_add_bool(htsmsg_t *msg, const char *name, int b) +{ + htsmsg_field_t *f = htsmsg_field_add(msg, name, HMF_BOOL, HMF_NAME_ALLOCED); + f->hmf_bool = !!b; +} + /* * */ @@ -313,6 +323,9 @@ htsmsg_get_s64(htsmsg_t *msg, const char *name, int64_t *s64p) case HMF_S64: *s64p = f->hmf_s64; break; + case HMF_BOOL: + *s64p = f->hmf_bool; + break; case HMF_DBL: *s64p = f->hmf_dbl; break; @@ -321,6 +334,17 @@ htsmsg_get_s64(htsmsg_t *msg, const char *name, int64_t *s64p) } +/** + * + */ +int +htsmsg_get_bool_or_default(htsmsg_t *msg, const char *name, int def) +{ + int64_t s64; + return htsmsg_get_s64(msg, name, &s64) ? def : s64; +} + + /** * */ @@ -598,6 +622,10 @@ htsmsg_print0(htsmsg_t *msg, int indent) printf("S64) = %" PRId64 "\n", f->hmf_s64); break; + case HMF_BOOL: + printf("BOOL) = %s\n", f->hmf_bool ? "true" : "false"); + break; + case HMF_DBL: printf("DBL) = %f\n", f->hmf_dbl); break; @@ -644,6 +672,10 @@ htsmsg_copy_i(htsmsg_t *src, htsmsg_t *dst) htsmsg_add_s64(dst, f->hmf_name, f->hmf_s64); break; + case HMF_BOOL: + htsmsg_add_bool(dst, f->hmf_name, f->hmf_bool); + break; + case HMF_BIN: htsmsg_add_bin(dst, f->hmf_name, f->hmf_bin, f->hmf_binsize); break; diff --git a/src/htsmsg.h b/src/htsmsg.h index 82fb7fda..e2836820 100644 --- a/src/htsmsg.h +++ b/src/htsmsg.h @@ -50,6 +50,7 @@ typedef struct htsmsg { #define HMF_BIN 4 #define HMF_LIST 5 #define HMF_DBL 6 +#define HMF_BOOL 7 typedef struct htsmsg_field { TAILQ_ENTRY(htsmsg_field) hmf_link; @@ -69,6 +70,7 @@ typedef struct htsmsg_field { } bin; htsmsg_t msg; double dbl; + int bool; } u; } htsmsg_field_t; @@ -78,6 +80,7 @@ typedef struct htsmsg_field { #define hmf_bin u.bin.data #define hmf_binsize u.bin.len #define hmf_dbl u.dbl +#define hmf_bool u.bool #define htsmsg_get_map_by_field(f) \ ((f)->hmf_type == HMF_MAP ? &(f)->hmf_msg : NULL) @@ -106,6 +109,8 @@ void htsmsg_field_destroy(htsmsg_t *msg, htsmsg_field_t *f); */ void htsmsg_destroy(htsmsg_t *msg); +void htsmsg_add_bool(htsmsg_t *msg, const char *name, int b); + /** * Add an integer field where source is unsigned 32 bit. */ @@ -190,6 +195,8 @@ int htsmsg_get_s64(htsmsg_t *msg, const char *name, int64_t *s64p); */ int64_t htsmsg_get_s64_or_default(htsmsg_t *msg, const char *name, int64_t def); +int htsmsg_get_bool_or_default(htsmsg_t *msg, const char *name, int def); + /** * Get pointer to a binary field. No copying of data is performed. diff --git a/src/htsmsg_json.c b/src/htsmsg_json.c index 3fda47c1..19c85a71 100644 --- a/src/htsmsg_json.c +++ b/src/htsmsg_json.c @@ -39,6 +39,7 @@ htsmsg_json_write(htsmsg_t *msg, htsbuf_queue_t *hq, int isarray, htsmsg_field_t *f; char buf[100]; static const char *indentor = "\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t"; + const char *s; htsbuf_append(hq, isarray ? "[" : "{", 1); @@ -69,6 +70,11 @@ htsmsg_json_write(htsmsg_t *msg, htsbuf_queue_t *hq, int isarray, htsbuf_append_and_escape_jsonstr(hq, "binary"); break; + case HMF_BOOL: + s = f->hmf_bool ? "true" : "false"; + htsbuf_append(hq, s, strlen(s)); + break; + case HMF_S64: snprintf(buf, sizeof(buf), "%" PRId64, f->hmf_s64); htsbuf_append(hq, buf, strlen(buf)); @@ -169,7 +175,7 @@ add_double(void *opaque, void *parent, const char *name, double v) static void add_bool(void *opaque, void *parent, const char *name, int v) { - htsmsg_add_u32(parent, name, v); + htsmsg_add_bool(parent, name, v); } static void From a6433e4a37dfcef05cabf38eb3bb769f00c5c9e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20=C3=96man?= Date: Thu, 7 Feb 2013 23:42:13 +0100 Subject: [PATCH 22/31] Work on settings properties on nodes from UI --- Makefile | 1 + src/dvb/dvb_multiplex.c | 19 +++--- src/dvb/dvb_network.c | 96 ++++------------------------ src/dvb/dvb_service.c | 17 ++--- src/idnode.c | 26 ++++++++ src/idnode.h | 7 +- src/prop.c | 84 ++++++++++++++++++++++++ src/prop.h | 24 +++++++ src/service.c | 32 +--------- src/service.h | 4 +- src/webui/extjs_dvb.c | 2 +- src/webui/static/app/dvb_networks.js | 44 ++++++++++++- 12 files changed, 218 insertions(+), 138 deletions(-) create mode 100644 src/prop.c create mode 100644 src/prop.h diff --git a/Makefile b/Makefile index 37145763..f073c5d5 100644 --- a/Makefile +++ b/Makefile @@ -64,6 +64,7 @@ endif # SRCS = src/main.c \ src/idnode.c \ + src/prop.c \ src/utils.c \ src/wrappers.c \ src/version.c \ diff --git a/src/dvb/dvb_multiplex.c b/src/dvb/dvb_multiplex.c index b7f11589..3a3129bc 100644 --- a/src/dvb/dvb_multiplex.c +++ b/src/dvb/dvb_multiplex.c @@ -58,13 +58,18 @@ static struct strtab muxfestatustab[] = { -static htsmsg_t *dvb_mux_serialize(struct idnode *self, int full); static idnode_t **dvb_mux_get_childs(struct idnode *self); +static const char *dvb_mux_get_title(struct idnode *self); static const idclass_t dvb_mux_class = { .ic_class = "dvbmux", - .ic_serialize = dvb_mux_serialize, + .ic_get_title = dvb_mux_get_title, .ic_get_childs = dvb_mux_get_childs, + .ic_properties = { + { + "enabled", "Enabled", PT_BOOL, + offsetof(dvb_mux_t, dm_enabled) + }, {}} }; @@ -1244,14 +1249,10 @@ dvb_subscription_create_from_tdmi(th_dvb_mux_instance_t *tdmi, /** * */ -static htsmsg_t * -dvb_mux_serialize(struct idnode *self, int full) +static const char * +dvb_mux_get_title(struct idnode *self) { - 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)); - htsmsg_add_str(m, "text", dvb_mux_nicename(dm)); - return m; + return dvb_mux_nicename((dvb_mux_t *)self); } /** diff --git a/src/dvb/dvb_network.c b/src/dvb/dvb_network.c index c0818446..82feba0c 100644 --- a/src/dvb/dvb_network.c +++ b/src/dvb/dvb_network.c @@ -27,13 +27,23 @@ 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, + .ic_properties = { + { + "autodiscovery", "Auto discovery", PT_BOOL, + offsetof(dvb_network_t, dn_autodiscovery) + }, { + "nitoid", "NIT OID", PT_INT, + offsetof(dvb_network_t, dn_nitoid) + }, { + "disable_pmt_monitor", "Disable PMT monitor", PT_BOOL, + offsetof(dvb_network_t, dn_disable_pmt_monitor) + }, { + }}, }; /** @@ -42,15 +52,12 @@ static const idclass_t dvb_network_class = { dvb_network_t * 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_pending_queue); TAILQ_INIT(&dn->dn_initial_scan_current_queue); @@ -62,20 +69,6 @@ dvb_network_create(int fe_type, const char *uuid) -/** - * - */ -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; -} - - /** * */ @@ -161,68 +154,6 @@ dvb_network_save(dvb_network_t *dn) #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 - - /** * @@ -268,9 +199,6 @@ dvb_network_init(void) 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; diff --git a/src/dvb/dvb_service.c b/src/dvb/dvb_service.c index 8b8e1ffb..7fbb2a34 100644 --- a/src/dvb/dvb_service.c +++ b/src/dvb/dvb_service.c @@ -44,7 +44,7 @@ #include "dvb_support.h" #include "notify.h" -static htsmsg_t *dvb_service_serialize(service_t *s, int full); +static htsmsg_t *dvb_service_serialize(service_t *s); /** @@ -414,18 +414,19 @@ dvb_service_find2(dvb_mux_t *dm, uint16_t sid, int pmt_pid, * */ static htsmsg_t * -dvb_service_serialize(service_t *s, int full) +dvb_service_serialize(service_t *s) { dvb_mux_t *dm = s->s_dvb_mux; htsmsg_t *m = htsmsg_create_map(); char buf[100]; - htsmsg_add_str(m, "id", idnode_uuid_as_str(&s->s_id)); - - snprintf(buf, sizeof(buf), "%s (0x%04x)", - s->s_svcname ?: "", s->s_dvb_service_id); - htsmsg_add_str(m, "text", buf); - + if(s->s_svcname) { + htsmsg_add_str(m, "text", s->s_svcname); + } else { + snprintf(buf, sizeof(buf), "Service-0x%04x", + 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); diff --git a/src/idnode.c b/src/idnode.c index 58b3bbd4..e907b103 100644 --- a/src/idnode.c +++ b/src/idnode.c @@ -156,3 +156,29 @@ idnode_unlink(idnode_t *in) { RB_REMOVE(&idnodes, in, in_link); } + + +/** + * + */ +htsmsg_t * +idnode_serialize(struct idnode *self) +{ + const idclass_t *c = self->in_class; + htsmsg_t *m; + if(c->ic_serialize != NULL) { + m = c->ic_serialize(self); + } else { + m = htsmsg_create_map(); + + if(c->ic_get_title != NULL) { + htsmsg_add_str(m, "text", c->ic_get_title(self)); + } else { + htsmsg_add_str(m, "text", idnode_uuid_as_str(self)); + } + htsmsg_add_msg(m, "properties", prop_get_values(self, c->ic_properties)); + htsmsg_add_msg(m, "propertynames", prop_get_names(c->ic_properties)); + htsmsg_add_str(m, "id", idnode_uuid_as_str(self)); + } + return m; +} diff --git a/src/idnode.h b/src/idnode.h index a49b4382..3735801a 100644 --- a/src/idnode.h +++ b/src/idnode.h @@ -1,14 +1,17 @@ #pragma once #include "tvheadend.h" +#include "prop.h" struct htsmsg; struct idnode; typedef struct idclass { const char *ic_class; - struct htsmsg *(*ic_serialize)(struct idnode *self, int full); + struct htsmsg *(*ic_serialize)(struct idnode *self); struct idnode **(*ic_get_childs)(struct idnode *self); + const char *(*ic_get_title)(struct idnode *self); + const property_t ic_properties[]; } idclass_t; @@ -27,3 +30,5 @@ const char *idnode_uuid_as_str(const idnode_t *in); idnode_t *idnode_find(const char *uuid); void idnode_unlink(idnode_t *in); + +htsmsg_t *idnode_serialize(struct idnode *self); diff --git a/src/prop.c b/src/prop.c new file mode 100644 index 00000000..7050e8cb --- /dev/null +++ b/src/prop.c @@ -0,0 +1,84 @@ +#include "prop.h" + +#if 0 +/** + * + */ +void +prop_write_values(void *ptr, const property_t p[], htsmsg_t *m) +{ + int i = 0; + for(;p[i].id; i++) { + switch(p[i].type) { + case PT_BOOL: + htsmsg_add_bool(m, p[i].id, *(int *)(ptr + p[i].off)); + break; + case PT_INT: + htsmsg_add_s32(m, p[i].id, *(int *)(ptr + p[i].off)); + break; + case PT_STR: + htsmsg_add_str(m, p[i].id, (const char *)(ptr + p[i].off)); + break; + } + } +} +#endif + + +/** + * + */ +void +prop_read_values(void *ptr, const property_t p[], htsmsg_t *m) +{ + int i = 0; + for(;p[i].id; i++) { + switch(p[i].type) { + case PT_BOOL: + htsmsg_add_bool(m, p[i].id, *(int *)(ptr + p[i].off)); + break; + case PT_INT: + htsmsg_add_s32(m, p[i].id, *(int *)(ptr + p[i].off)); + break; + case PT_STR: + htsmsg_add_str(m, p[i].id, (const char *)(ptr + p[i].off)); + break; + } + } +} + + +/** + * + */ +htsmsg_t * +prop_get_values(void *ptr, const property_t p[]) +{ + htsmsg_t *m = htsmsg_create_map(); + prop_read_values(ptr, p, m); + return m; +} + + +/** + * + */ +void +prop_read_names(const property_t p[], htsmsg_t *m) +{ + int i = 0; + for(;p[i].name; i++) + htsmsg_add_str(m, p[i].id, p[i].name); +} + + +/** + * + */ +htsmsg_t * +prop_get_names(const property_t p[]) +{ + htsmsg_t *m = htsmsg_create_map(); + prop_read_names(p, m); + return m; +} diff --git a/src/prop.h b/src/prop.h new file mode 100644 index 00000000..148d67ed --- /dev/null +++ b/src/prop.h @@ -0,0 +1,24 @@ +#pragma once +#include + +#include "htsmsg.h" + +typedef enum { + PT_BOOL, + PT_INT, + PT_STR, +} prop_type_t; + +typedef struct property { + const char *id; + const char *name; + prop_type_t type; + size_t off; +} property_t; + + + +void prop_read_values(void *ptr, const property_t p[], htsmsg_t *m); +htsmsg_t *prop_get_values(void *ptr, const property_t p[]); +void prop_read_names(const property_t p[], htsmsg_t *m); +htsmsg_t *prop_get_names(const property_t p[]); diff --git a/src/service.c b/src/service.c index 220f4cbc..89608b82 100644 --- a/src/service.c +++ b/src/service.c @@ -51,7 +51,7 @@ static void service_data_timeout(void *aux); -static htsmsg_t *service_serialize(struct idnode *self, int full); +static htsmsg_t *service_serialize(struct idnode *self); static const idclass_t service_class = { .ic_class = "service", @@ -261,11 +261,6 @@ service_find_instance(channel_t *ch, struct service_instance_list *sil, service_instance_destroy(si); } - printf("Service start, enlisted candidates\n"); - LIST_FOREACH(si, sil, si_link) - printf(" %s i:%d w:%d p:%d\n", si->si_s->s_nicename, si->si_instance, si->si_weight, si->si_prio); - - // Check if any service is already running, if so, use that LIST_FOREACH(si, sil, si_link) if(si->si_s->s_status == SERVICE_RUNNING) @@ -385,27 +380,6 @@ service_enlist(channel_t *ch) #endif -/** - * - */ -unsigned int -service_compute_weight(struct service_list *head) -{ - service_t *t; - th_subscription_t *s; - int w = 0; - - lock_assert(&global_lock); - - LIST_FOREACH(t, head, s_active_link) { - LIST_FOREACH(s, &t->s_subscriptions, ths_service_link) { - if(s->ths_weight > w) - w = s->ths_weight; - } - } - return w; -} - /** * @@ -1219,8 +1193,8 @@ htsmsg_t *servicetype_list ( void ) * */ static htsmsg_t * -service_serialize(struct idnode *self, int full) +service_serialize(struct idnode *self) { service_t *s = (service_t *)self; - return s->s_serialize(s, full); + return s->s_serialize(s); } diff --git a/src/service.h b/src/service.h index d045231a..bfaf1346 100644 --- a/src/service.h +++ b/src/service.h @@ -315,7 +315,7 @@ typedef struct service { void (*s_dtor)(struct service *t); - htsmsg_t *(*s_serialize)(struct service *s, int full); + htsmsg_t *(*s_serialize)(struct service *s); /* * Per source type structs @@ -549,8 +549,6 @@ typedef struct service { void service_init(void); -unsigned int service_compute_weight(struct service_list *head); - int service_start(service_t *t, int instance); service_t *service_create(const char *uuid, int source_type); diff --git a/src/webui/extjs_dvb.c b/src/webui/extjs_dvb.c index 408e2d3b..9f48ad33 100644 --- a/src/webui/extjs_dvb.c +++ b/src/webui/extjs_dvb.c @@ -715,7 +715,7 @@ extjs_dvbnetworks(http_connection_t *hc, const char *remain, void *opaque) int i; for(i = 0; v[i] != NULL; i++) { - htsmsg_t *m = v[i]->in_class->ic_serialize(v[i], 0); + htsmsg_t *m = idnode_serialize(v[i]); if(v[i]->in_class->ic_get_childs == NULL) htsmsg_add_u32(m, "leaf", 1); htsmsg_add_msg(out, NULL, m); diff --git a/src/webui/static/app/dvb_networks.js b/src/webui/static/app/dvb_networks.js index 378df82b..be0ecab6 100644 --- a/src/webui/static/app/dvb_networks.js +++ b/src/webui/static/app/dvb_networks.js @@ -1,30 +1,68 @@ + + + +tvheadend.item_editor = function(item) { + var propsGrid = new Ext.grid.PropertyGrid({ + flex:1, + padding: 5, + propertyNames: item.propertynames, + source: item.properties + }); + return propsGrid; +} + + + + + + + /** * */ tvheadend.dvb_networks = function() { + var current = null; + var loader = new Ext.tree.TreeLoader({ dataUrl: 'dvb/networks' }); var tree = new Ext.tree.TreePanel({ - title: 'DVB Networks', loader: loader, + flex:1, + border: false, root : new Ext.tree.AsyncTreeNode({ id : 'root', text: 'DVB Networks' }), listeners: { click: function(n) { - Ext.Msg.alert('Navigation Tree Click', 'You clicked: "' + n.attributes.text + '"'); + if(current) + panel.remove(current); + current = panel.add(new tvheadend.item_editor(n.attributes)); + panel.doLayout(); } } }); + var panel = new Ext.Panel({ + title: 'DVB Networks', + layout: 'hbox', + flex: 1, + padding: 5, + border: false, + layoutConfig: { + align:'stretch' + }, + items: [tree] + }); + + tree.on('render', function() { tree.getRootNode().expand(); }); - return tree; + return panel; } From 3f1d29974914cdabbf6adc718ba38752c79c9936 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20=C3=96man?= Date: Thu, 7 Feb 2013 23:44:14 +0100 Subject: [PATCH 23/31] fix some issues --- src/dvb/dvb_tables.c | 4 +--- src/rawtsinput.c | 2 +- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/dvb/dvb_tables.c b/src/dvb/dvb_tables.c index 3537cb51..133f9b6c 100644 --- a/src/dvb/dvb_tables.c +++ b/src/dvb/dvb_tables.c @@ -52,7 +52,6 @@ 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; - char buf[100]; if(dm->dm_scan_status == DM_SCAN_DONE) return; @@ -63,9 +62,8 @@ dvb_table_fastswitch(th_dvb_mux_instance_t *tdmi) 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); + tda->tda_rootpath, dvb_mux_nicename(dm)); dvb_mux_initial_scan_done(dm); } diff --git a/src/rawtsinput.c b/src/rawtsinput.c index 256d476d..ee568302 100644 --- a/src/rawtsinput.c +++ b/src/rawtsinput.c @@ -52,7 +52,7 @@ typedef struct rawts { * */ static int -rawts_service_start(service_t *t, unsigned int weight, int force_start) +rawts_service_start(service_t *t, int id) { return 0; // Always ok } From eec7d0ebcf6a4d77d4ba13db0a023d76bfc0953b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20=C3=96man?= Date: Fri, 15 Mar 2013 12:45:22 +0100 Subject: [PATCH 24/31] Split service out in a superclass and a per-hw type class --- src/dvb/dvb.h | 2 +- src/dvb/dvb_adapter.c | 21 ---------- src/dvb/dvb_multiplex.c | 2 +- src/dvb/dvb_network.c | 20 ++++------ src/dvb/dvb_service.c | 40 +++++++++++++++++-- src/idnode.c | 26 +++++++++++-- src/idnode.h | 5 ++- src/iptv_input.c | 26 +++++-------- src/prop.c | 86 +++++++++++++++++++++++++++++++---------- src/prop.h | 13 +++++-- src/rawtsinput.c | 7 +++- src/service.c | 58 ++++++++++++++++++--------- src/service.h | 6 +-- src/serviceprobe.c | 2 +- src/tvheadend.h | 7 ++++ src/v4l.c | 6 ++- src/webui/extjs_dvb.c | 22 +++++------ 17 files changed, 225 insertions(+), 124 deletions(-) diff --git a/src/dvb/dvb.h b/src/dvb/dvb.h index cfb42e1a..db72f1cd 100644 --- a/src/dvb/dvb.h +++ b/src/dvb/dvb.h @@ -108,6 +108,7 @@ typedef struct dvb_network { uint32_t dn_disable_pmt_monitor; uint32_t dn_autodiscovery; uint32_t dn_nitoid; + uint32_t dn_skip_checksubscr; struct th_dvb_adapter_list dn_adapters; @@ -248,7 +249,6 @@ typedef struct th_dvb_adapter { char *tda_identifier; 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; diff --git a/src/dvb/dvb_adapter.c b/src/dvb/dvb_adapter.c index 03cc15a2..eb6169bb 100644 --- a/src/dvb/dvb_adapter.c +++ b/src/dvb/dvb_adapter.c @@ -77,7 +77,6 @@ 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, "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); @@ -151,25 +150,6 @@ dvb_adapter_set_idleclose(th_dvb_adapter_t *tda, int on) tda_save(tda); } - -/** - * - */ -void -dvb_adapter_set_skip_checksubscr(th_dvb_adapter_t *tda, int on) -{ - if(tda->tda_skip_checksubscr == on) - return; - - lock_assert(&global_lock); - - tvhlog(LOG_NOTICE, "dvb", "Adapter \"%s\" skip service availability check when mapping set to: %s", - tda->tda_displayname, on ? "On" : "Off"); - - tda->tda_skip_checksubscr = on; - tda_save(tda); -} - /** * */ @@ -609,7 +589,6 @@ dvb_adapter_init(uint32_t adapter_mask, const char *rawfile) tda->tda_displayname = strdup(name); 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); diff --git a/src/dvb/dvb_multiplex.c b/src/dvb/dvb_multiplex.c index 3a3129bc..5069549f 100644 --- a/src/dvb/dvb_multiplex.c +++ b/src/dvb/dvb_multiplex.c @@ -65,7 +65,7 @@ static const idclass_t dvb_mux_class = { .ic_class = "dvbmux", .ic_get_title = dvb_mux_get_title, .ic_get_childs = dvb_mux_get_childs, - .ic_properties = { + .ic_properties = (const property_t[]){ { "enabled", "Enabled", PT_BOOL, offsetof(dvb_mux_t, dm_enabled) diff --git a/src/dvb/dvb_network.c b/src/dvb/dvb_network.c index 82feba0c..3dc45902 100644 --- a/src/dvb/dvb_network.c +++ b/src/dvb/dvb_network.c @@ -32,7 +32,7 @@ static idnode_t **dvb_network_get_childs(struct idnode *self); static const idclass_t dvb_network_class = { .ic_class = "dvbnetwork", .ic_get_childs = dvb_network_get_childs, - .ic_properties = { + .ic_properties = (const property_t[]){ { "autodiscovery", "Auto discovery", PT_BOOL, offsetof(dvb_network_t, dn_autodiscovery) @@ -42,6 +42,9 @@ static const idclass_t dvb_network_class = { }, { "disable_pmt_monitor", "Disable PMT monitor", PT_BOOL, offsetof(dvb_network_t, dn_disable_pmt_monitor) + }, { + "disable_pmt_monitor", "Disable PMT monitor", PT_BOOL, + offsetof(dvb_network_t, dn_disable_pmt_monitor) }, { }}, }; @@ -122,16 +125,12 @@ dvb_network_load(htsmsg_t *m, const char *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); - + prop_write_values(dn, dvb_network_class.ic_properties, m); dvb_mux_load(dn); - dvb_network_schedule_initial_scan(dn); } -#if 1 + /** * */ @@ -142,17 +141,12 @@ 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); + prop_read_values(dn, dvb_network_class.ic_properties, m); hts_settings_save(m, "dvb/networks/%s/config", idnode_uuid_as_str(&dn->dn_id)); htsmsg_destroy(m); } -#endif - /** diff --git a/src/dvb/dvb_service.c b/src/dvb/dvb_service.c index 7fbb2a34..748b445c 100644 --- a/src/dvb/dvb_service.c +++ b/src/dvb/dvb_service.c @@ -44,7 +44,20 @@ #include "dvb_support.h" #include "notify.h" -static htsmsg_t *dvb_service_serialize(service_t *s); +static const char *dvb_service_get_title(struct idnode *self); + +const idclass_t dvb_service_class = { + .ic_super = &service_class, + .ic_class = "dvbservice", + .ic_get_title = dvb_service_get_title, + // .ic_get_childs = dvb_service_get_childs, + .ic_properties = (const property_t[]){ + { + "dvb_eit_enable", "Use EPG", PT_BOOL, + offsetof(service_t, s_dvb_eit_enable) + }, { + }} +}; /** @@ -385,7 +398,8 @@ dvb_service_find2(dvb_mux_t *dm, uint16_t sid, int pmt_pid, tvhlog(LOG_DEBUG, "dvb", "Add service \"0x%x\" on \"%s\"", sid, dvb_mux_nicename(dm)); - t = service_create(uuid, S_MPEG_TS); + t = service_create(uuid, S_MPEG_TS, &dvb_service_class); + if (save) *save = 1; t->s_dvb_service_id = sid; @@ -397,7 +411,6 @@ 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_enlist = dvb_service_enlist; t->s_dvb_mux = dm; @@ -409,7 +422,7 @@ dvb_service_find2(dvb_mux_t *dm, uint16_t sid, int pmt_pid, return t; } - +#if 0 /** * */ @@ -454,6 +467,25 @@ dvb_service_serialize(service_t *s) return m; } +#endif + + +/** + * + */ +static const char * +dvb_service_get_title(struct idnode *self) +{ + service_t *s = (service_t *)self; + static char buf[100]; + + if(s->s_svcname) { + return s->s_svcname; + } else { + snprintf(buf, sizeof(buf), "Service-0x%04x", s->s_dvb_service_id); + return buf; + } +} /** diff --git a/src/idnode.c b/src/idnode.c index e907b103..ec3211ea 100644 --- a/src/idnode.c +++ b/src/idnode.c @@ -136,14 +136,22 @@ idnode_uuid_as_str(const idnode_t *in) /** * */ -idnode_t * -idnode_find(const char *uuid) +void * +idnode_find(const char *uuid, const idclass_t *idc) { idnode_t skel, *r; if(hex2bin(skel.in_uuid, 16, uuid)) return NULL; r = RB_FIND(&idnodes, &skel, in_link, in_cmp); + if(r != NULL && idc != NULL) { + const idclass_t *c = r->in_class; + for(;c != NULL; c = c->ic_super) { + if(idc == c) + return r; + } + return NULL; + } return r; } @@ -171,13 +179,23 @@ idnode_serialize(struct idnode *self) } else { m = htsmsg_create_map(); + htsmsg_t *p = htsmsg_create_map(); + htsmsg_t *pn = htsmsg_create_map(); + if(c->ic_get_title != NULL) { htsmsg_add_str(m, "text", c->ic_get_title(self)); } else { htsmsg_add_str(m, "text", idnode_uuid_as_str(self)); } - htsmsg_add_msg(m, "properties", prop_get_values(self, c->ic_properties)); - htsmsg_add_msg(m, "propertynames", prop_get_names(c->ic_properties)); + + for(;c != NULL; c = c->ic_super) { + prop_read_values(self, c->ic_properties, p); + prop_read_names(c->ic_properties, pn); + } + + htsmsg_add_msg(m, "properties", p); + htsmsg_add_msg(m, "propertynames", pn); + htsmsg_add_str(m, "id", idnode_uuid_as_str(self)); } return m; diff --git a/src/idnode.h b/src/idnode.h index 3735801a..a5a0901b 100644 --- a/src/idnode.h +++ b/src/idnode.h @@ -7,11 +7,12 @@ struct htsmsg; struct idnode; typedef struct idclass { + const struct idclass *ic_super; const char *ic_class; struct htsmsg *(*ic_serialize)(struct idnode *self); struct idnode **(*ic_get_childs)(struct idnode *self); const char *(*ic_get_title)(struct idnode *self); - const property_t ic_properties[]; + const property_t *ic_properties; } idclass_t; @@ -27,7 +28,7 @@ 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_find(const char *uuid, const idclass_t *class); void idnode_unlink(idnode_t *in); diff --git a/src/iptv_input.c b/src/iptv_input.c index 57c994e9..9851c202 100644 --- a/src/iptv_input.c +++ b/src/iptv_input.c @@ -48,6 +48,11 @@ static pthread_mutex_t iptv_recvmutex; struct service_list iptv_all_services; /* All IPTV services */ static struct service_list iptv_active_services; /* Currently enabled */ +const idclass_t iptv_class = { + .ic_super = &service_class, + .ic_class = "iptv", +}; + /** * PAT parser. We only parse a single program. CRC has already been verified */ @@ -496,32 +501,19 @@ iptv_service_dtor(service_t *t) service_t * iptv_service_find(const char *id, int create) { - static int tally; service_t *t; - char buf[20]; if(id != NULL) { - if(strncmp(id, "iptv_", 5)) - return NULL; - - LIST_FOREACH(t, &iptv_all_services, s_group_link) - if(!strcmp(t->s_nicename, id)) // XXX(dvbreorg) - return t; + t = idnode_find(id, &iptv_class); + if(t != NULL) + return t; } if(create == 0) return NULL; - - if(id == NULL) { - tally++; - snprintf(buf, sizeof(buf), "iptv_%d", tally); - id = buf; - } else { - tally = MAX(atoi(id + 5), tally); - } - t = service_create(id, S_MPEG_TS); + t = service_create(id, S_MPEG_TS, &iptv_class); t->s_servicetype = ST_SDTV; t->s_start_feed = iptv_service_start; diff --git a/src/prop.c b/src/prop.c index 7050e8cb..d148b43a 100644 --- a/src/prop.c +++ b/src/prop.c @@ -1,47 +1,91 @@ +#include +#include + +#include "tvheadend.h" #include "prop.h" -#if 0 + + + +static const property_t * +prop_find(const property_t *p, const char *id) +{ + int i; + for(;p[i].id; i++) + if(!strcmp(id, p[i].id)) + return p; + return NULL; +} + + + +#define TO_FROM(x, y) ((x) << 16 | (y)) + /** * */ void -prop_write_values(void *ptr, const property_t p[], htsmsg_t *m) +prop_write_values(void *obj, const property_t *pl, htsmsg_t *m) { - int i = 0; - for(;p[i].id; i++) { - switch(p[i].type) { - case PT_BOOL: - htsmsg_add_bool(m, p[i].id, *(int *)(ptr + p[i].off)); + htsmsg_field_t *f; + HTSMSG_FOREACH(f, m) { + if(f->hmf_name == NULL) + continue; + const property_t *p = prop_find(pl, f->hmf_name); + if(p == NULL) { + fprintf(stderr, "Property %s unmappable\n", f->hmf_name); + continue; + } + + void *val = obj + p->off; + switch(TO_FROM(p->type, f->hmf_type)) { + case TO_FROM(PT_BOOL, HMF_BOOL): + *(int *)val = f->hmf_bool; break; - case PT_INT: - htsmsg_add_s32(m, p[i].id, *(int *)(ptr + p[i].off)); + case TO_FROM(PT_BOOL, HMF_S64): + *(int *)val = !!f->hmf_s64; break; - case PT_STR: - htsmsg_add_str(m, p[i].id, (const char *)(ptr + p[i].off)); + case TO_FROM(PT_INT, HMF_S64): + *(int *)val = f->hmf_s64; + break; + case TO_FROM(PT_STR, HMF_STR): + if(p->str_set != NULL) + p->str_set(obj, f->hmf_str); + else + mystrset(val, f->hmf_str); break; } } } -#endif + /** * */ void -prop_read_values(void *ptr, const property_t p[], htsmsg_t *m) +prop_read_values(void *obj, const property_t *p, htsmsg_t *m) { + const char *s; + if(p == NULL) + return; int i = 0; for(;p[i].id; i++) { + void *val = obj + p[i].off; switch(p[i].type) { case PT_BOOL: - htsmsg_add_bool(m, p[i].id, *(int *)(ptr + p[i].off)); + htsmsg_add_bool(m, p[i].id, *(int *)val); break; case PT_INT: - htsmsg_add_s32(m, p[i].id, *(int *)(ptr + p[i].off)); + htsmsg_add_s32(m, p[i].id, *(int *)val); break; case PT_STR: - htsmsg_add_str(m, p[i].id, (const char *)(ptr + p[i].off)); + if(p->str_get != NULL) + s = p->str_get(obj); + else + s = *(const char **)val; + if(s != NULL) + htsmsg_add_str(m, p[i].id, s); break; } } @@ -52,7 +96,7 @@ prop_read_values(void *ptr, const property_t p[], htsmsg_t *m) * */ htsmsg_t * -prop_get_values(void *ptr, const property_t p[]) +prop_get_values(void *ptr, const property_t *p) { htsmsg_t *m = htsmsg_create_map(); prop_read_values(ptr, p, m); @@ -64,10 +108,12 @@ prop_get_values(void *ptr, const property_t p[]) * */ void -prop_read_names(const property_t p[], htsmsg_t *m) +prop_read_names(const property_t *p, htsmsg_t *m) { + if(p == NULL) + return; int i = 0; - for(;p[i].name; i++) + for(;p[i].id; i++) htsmsg_add_str(m, p[i].id, p[i].name); } @@ -76,7 +122,7 @@ prop_read_names(const property_t p[], htsmsg_t *m) * */ htsmsg_t * -prop_get_names(const property_t p[]) +prop_get_names(const property_t *p) { htsmsg_t *m = htsmsg_create_map(); prop_read_names(p, m); diff --git a/src/prop.h b/src/prop.h index 148d67ed..4bfd89b2 100644 --- a/src/prop.h +++ b/src/prop.h @@ -14,11 +14,16 @@ typedef struct property { const char *name; prop_type_t type; size_t off; + + const char *(*str_get)(void *ptr); + void (*str_set)(void *ptr, const char *str); + } property_t; -void prop_read_values(void *ptr, const property_t p[], htsmsg_t *m); -htsmsg_t *prop_get_values(void *ptr, const property_t p[]); -void prop_read_names(const property_t p[], htsmsg_t *m); -htsmsg_t *prop_get_names(const property_t p[]); +void prop_read_values(void *ptr, const property_t *p, htsmsg_t *m); +htsmsg_t *prop_get_values(void *ptr, const property_t *p); +void prop_read_names(const property_t *p, htsmsg_t *m); +htsmsg_t *prop_get_names(const property_t *p); +void prop_write_values(void *ptr, const property_t *pl, htsmsg_t *m); diff --git a/src/rawtsinput.c b/src/rawtsinput.c index ee568302..ffc89e8d 100644 --- a/src/rawtsinput.c +++ b/src/rawtsinput.c @@ -48,6 +48,11 @@ typedef struct rawts { } rawts_t; +const idclass_t rawts_class = { + .ic_super = &service_class, + .ic_class = "rawts", +}; + /** * */ @@ -112,7 +117,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, S_MPEG_TS); + t = service_create(NULL, S_MPEG_TS, &rawts_class); t->s_flags |= S_DEBUG; t->s_dvb_service_id = sid; diff --git a/src/service.c b/src/service.c index 89608b82..4e12c045 100644 --- a/src/service.c +++ b/src/service.c @@ -50,12 +50,23 @@ #include "lang_codes.h" static void service_data_timeout(void *aux); +static const char *service_channel_get(void *obj); +static void service_channel_set(void *obj, const char *str); -static htsmsg_t *service_serialize(struct idnode *self); -static const idclass_t service_class = { +const idclass_t service_class = { .ic_class = "service", - .ic_serialize = service_serialize, + .ic_properties = (const property_t[]){ + { + "channel", "Channel", PT_STR, + + .str_get = service_channel_get, + .str_set = service_channel_set, + }, { + "enabled", "Enabled", PT_BOOL, + offsetof(service_t, s_enabled) + }, { + }} }; /** @@ -70,7 +81,7 @@ stream_init(elementary_stream_t *st) st->es_curdts = PTS_UNSET; st->es_curpts = PTS_UNSET; st->es_prevdts = PTS_UNSET; - + st->es_pcr_real_last = PTS_UNSET; st->es_pcr_last = PTS_UNSET; st->es_pcr_drift = 0; @@ -466,7 +477,7 @@ service_destroy(service_t *t) * Create and initialize a new service struct */ service_t * -service_create(const char *uuid, int source_type) +service_create(const char *uuid, int source_type, const idclass_t *idc) { service_t *t = calloc(1, sizeof(service_t)); @@ -486,7 +497,7 @@ service_create(const char *uuid, int source_type) streaming_pad_init(&t->s_streaming_pad); - idnode_insert(&t->s_id, uuid, &service_class); + idnode_insert(&t->s_id, uuid, idc); return t; } @@ -497,8 +508,7 @@ service_create(const char *uuid, int source_type) service_t * service_find_by_identifier(const char *identifier) { - idnode_t *id = idnode_find(identifier); - return id->in_class == &service_class ? (service_t *)id : NULL; + return idnode_find(identifier, &service_class); } @@ -648,6 +658,27 @@ service_map_channel(service_t *t, channel_t *ch, int save) t->s_config_save(t); } + +/** + * + */ +static const char *service_channel_get(void *obj) +{ + service_t *s = obj; + return s->s_ch ? s->s_ch->ch_name : NULL; +} + + +/** + * + */ +static void +service_channel_set(void *obj, const char *str) +{ + service_map_channel(obj, str ? channel_find_by_name(str, 1, 0) : NULL, 1); +} + + /** * */ @@ -1187,14 +1218,3 @@ htsmsg_t *servicetype_list ( void ) } return ret; } - - -/** - * - */ -static htsmsg_t * -service_serialize(struct idnode *self) -{ - service_t *s = (service_t *)self; - return s->s_serialize(s); -} diff --git a/src/service.h b/src/service.h index bfaf1346..be321aa3 100644 --- a/src/service.h +++ b/src/service.h @@ -25,6 +25,8 @@ #include "idnode.h" +extern const idclass_t service_class; + /** * Descrambler superclass * @@ -315,8 +317,6 @@ typedef struct service { void (*s_dtor)(struct service *t); - htsmsg_t *(*s_serialize)(struct service *s); - /* * Per source type structs */ @@ -551,7 +551,7 @@ void service_init(void); int service_start(service_t *t, int instance); -service_t *service_create(const char *uuid, int source_type); +service_t *service_create(const char *uuid, int source_type, const idclass_t *idc); void service_unref(service_t *t); diff --git a/src/serviceprobe.c b/src/serviceprobe.c index 2bdb5048..60909129 100644 --- a/src/serviceprobe.c +++ b/src/serviceprobe.c @@ -109,7 +109,7 @@ serviceprobe_thread(void *aux) } // XXX(dvbreorg) - checksubscr = 1; // !t->s_dvb_mux->tdmi_adapter->tda_skip_checksubscr; + checksubscr = !t->s_dvb_mux->dm_dn->dn_skip_checksubscr; if (checksubscr) { tvhlog(LOG_INFO, "serviceprobe", "%20s: checking...", diff --git a/src/tvheadend.h b/src/tvheadend.h index 6fddae3b..e6a4f6cc 100644 --- a/src/tvheadend.h +++ b/src/tvheadend.h @@ -27,6 +27,7 @@ #include #include #include +#include #include "queue.h" #include "avg.h" @@ -441,6 +442,12 @@ static inline const char *tvh_strbegins(const char *s1, const char *s2) return s1; } +static inline void mystrset(char **p, const char *s) +{ + free(*p); + *p = s ? strdup(s) : NULL; +} + int tvh_open(const char *pathname, int flags, mode_t mode); int tvh_socket(int domain, int type, int protocol); diff --git a/src/v4l.c b/src/v4l.c index 1e76ba1a..2822fc63 100644 --- a/src/v4l.c +++ b/src/v4l.c @@ -45,6 +45,10 @@ struct v4l_adapter_queue v4l_adapters; static void v4l_adapter_notify(v4l_adapter_t *va); +const idclass_t v4l_class = { + .ic_super = &service_class, + .ic_class = "v4l", +}; /** * @@ -354,7 +358,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, 0); + t = service_create(id, 0, &v4l_class); t->s_start_feed = v4l_service_start; t->s_refresh_feed = v4l_service_refresh; diff --git a/src/webui/extjs_dvb.c b/src/webui/extjs_dvb.c index 9f48ad33..e3a3bd18 100644 --- a/src/webui/extjs_dvb.c +++ b/src/webui/extjs_dvb.c @@ -151,7 +151,6 @@ extjs_dvbadapter(http_connection_t *hc, const char *remain, void *opaque) htsmsg_add_str(r, "name", tda->tda_displayname); 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); @@ -177,9 +176,6 @@ extjs_dvbadapter(http_connection_t *hc, const char *remain, void *opaque) s = http_arg_get(&hc->hc_req_args, "idleclose"); dvb_adapter_set_idleclose(tda, !!s); - s = http_arg_get(&hc->hc_req_args, "skip_checksubscr"); - dvb_adapter_set_skip_checksubscr(tda, !!s); - s = http_arg_get(&hc->hc_req_args, "qmon"); dvb_adapter_set_qmon(tda, !!s); @@ -708,17 +704,19 @@ extjs_dvbnetworks(http_connection_t *hc, const char *remain, void *opaque) 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 ? + idnode_t *n = idnode_find(s, NULL); + 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 = idnode_serialize(v[i]); - if(v[i]->in_class->ic_get_childs == NULL) - htsmsg_add_u32(m, "leaf", 1); - htsmsg_add_msg(out, NULL, m); + if(v != NULL) { + int i; + for(i = 0; v[i] != NULL; i++) { + htsmsg_t *m = idnode_serialize(v[i]); + 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); From ec88726175bc8f8eec5166c0e4c6b4279f59b871 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20=C3=96man?= Date: Sun, 31 Mar 2013 10:52:20 +0200 Subject: [PATCH 25/31] constify strtab --- src/hts_strtab.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/hts_strtab.h b/src/hts_strtab.h index f85f7fa6..38d47bcc 100644 --- a/src/hts_strtab.h +++ b/src/hts_strtab.h @@ -26,11 +26,11 @@ struct strtab { int val; }; -static int str2val0(const char *str, struct strtab tab[], int l) +static int str2val0(const char *str, const struct strtab tab[], int l) __attribute((unused)); static int -str2val0(const char *str, struct strtab tab[], int l) +str2val0(const char *str, const struct strtab tab[], int l) { int i; for(i = 0; i < l; i++) @@ -62,11 +62,11 @@ str2val0_def(const char *str, struct strtab tab[], int l, int def) str2val0_def(str, tab, sizeof(tab) / sizeof(tab[0]), def) -static const char * val2str0(int val, struct strtab tab[], int l) +static const char * val2str0(int val, const struct strtab tab[], int l) __attribute__((unused)); static const char * -val2str0(int val, struct strtab tab[], int l) +val2str0(int val, const struct strtab tab[], int l) { int i; for(i = 0; i < l; i++) From f6ce21f747bdbcf42c0284eae55027ed25eabb35 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20=C3=96man?= Date: Sun, 31 Mar 2013 13:23:42 +0200 Subject: [PATCH 26/31] Deal with POSTs that are empty --- src/http.c | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/src/http.c b/src/http.c index 07c88fc6..23ed67e8 100644 --- a/src/http.c +++ b/src/http.c @@ -387,8 +387,7 @@ static int http_cmd_post(http_connection_t *hc, htsbuf_queue_t *spill) { http_path_t *hp; - char *remain, *args, *v, *argv[2]; - int n; + char *remain, *args, *v; /* Set keep-alive status */ v = http_arg_get(&hc->hc_args, "Content-Length"); @@ -415,18 +414,17 @@ http_cmd_post(http_connection_t *hc, htsbuf_queue_t *spill) /* Parse content-type */ v = http_arg_get(&hc->hc_args, "Content-Type"); - if(v == NULL) { - http_error(hc, HTTP_STATUS_BAD_REQUEST); - return 0; - } - n = http_tokenize(v, argv, 2, ';'); - if(n == 0) { - http_error(hc, HTTP_STATUS_BAD_REQUEST); - return 0; - } + if(v != NULL) { + char *argv[2]; + int n = http_tokenize(v, argv, 2, ';'); + if(n == 0) { + http_error(hc, HTTP_STATUS_BAD_REQUEST); + return 0; + } - if(!strcmp(argv[0], "application/x-www-form-urlencoded")) - http_parse_get_args(hc, hc->hc_post_data); + if(!strcmp(argv[0], "application/x-www-form-urlencoded")) + http_parse_get_args(hc, hc->hc_post_data); + } hp = http_resolve(hc, &remain, &args); if(hp == NULL) { From 12a963e8393f8f1be62e75398414daa5765fd8dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20=C3=96man?= Date: Sun, 31 Mar 2013 13:28:02 +0200 Subject: [PATCH 27/31] Implement updating of properties from webui --- src/dvb/dvb_multiplex.c | 10 +- src/dvb/dvb_network.c | 39 +++--- src/dvb/dvb_service.c | 57 ++------- src/idnode.c | 85 +++++++++++-- src/idnode.h | 9 ++ src/prop.c | 184 ++++++++++++++++++++------- src/prop.h | 14 +- src/service.c | 16 ++- src/webui/extjs.c | 98 ++++++++++++++ src/webui/extjs_dvb.c | 45 +------ src/webui/static/app/dvb_networks.js | 68 ++++++++-- src/webui/webui.h | 5 + 12 files changed, 454 insertions(+), 176 deletions(-) diff --git a/src/dvb/dvb_multiplex.c b/src/dvb/dvb_multiplex.c index 5069549f..232670e9 100644 --- a/src/dvb/dvb_multiplex.c +++ b/src/dvb/dvb_multiplex.c @@ -65,6 +65,7 @@ static const idclass_t dvb_mux_class = { .ic_class = "dvbmux", .ic_get_title = dvb_mux_get_title, .ic_get_childs = dvb_mux_get_childs, + .ic_save = (void *)dvb_mux_save, .ic_properties = (const property_t[]){ { "enabled", "Enabled", PT_BOOL, @@ -517,6 +518,7 @@ dvb_mux_save(dvb_mux_t *dm) htsmsg_t *m = htsmsg_create_map(); htsmsg_add_u32(m, "enabled", dm->dm_enabled); + htsmsg_add_str(m, "uuid", idnode_uuid_as_str(&dm->dm_id)); htsmsg_add_u32(m, "transportstreamid", dm->dm_transport_stream_id); htsmsg_add_u32(m, "originalnetworkid", dm->dm_network_id); @@ -727,14 +729,20 @@ dvb_mux_create_by_msg(dvb_network_t *dn, htsmsg_t *m, const char *fname) if(htsmsg_get_u32(m, "enabled", &enabled)) enabled = 1; + const char *uuid = htsmsg_get_str(m, "uuid"); dm = dvb_mux_create(dn, &dmc, onid, tsid, htsmsg_get_str(m, "network"), NULL, enabled, htsmsg_get_u32_or_default(m, "needscan", 1), - htsmsg_get_str(m, "uuid")); + uuid); if(dm != NULL) { if((s = htsmsg_get_str(m, "default_authority"))) dm->dm_default_authority = strdup(s); + + + if(uuid == NULL) + // If mux didn't have UUID, write it to make sure UUID is stable + dvb_mux_save(dm); } return NULL; } diff --git a/src/dvb/dvb_network.c b/src/dvb/dvb_network.c index 3dc45902..feca6cb6 100644 --- a/src/dvb/dvb_network.c +++ b/src/dvb/dvb_network.c @@ -25,13 +25,24 @@ #include "settings.h" #include "dvb_support.h" + +const static struct strtab typetab[] = { + {"DVB-T", FE_OFDM}, + {"DVB-C", FE_QAM}, + {"DVB-S", FE_QPSK}, + {"ATSC", FE_ATSC}, +}; + + struct dvb_network_list dvb_networks; static idnode_t **dvb_network_get_childs(struct idnode *self); +static void dvb_network_save(idnode_t *in); static const idclass_t dvb_network_class = { .ic_class = "dvbnetwork", .ic_get_childs = dvb_network_get_childs, + .ic_save = dvb_network_save, .ic_properties = (const property_t[]){ { "autodiscovery", "Auto discovery", PT_BOOL, @@ -42,11 +53,7 @@ static const idclass_t dvb_network_class = { }, { "disable_pmt_monitor", "Disable PMT monitor", PT_BOOL, offsetof(dvb_network_t, dn_disable_pmt_monitor) - }, { - "disable_pmt_monitor", "Disable PMT monitor", PT_BOOL, - offsetof(dvb_network_t, dn_disable_pmt_monitor) - }, { - }}, + }, {}}, }; /** @@ -116,15 +123,19 @@ dvb_network_get_childs(struct idnode *self) static void dvb_network_load(htsmsg_t *m, const char *uuid) { - uint32_t fetype; + const char *s = htsmsg_get_str(m, "type"); + if(s == NULL) + return; - if(htsmsg_get_u32(m, "fetype", &fetype)) + int fetype = str2val(s, typetab); + if(fetype == -1) return; dvb_network_t *dn = dvb_network_create(fetype, uuid); if(dn == NULL) return; + htsmsg_delete_field(m, "type"); prop_write_values(dn, dvb_network_class.ic_properties, m); dvb_mux_load(dn); dvb_network_schedule_initial_scan(dn); @@ -135,16 +146,19 @@ dvb_network_load(htsmsg_t *m, const char *uuid) * */ static void -dvb_network_save(dvb_network_t *dn) +dvb_network_save(idnode_t *in) { + dvb_network_t *dn = (dvb_network_t *)in; htsmsg_t *m = htsmsg_create_map(); lock_assert(&global_lock); - prop_read_values(dn, dvb_network_class.ic_properties, m); + htsmsg_add_str(m, "type", val2str(dn->dn_fe_type, typetab)); + prop_read_values(in, dvb_network_class.ic_properties, m); hts_settings_save(m, "dvb/networks/%s/config", - idnode_uuid_as_str(&dn->dn_id)); + idnode_uuid_as_str(in)); + htsmsg_destroy(m); } @@ -185,11 +199,6 @@ 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; diff --git a/src/dvb/dvb_service.c b/src/dvb/dvb_service.c index 748b445c..0fc6062a 100644 --- a/src/dvb/dvb_service.c +++ b/src/dvb/dvb_service.c @@ -175,6 +175,7 @@ dvb_service_save(service_t *t) lock_assert(&global_lock); + htsmsg_add_str(m, "uuid", idnode_uuid_as_str(&t->s_id)); htsmsg_add_u32(m, "service_id", t->s_dvb_service_id); htsmsg_add_u32(m, "pmt", t->s_pmt_pid); htsmsg_add_u32(m, "stype", t->s_servicetype); @@ -246,7 +247,8 @@ dvb_service_load(dvb_mux_t *dm) if(htsmsg_get_u32(c, "pmt", &pmt)) continue; - t = dvb_service_find(dm, sid, pmt, f->hmf_name); + const char *uuid = htsmsg_get_str(c, "uuid"); + t = dvb_service_find(dm, sid, pmt, uuid); htsmsg_get_u32(c, "stype", &t->s_servicetype); if(htsmsg_get_u32(c, "scrambled", &u32)) @@ -285,6 +287,12 @@ dvb_service_load(dvb_mux_t *dm) if(s && u32) service_map_channel(t, channel_find_by_name(s, 1, 0), 0); + + if(uuid == NULL) { + // If service config on disk lacked UUID (for whatever reason), + // write it back + dvb_service_save(t); + } } htsmsg_destroy(l); } @@ -422,53 +430,6 @@ dvb_service_find2(dvb_mux_t *dm, uint16_t sid, int pmt_pid, return t; } -#if 0 -/** - * - */ -static htsmsg_t * -dvb_service_serialize(service_t *s) -{ - dvb_mux_t *dm = s->s_dvb_mux; - htsmsg_t *m = htsmsg_create_map(); - char buf[100]; - - if(s->s_svcname) { - htsmsg_add_str(m, "text", s->s_svcname); - } else { - snprintf(buf, sizeof(buf), "Service-0x%04x", - s->s_dvb_service_id); - htsmsg_add_str(m, "text", buf); - } - - htsmsg_add_u32(m, "enabled", s->s_enabled); - htsmsg_add_u32(m, "channel", s->s_channel_number); - - htsmsg_add_u32(m, "sid", s->s_dvb_service_id); - htsmsg_add_u32(m, "pmt", s->s_pmt_pid); - htsmsg_add_u32(m, "pcr", s->s_pcr_pid); - - htsmsg_add_str(m, "type", service_servicetype_txt(s)); - - htsmsg_add_str(m, "svcname", s->s_svcname ?: ""); - htsmsg_add_str(m, "provider", s->s_provider ?: ""); - - htsmsg_add_str(m, "network", dm->dm_network_name ?: ""); - - htsmsg_add_str(m, "mux", dvb_mux_nicefreq(dm)); - - if(s->s_ch != NULL) - htsmsg_add_str(m, "channelname", s->s_ch->ch_name); - - if(s->s_dvb_charset != NULL) - htsmsg_add_str(m, "dvb_charset", s->s_dvb_charset); - - htsmsg_add_u32(m, "dvb_eit_enable", s->s_dvb_eit_enable); - - return m; -} -#endif - /** * diff --git a/src/idnode.c b/src/idnode.c index ec3211ea..9394c578 100644 --- a/src/idnode.c +++ b/src/idnode.c @@ -166,6 +166,27 @@ idnode_unlink(idnode_t *in) } +/** + * Recursive to get superclass nodes first + */ +static void +add_descriptors(struct idnode *self, const idclass_t *ic, htsmsg_t *p) +{ + if(ic->ic_super != NULL) + add_descriptors(self, ic->ic_super, p); + + if(TAILQ_FIRST(&p->hm_fields) != NULL) { + // Only add separator if not empty + htsmsg_t *m = htsmsg_create_map(); + htsmsg_add_str(m, "caption", ic->ic_caption ?: ic->ic_class); + htsmsg_add_str(m, "type", "separator"); + htsmsg_add_msg(p, NULL, m); + } + + prop_add_descriptors_to_msg(self, ic->ic_properties, p); +} + + /** * */ @@ -179,24 +200,70 @@ idnode_serialize(struct idnode *self) } else { m = htsmsg_create_map(); - htsmsg_t *p = htsmsg_create_map(); - htsmsg_t *pn = htsmsg_create_map(); - if(c->ic_get_title != NULL) { htsmsg_add_str(m, "text", c->ic_get_title(self)); } else { htsmsg_add_str(m, "text", idnode_uuid_as_str(self)); } - for(;c != NULL; c = c->ic_super) { - prop_read_values(self, c->ic_properties, p); - prop_read_names(c->ic_properties, pn); - } + htsmsg_t *p = htsmsg_create_list(); + add_descriptors(self, c, p); - htsmsg_add_msg(m, "properties", p); - htsmsg_add_msg(m, "propertynames", pn); + htsmsg_add_msg(m, "descriptors", p); htsmsg_add_str(m, "id", idnode_uuid_as_str(self)); } return m; } + +/** + * + */ +static void +idnode_save(idnode_t *in) +{ + const idclass_t *ic = in->in_class; + for(; ic != NULL; ic = ic->ic_super) { + if(ic->ic_save != NULL) { + ic->ic_save(in); + return; + } + } +} + + +/** + * + */ +void +idnode_set_prop(idnode_t *in, const char *key, const char *value) +{ + const idclass_t *ic = in->in_class; + int do_save = 0; + for(;ic != NULL; ic = ic->ic_super) { + int x = prop_set(in, ic->ic_properties, key, value); + if(x == -1) + continue; + do_save |= x; + break; + } + if(do_save) + idnode_save(in); +} + + +/** + * + */ +void +idnode_update_all_props(idnode_t *in, + const char *(*getvalue)(void *opaque, const char *key), + void *opaque) +{ + const idclass_t *ic = in->in_class; + int do_save = 0; + for(;ic != NULL; ic = ic->ic_super) + do_save |= prop_update_all(in, ic->ic_properties, getvalue, opaque); + if(do_save) + idnode_save(in); +} diff --git a/src/idnode.h b/src/idnode.h index a5a0901b..a71b8828 100644 --- a/src/idnode.h +++ b/src/idnode.h @@ -9,9 +9,11 @@ struct idnode; typedef struct idclass { const struct idclass *ic_super; const char *ic_class; + const char *ic_caption; struct htsmsg *(*ic_serialize)(struct idnode *self); struct idnode **(*ic_get_childs)(struct idnode *self); const char *(*ic_get_title)(struct idnode *self); + void (*ic_save)(struct idnode *self); const property_t *ic_properties; } idclass_t; @@ -33,3 +35,10 @@ void *idnode_find(const char *uuid, const idclass_t *class); void idnode_unlink(idnode_t *in); htsmsg_t *idnode_serialize(struct idnode *self); + +void idnode_set_prop(idnode_t *in, const char *key, const char *value); + +void idnode_update_all_props(idnode_t *in, + const char *(*getvalue)(void *opaque, + const char *key), + void *opaque); diff --git a/src/prop.c b/src/prop.c index d148b43a..559130dc 100644 --- a/src/prop.c +++ b/src/prop.c @@ -7,13 +7,33 @@ + +/** + * + */ +static int +str_to_bool(const char *s) +{ + if(s == NULL) + return 0; + int v = atoi(s); + if(v) + return 1; + if(!strcasecmp(s, "on") || + !strcasecmp(s, "true") || + !strcasecmp(s, "yes")) + return 1; + return 0; +} + + static const property_t * prop_find(const property_t *p, const char *id) { - int i; + int i = 0; for(;p[i].id; i++) if(!strcmp(id, p[i].id)) - return p; + return p + i; return NULL; } @@ -63,68 +83,142 @@ prop_write_values(void *obj, const property_t *pl, htsmsg_t *m) /** * */ -void -prop_read_values(void *obj, const property_t *p, htsmsg_t *m) +static void +prop_read_value(void *obj, const property_t *p, htsmsg_t *m, const char *name) { const char *s; - if(p == NULL) - return; - int i = 0; - for(;p[i].id; i++) { - void *val = obj + p[i].off; - switch(p[i].type) { - case PT_BOOL: - htsmsg_add_bool(m, p[i].id, *(int *)val); - break; - case PT_INT: - htsmsg_add_s32(m, p[i].id, *(int *)val); - break; - case PT_STR: - if(p->str_get != NULL) - s = p->str_get(obj); - else - s = *(const char **)val; - if(s != NULL) - htsmsg_add_str(m, p[i].id, s); - break; - } + const void *val = obj + p->off; + + switch(p->type) { + case PT_BOOL: + htsmsg_add_bool(m, name, *(int *)val); + break; + case PT_INT: + htsmsg_add_s32(m, name, *(int *)val); + break; + case PT_STR: + if(p->str_get != NULL) + s = p->str_get(obj); + else + s = *(const char **)val; + if(s != NULL) + htsmsg_add_str(m, name, s); + break; } } - -/** - * - */ -htsmsg_t * -prop_get_values(void *ptr, const property_t *p) -{ - htsmsg_t *m = htsmsg_create_map(); - prop_read_values(ptr, p, m); - return m; -} - - /** * */ void -prop_read_names(const property_t *p, htsmsg_t *m) +prop_read_values(void *obj, const property_t *p, htsmsg_t *m) { if(p == NULL) return; int i = 0; for(;p[i].id; i++) - htsmsg_add_str(m, p[i].id, p[i].name); + prop_read_value(obj, p+i, m, p[i].id); } /** * */ -htsmsg_t * -prop_get_names(const property_t *p) +const static struct strtab typetab[] = { + { "bool", PT_BOOL }, + { "int", PT_INT }, + { "str", PT_STR }, +}; + + +/** + * + */ +void +prop_add_descriptors_to_msg(void *obj, const property_t *p, htsmsg_t *msg) { - htsmsg_t *m = htsmsg_create_map(); - prop_read_names(p, m); - return m; + if(p == NULL) + return; + int i = 0; + for(;p[i].id; i++) { + htsmsg_t *m = htsmsg_create_map(); + htsmsg_add_str(m, "id", p[i].id); + htsmsg_add_str(m, "caption", p[i].name); + htsmsg_add_str(m, "type", val2str(p[i].type, typetab) ?: "unknown"); + prop_read_value(obj, p+i, m, "value"); + htsmsg_add_msg(msg, NULL, m); + } +} + + +/** + * value can be NULL + * + * Return 1 if we actually changed something + */ +static int +prop_seti(void *obj, const property_t *p, const char *value) +{ + int i32; + const char *s; + + void *val = obj + p->off; + switch(p->type) { + + case PT_BOOL: + i32 = str_to_bool(value); + if(0) + case PT_INT: + i32 = value ? atoi(value) : 0; + if(*(int *)val == i32) + return 0; // Already set + *(int *)val = i32; + break; + + case PT_STR: + if(p->str_get != NULL) + s = p->str_get(obj); + else + s = *(const char **)val; + + if(!strcmp(s ?: "", value ?: "")) + return 0; + + if(p->str_set != NULL) + p->str_set(obj, value); + else + mystrset(val, value); + break; + } + + return 1; + +} + + +/** + * Return 1 if something changed + */ +int +prop_set(void *obj, const property_t *p, const char *key, const char *value) +{ + if((p = prop_find(p, key)) == NULL) + return -1; + return prop_seti(obj, p, value); +} + + +/** + * + */ +int +prop_update_all(void *obj, const property_t *p, + const char *(*getvalue)(void *opaque, const char *key), + void *opaque) +{ + int i = 0; + int r = 0; + for(; p[i].id; i++) + r |= prop_seti(obj, p+i, getvalue(opaque, p[i].id)); + return r; } diff --git a/src/prop.h b/src/prop.h index 4bfd89b2..178bb287 100644 --- a/src/prop.h +++ b/src/prop.h @@ -22,8 +22,14 @@ typedef struct property { -void prop_read_values(void *ptr, const property_t *p, htsmsg_t *m); -htsmsg_t *prop_get_values(void *ptr, const property_t *p); -void prop_read_names(const property_t *p, htsmsg_t *m); -htsmsg_t *prop_get_names(const property_t *p); +void prop_add_descriptors_to_msg(void *obj, const property_t *p, htsmsg_t *msg); + void prop_write_values(void *ptr, const property_t *pl, htsmsg_t *m); + +void prop_read_values(void *obj, const property_t *p, htsmsg_t *m); + +int prop_set(void *obj, const property_t *p, const char *key, const char *val); + +int prop_update_all(void *obj, const property_t *p, + const char *(*getvalue)(void *opaque, const char *key), + void *opaque); diff --git a/src/service.c b/src/service.c index 4e12c045..e93da9af 100644 --- a/src/service.c +++ b/src/service.c @@ -52,10 +52,12 @@ static void service_data_timeout(void *aux); static const char *service_channel_get(void *obj); static void service_channel_set(void *obj, const char *str); - +static void service_save(struct idnode *self); const idclass_t service_class = { .ic_class = "service", + .ic_caption = "Service", + .ic_save = service_save, .ic_properties = (const property_t[]){ { "channel", "Channel", PT_STR, @@ -675,7 +677,7 @@ static const char *service_channel_get(void *obj) static void service_channel_set(void *obj, const char *str) { - service_map_channel(obj, str ? channel_find_by_name(str, 1, 0) : NULL, 1); + service_map_channel(obj, str ? channel_find_by_name(str, 1, 0) : NULL, 0); } @@ -931,6 +933,16 @@ service_request_save(service_t *t, int restart) } +/** + * + */ +static void +service_save(struct idnode *self) +{ + service_t *s = (service_t *)self; + s->s_config_save(s); +} + /** * */ diff --git a/src/webui/extjs.c b/src/webui/extjs.c index 841840b8..4f8e3bac 100644 --- a/src/webui/extjs.c +++ b/src/webui/extjs.c @@ -1900,6 +1900,103 @@ extjs_config(http_connection_t *hc, const char *remain, void *opaque) return 0; } + +/** + * + */ +int +extjs_get_idnode(http_connection_t *hc, const char *remain, void *opaque, + idnode_t **(*rootfn)(void)) +{ + htsbuf_queue_t *hq = &hc->hc_reply; + const char *s = http_arg_get(&hc->hc_req_args, "node"); + htsmsg_t *out = NULL; + + if(s == NULL) + return HTTP_STATUS_BAD_REQUEST; + + pthread_mutex_lock(&global_lock); + + if(http_access_verify(hc, ACCESS_ADMIN)) { + pthread_mutex_unlock(&global_lock); + return HTTP_STATUS_UNAUTHORIZED; + } + + out = htsmsg_create_list(); + idnode_t **v; + + if(!strcmp(s, "root")) { + v = rootfn(); + } else { + idnode_t *n = idnode_find(s, NULL); + v = n != NULL && n->in_class->ic_get_childs != NULL ? + n->in_class->ic_get_childs(n) : NULL; + } + + if(v != NULL) { + int i; + for(i = 0; v[i] != NULL; i++) { + htsmsg_t *m = idnode_serialize(v[i]); + 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"); + return 0; +} + + +static const char * +get_prop_value(void *opaque, const char *key) +{ + http_connection_t *hc = opaque; + return http_arg_get(&hc->hc_req_args, key); +} + +/** + * + */ +static int +extjs_item_update(http_connection_t *hc, const char *remain, void *opaque) +{ + htsbuf_queue_t *hq = &hc->hc_reply; + htsmsg_t *out = NULL; + + if(remain == NULL) + return HTTP_STATUS_BAD_REQUEST; + + pthread_mutex_lock(&global_lock); + + idnode_t *n = idnode_find(remain, NULL); + + if(n == NULL) { + pthread_mutex_unlock(&global_lock); + return 404; + } + + idnode_update_all_props(n, get_prop_value, hc); + + pthread_mutex_unlock(&global_lock); + + out = htsmsg_create_map(); + htsmsg_add_u32(out, "success", 1); + htsmsg_json_serialize(out, hq, 0); + htsmsg_destroy(out); + http_output_content(hc, "text/x-json; charset=UTF-8"); + return 0; +} + + + + /** * WEB user interface */ @@ -1926,6 +2023,7 @@ extjs_start(void) http_path_add("/iptv/services", NULL, extjs_iptvservices, ACCESS_ADMIN); http_path_add("/servicedetails", NULL, extjs_servicedetails, ACCESS_ADMIN); http_path_add("/tv/adapter", NULL, extjs_tvadapter, ACCESS_ADMIN); + http_path_add("/item/update", NULL, extjs_item_update, ACCESS_ADMIN); #if ENABLE_LINUXDVB extjs_start_dvb(); diff --git a/src/webui/extjs_dvb.c b/src/webui/extjs_dvb.c index e3a3bd18..4173b425 100644 --- a/src/webui/extjs_dvb.c +++ b/src/webui/extjs_dvb.c @@ -684,53 +684,10 @@ extjs_list_dvb_adapters(htsmsg_t *array) static int extjs_dvbnetworks(http_connection_t *hc, const char *remain, void *opaque) { - htsbuf_queue_t *hq = &hc->hc_reply; - const char *s = http_arg_get(&hc->hc_req_args, "node"); - htsmsg_t *out = NULL; - - if(s == NULL) - return HTTP_STATUS_BAD_REQUEST; - - pthread_mutex_lock(&global_lock); - - if(http_access_verify(hc, ACCESS_ADMIN)) { - pthread_mutex_unlock(&global_lock); - return HTTP_STATUS_UNAUTHORIZED; - } - - out = htsmsg_create_list(); - idnode_t **v; - - if(!strcmp(s, "root")) { - v = dvb_network_root(); - } else { - idnode_t *n = idnode_find(s, NULL); - v = n != NULL && n->in_class->ic_get_childs != NULL ? - n->in_class->ic_get_childs(n) : NULL; - } - - if(v != NULL) { - int i; - for(i = 0; v[i] != NULL; i++) { - htsmsg_t *m = idnode_serialize(v[i]); - 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"); - return 0; + return extjs_get_idnode(hc, remain, opaque, &dvb_network_root); } - /** * DVB WEB user interface */ diff --git a/src/webui/static/app/dvb_networks.js b/src/webui/static/app/dvb_networks.js index be0ecab6..ee028417 100644 --- a/src/webui/static/app/dvb_networks.js +++ b/src/webui/static/app/dvb_networks.js @@ -1,14 +1,66 @@ - - tvheadend.item_editor = function(item) { - var propsGrid = new Ext.grid.PropertyGrid({ - flex:1, - padding: 5, - propertyNames: item.propertynames, - source: item.properties + + var fields = [] + console.log(fields); + for (var idx in item.descriptors) { + var f = item.descriptors[idx]; + switch(f.type) { + case 'str': + fields.push({ + fieldLabel: f.caption, + name: f.id, + value: f.value + }); + break; + + case 'bool': + fields.push({ + xtype: 'checkbox', + fieldLabel: f.caption, + name: f.id, + checked: f.value + }); + break; + + case 'separator': + fields.push({ + xtype: 'label', + fieldLabel: f.caption, + }); + break; + } + } + + var panel = new Ext.FormPanel({ + labelWidth: 75, // label settings here cascade unless overridden + url:'save-form.php', + frame:true, + title: 'Parameters', + bodyStyle:'padding:5px 5px 0', + width: 350, + defaults: {width: 230}, + defaultType: 'textfield', + items: fields, + + buttons: [{ + text: 'Save', + handler: function(){ + if(panel.getForm().isValid()){ + panel.getForm().submit({ + url: 'item/update/' + item.id, + waitMsg : 'Saving Data...' + }); + } + } + },{ + text: 'Reset', + handler: function(){ + panel.getForm().reset(); + } + }] }); - return propsGrid; + return panel; } diff --git a/src/webui/webui.h b/src/webui/webui.h index cbbec569..300d32f6 100644 --- a/src/webui/webui.h +++ b/src/webui/webui.h @@ -20,6 +20,8 @@ #define WEBUI_H_ #include "htsmsg.h" +#include "idnode.h" +#include "http.h" void webui_init(void); @@ -45,6 +47,9 @@ void extjs_service_update(htsmsg_t *in); void extjs_service_delete(htsmsg_t *in); +int extjs_get_idnode(http_connection_t *hc, const char *remain, void *opaque, + idnode_t **(*rootfn)(void)); + /** * */ From 9b5d47e21a84ca40cdd898ddf3f8c9b93534c6e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20=C3=96man?= Date: Sun, 31 Mar 2013 14:15:40 +0200 Subject: [PATCH 28/31] Add code for updating webui when title / descriptors are changed in tvh --- src/idnode.c | 51 ++++++++++++++++++++++++---- src/idnode.h | 3 ++ src/prop.c | 4 +-- src/prop.h | 2 ++ src/webui/static/app/dvb_networks.js | 16 ++++++++- 5 files changed, 66 insertions(+), 10 deletions(-) diff --git a/src/idnode.c b/src/idnode.c index 9394c578..b109d1ca 100644 --- a/src/idnode.c +++ b/src/idnode.c @@ -5,6 +5,7 @@ #include #include "idnode.h" +#include "notify.h" static int randfd = 0; @@ -187,6 +188,21 @@ add_descriptors(struct idnode *self, const idclass_t *ic, htsmsg_t *p) } +/** + * + */ +static const char * +idnode_get_title(idnode_t *in) +{ + if(in->in_class->ic_get_title != NULL) { + return in->in_class->ic_get_title(in); + } else { + return idnode_uuid_as_str(in); + } +} + + + /** * */ @@ -199,12 +215,7 @@ idnode_serialize(struct idnode *self) m = c->ic_serialize(self); } else { m = htsmsg_create_map(); - - if(c->ic_get_title != NULL) { - htsmsg_add_str(m, "text", c->ic_get_title(self)); - } else { - htsmsg_add_str(m, "text", idnode_uuid_as_str(self)); - } + htsmsg_add_str(m, "text", idnode_get_title(self)); htsmsg_t *p = htsmsg_create_list(); add_descriptors(self, c, p); @@ -223,12 +234,24 @@ static void idnode_save(idnode_t *in) { const idclass_t *ic = in->in_class; + for(; ic != NULL; ic = ic->ic_super) { if(ic->ic_save != NULL) { ic->ic_save(in); - return; + break; } } + + // Tell about updated descriptors + + htsmsg_t *m = htsmsg_create_map(); + htsmsg_add_str(m, "id", idnode_uuid_as_str(in)); + + htsmsg_t *p = htsmsg_create_list(); + add_descriptors(in, in->in_class, p); + htsmsg_add_msg(m, "descriptors", p); + + notify_by_msg("idnodeDescriptorsChanged", m); } @@ -267,3 +290,17 @@ idnode_update_all_props(idnode_t *in, if(do_save) idnode_save(in); } + + +/** + * + */ +void +idnode_notify_title_changed(void *obj) +{ + idnode_t *in = obj; + htsmsg_t *m = htsmsg_create_map(); + htsmsg_add_str(m, "id", idnode_uuid_as_str(in)); + htsmsg_add_str(m, "text", idnode_get_title(in)); + notify_by_msg("idnodeNameChanged", m); +} diff --git a/src/idnode.h b/src/idnode.h index a71b8828..52fa1d24 100644 --- a/src/idnode.h +++ b/src/idnode.h @@ -42,3 +42,6 @@ void idnode_update_all_props(idnode_t *in, const char *(*getvalue)(void *opaque, const char *key), void *opaque); + +void idnode_notify_title_changed(void *obj); + diff --git a/src/prop.c b/src/prop.c index 559130dc..a77d9c04 100644 --- a/src/prop.c +++ b/src/prop.c @@ -190,9 +190,9 @@ prop_seti(void *obj, const property_t *p, const char *value) mystrset(val, value); break; } - + if(p->notify) + p->notify(obj); return 1; - } diff --git a/src/prop.h b/src/prop.h index 178bb287..8332cea5 100644 --- a/src/prop.h +++ b/src/prop.h @@ -18,6 +18,8 @@ typedef struct property { const char *(*str_get)(void *ptr); void (*str_set)(void *ptr, const char *str); + void (*notify)(void *ptr); + } property_t; diff --git a/src/webui/static/app/dvb_networks.js b/src/webui/static/app/dvb_networks.js index ee028417..31849736 100644 --- a/src/webui/static/app/dvb_networks.js +++ b/src/webui/static/app/dvb_networks.js @@ -2,7 +2,7 @@ tvheadend.item_editor = function(item) { var fields = [] - console.log(fields); + for (var idx in item.descriptors) { var f = item.descriptors[idx]; switch(f.type) { @@ -98,6 +98,20 @@ tvheadend.dvb_networks = function() { } }); + tvheadend.comet.on('idnodeNameChanged', function(o) { + var n = tree.getNodeById(o.id); + if(n) { + n.setText(o.text); + } + }); + + tvheadend.comet.on('idnodeDescriptorsChanged', function(o) { + var n = tree.getNodeById(o.id); + if(n) { + n.attributes.descriptors = o.descriptors; + } + }); + var panel = new Ext.Panel({ title: 'DVB Networks', From 9414fd4d45283be0ffe2cdd6cc6141000b6f4ac0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20=C3=96man?= Date: Sun, 31 Mar 2013 14:20:04 +0200 Subject: [PATCH 29/31] idnode: Rename descriptors -> parameters --- src/idnode.c | 18 +++++++++--------- src/prop.c | 2 +- src/prop.h | 2 +- src/webui/static/app/dvb_networks.js | 8 ++++---- 4 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/idnode.c b/src/idnode.c index b109d1ca..1f2a221d 100644 --- a/src/idnode.c +++ b/src/idnode.c @@ -171,10 +171,10 @@ idnode_unlink(idnode_t *in) * Recursive to get superclass nodes first */ static void -add_descriptors(struct idnode *self, const idclass_t *ic, htsmsg_t *p) +add_params(struct idnode *self, const idclass_t *ic, htsmsg_t *p) { if(ic->ic_super != NULL) - add_descriptors(self, ic->ic_super, p); + add_params(self, ic->ic_super, p); if(TAILQ_FIRST(&p->hm_fields) != NULL) { // Only add separator if not empty @@ -184,7 +184,7 @@ add_descriptors(struct idnode *self, const idclass_t *ic, htsmsg_t *p) htsmsg_add_msg(p, NULL, m); } - prop_add_descriptors_to_msg(self, ic->ic_properties, p); + prop_add_params_to_msg(self, ic->ic_properties, p); } @@ -218,9 +218,9 @@ idnode_serialize(struct idnode *self) htsmsg_add_str(m, "text", idnode_get_title(self)); htsmsg_t *p = htsmsg_create_list(); - add_descriptors(self, c, p); + add_params(self, c, p); - htsmsg_add_msg(m, "descriptors", p); + htsmsg_add_msg(m, "params", p); htsmsg_add_str(m, "id", idnode_uuid_as_str(self)); } @@ -242,16 +242,16 @@ idnode_save(idnode_t *in) } } - // Tell about updated descriptors + // Tell about updated parameters htsmsg_t *m = htsmsg_create_map(); htsmsg_add_str(m, "id", idnode_uuid_as_str(in)); htsmsg_t *p = htsmsg_create_list(); - add_descriptors(in, in->in_class, p); - htsmsg_add_msg(m, "descriptors", p); + add_params(in, in->in_class, p); + htsmsg_add_msg(m, "params", p); - notify_by_msg("idnodeDescriptorsChanged", m); + notify_by_msg("idnodeParamsChanged", m); } diff --git a/src/prop.c b/src/prop.c index a77d9c04..ac7a92c7 100644 --- a/src/prop.c +++ b/src/prop.c @@ -135,7 +135,7 @@ const static struct strtab typetab[] = { * */ void -prop_add_descriptors_to_msg(void *obj, const property_t *p, htsmsg_t *msg) +prop_add_params_to_msg(void *obj, const property_t *p, htsmsg_t *msg) { if(p == NULL) return; diff --git a/src/prop.h b/src/prop.h index 8332cea5..e7bc63e9 100644 --- a/src/prop.h +++ b/src/prop.h @@ -24,7 +24,7 @@ typedef struct property { -void prop_add_descriptors_to_msg(void *obj, const property_t *p, htsmsg_t *msg); +void prop_add_params_to_msg(void *obj, const property_t *p, htsmsg_t *msg); void prop_write_values(void *ptr, const property_t *pl, htsmsg_t *m); diff --git a/src/webui/static/app/dvb_networks.js b/src/webui/static/app/dvb_networks.js index 31849736..eb99f540 100644 --- a/src/webui/static/app/dvb_networks.js +++ b/src/webui/static/app/dvb_networks.js @@ -3,8 +3,8 @@ tvheadend.item_editor = function(item) { var fields = [] - for (var idx in item.descriptors) { - var f = item.descriptors[idx]; + for (var idx in item.params) { + var f = item.params[idx]; switch(f.type) { case 'str': fields.push({ @@ -105,10 +105,10 @@ tvheadend.dvb_networks = function() { } }); - tvheadend.comet.on('idnodeDescriptorsChanged', function(o) { + tvheadend.comet.on('idnodeParamsChanged', function(o) { var n = tree.getNodeById(o.id); if(n) { - n.attributes.descriptors = o.descriptors; + n.attributes.params = o.params; } }); From bc0d93dd7211654b1b64d20029f7396458a5c9de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20=C3=96man?= Date: Sun, 31 Mar 2013 14:20:46 +0200 Subject: [PATCH 30/31] Add support renaming of DVB networks --- src/dvb/dvb.h | 2 ++ src/dvb/dvb_network.c | 20 ++++++++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/src/dvb/dvb.h b/src/dvb/dvb.h index db72f1cd..f81d46ef 100644 --- a/src/dvb/dvb.h +++ b/src/dvb/dvb.h @@ -110,6 +110,8 @@ typedef struct dvb_network { uint32_t dn_nitoid; uint32_t dn_skip_checksubscr; + char *dn_name; // User configured name + struct th_dvb_adapter_list dn_adapters; } dvb_network_t; diff --git a/src/dvb/dvb_network.c b/src/dvb/dvb_network.c index feca6cb6..74c8a14b 100644 --- a/src/dvb/dvb_network.c +++ b/src/dvb/dvb_network.c @@ -37,14 +37,20 @@ const static struct strtab typetab[] = { struct dvb_network_list dvb_networks; static idnode_t **dvb_network_get_childs(struct idnode *self); +static const char *dvb_network_get_title(struct idnode *self); static void dvb_network_save(idnode_t *in); static const idclass_t dvb_network_class = { .ic_class = "dvbnetwork", .ic_get_childs = dvb_network_get_childs, + .ic_get_title = dvb_network_get_title, .ic_save = dvb_network_save, .ic_properties = (const property_t[]){ { + "name", "Name", PT_STR, + offsetof(dvb_network_t, dn_name), + .notify = &idnode_notify_title_changed, + }, { "autodiscovery", "Auto discovery", PT_BOOL, offsetof(dvb_network_t, dn_autodiscovery) }, { @@ -62,6 +68,7 @@ static const idclass_t dvb_network_class = { dvb_network_t * dvb_network_create(int fe_type, const char *uuid) { + char defname[64]; dvb_network_t *dn = calloc(1, sizeof(dvb_network_t)); if(idnode_insert(&dn->dn_id, uuid, &dvb_network_class)) { free(dn); @@ -73,12 +80,25 @@ dvb_network_create(int fe_type, const char *uuid) TAILQ_INIT(&dn->dn_initial_scan_current_queue); dn->dn_autodiscovery = fe_type != FE_QPSK; + snprintf(defname, sizeof(defname), "%s network", val2str(fe_type, typetab)); + dn->dn_name = strdup(defname); LIST_INSERT_HEAD(&dvb_networks, dn, dn_global_link); return dn; } +/** + * + */ +static const char * +dvb_network_get_title(struct idnode *self) +{ + dvb_network_t *dn = (dvb_network_t *)self; + return dn->dn_name; +} + + /** * */ From 20e94bc17db38a20677916a563da36f96f32d10c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20=C3=96man?= Date: Tue, 23 Apr 2013 15:46:43 +0200 Subject: [PATCH 31/31] Initial work on DVB hw tree --- Makefile | 4 +- src/capmt.c | 5 +- src/dvb/dvb.c | 3 +- src/dvb/dvb.h | 89 ++++++----- src/dvb/dvb_fe.c | 2 +- src/dvb/dvb_hardware.c | 82 ++++++++++ src/dvb/dvb_linux.c | 218 +++++++++++++++++++++++++++ src/dvb/dvb_multiplex.c | 5 +- src/dvb/dvb_support.c | 12 -- src/idnode.c | 44 +++++- src/idnode.h | 6 + src/tvadapters.c | 40 +++++ src/tvadapters.h | 5 + src/webui/extjs.c | 24 ++- src/webui/extjs_dvb.c | 20 +-- src/webui/extjs_v4l.c | 2 + src/webui/statedump.c | 6 - src/webui/static/app/dvb_networks.js | 24 ++- src/webui/static/app/tvadapters.js | 9 +- src/webui/webui.h | 2 - 20 files changed, 505 insertions(+), 97 deletions(-) create mode 100644 src/dvb/dvb_hardware.c create mode 100644 src/dvb/dvb_linux.c create mode 100644 src/tvadapters.c create mode 100644 src/tvadapters.h diff --git a/Makefile b/Makefile index f073c5d5..3620d796 100644 --- a/Makefile +++ b/Makefile @@ -65,6 +65,7 @@ endif SRCS = src/main.c \ src/idnode.c \ src/prop.c \ + src/tvadapters.c \ src/utils.c \ src/wrappers.c \ src/version.c \ @@ -154,7 +155,8 @@ SRCS-${CONFIG_LINUXDVB} += \ src/dvb/dvb_fe.c \ src/dvb/dvb_tables.c \ src/dvb/diseqc.c \ - src/dvb/dvb_adapter.c \ + src/dvb/dvb_linux.c \ + src/dvb/dvb_hardware.c \ src/dvb/dvb_network.c \ src/dvb/dvb_multiplex.c \ src/dvb/dvb_service.c \ diff --git a/src/capmt.c b/src/capmt.c index 1565309a..6af93cd3 100644 --- a/src/capmt.c +++ b/src/capmt.c @@ -541,7 +541,6 @@ capmt_thread(void *aux) capmt_t *capmt = aux; struct timespec ts; int d, i, bind_ok = 0; - th_dvb_adapter_t *tda; while (capmt->capmt_running) { for (i = 0; i < MAX_CA; i++) @@ -574,6 +573,9 @@ capmt_thread(void *aux) if (!capmt->capmt_oscam) { bind_ok = capmt_create_udp_socket(&capmt->capmt_sock_ca0[0], capmt->capmt_port); } else { + +#if 0 + th_dvb_adapter_t *tda; TAILQ_FOREACH(tda, &dvb_adapters, tda_global_link) { if (tda->tda_rootpath) { //if rootpath is NULL then can't rely on tda_adapter_num because it is always 0 if (tda->tda_adapter_num > MAX_CA) { @@ -584,6 +586,7 @@ capmt_thread(void *aux) bind_ok = capmt_create_udp_socket(&capmt->capmt_sock_ca0[tda->tda_adapter_num], 9000 + tda->tda_adapter_num); } } +#endif } if (bind_ok) handle_ca0(capmt); diff --git a/src/dvb/dvb.c b/src/dvb/dvb.c index 44e905d5..533e9450 100644 --- a/src/dvb/dvb.c +++ b/src/dvb/dvb.c @@ -25,7 +25,8 @@ void dvb_init(uint32_t adapter_mask, const char *rawfile) { + TAILQ_INIT(&dvb_adapters); dvb_charset_init(); dvb_network_init(); - dvb_adapter_init(adapter_mask, rawfile); + dvb_linux_init(); } diff --git a/src/dvb/dvb.h b/src/dvb/dvb.h index f81d46ef..8daf0100 100644 --- a/src/dvb/dvb.h +++ b/src/dvb/dvb.h @@ -43,6 +43,7 @@ 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); +TAILQ_HEAD(dvb_hardware_queue, dvb_hardware); /** * Satconf @@ -225,13 +226,45 @@ typedef struct dvb_table_feed { +/** + * dvb_hardware refers to any kind of DVB hardware + * + * This includes + * + * DVB Adapters (On linux: /dev/dvb/adapterX) + * DVB Frontends (On linux: /dev/dvb/adapterX/frontendX) + * DVB-S LNBs + * Diseqc equipment (Switches, motors, etc) + * + */ +typedef struct dvb_hardware { + idnode_t dh_id; + + // Hierarcy + struct dvb_hardware *dh_parent; + TAILQ_ENTRY(dvb_hardware) dh_parent_link; + struct dvb_hardware_queue dh_childs; + + // If attached to a network, this is set + dvb_network_t *dh_dn; + LIST_ENTRY(th_dvb_adapter) dh_network_link; + + // These are created on-demand whenever this particular network + // attachment point tunes to a mux + struct th_dvb_mux_instance_list dh_tdmis; + th_dvb_mux_instance_t *dh_current_tdmi; + + char *dh_name; + +} dvb_hardware_t; + + /** * DVB Adapter (one of these per physical adapter) */ -#define TDA_MUX_HASH_WIDTH 101 - typedef struct th_dvb_adapter { +#if 1 int tda_instance; @@ -310,6 +343,7 @@ typedef struct th_dvb_adapter { // PIDs that needs to be requeued and processed as tables uint8_t tda_table_filter[8192]; +#endif } th_dvb_adapter_t; @@ -363,8 +397,7 @@ typedef struct th_dvb_table { 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 dvb_hardware_queue dvb_adapters; void dvb_init(uint32_t adapter_mask, const char *rawfile); @@ -373,40 +406,9 @@ void dvb_init(uint32_t adapter_mask, const char *rawfile); */ void dvb_adapter_init(uint32_t adapter_mask, const char *rawfile); -void dvb_adapter_start (th_dvb_adapter_t *tda); +void dvb_adapter_start(th_dvb_adapter_t *tda); -void dvb_adapter_stop (th_dvb_adapter_t *tda); - -void 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); - -void dvb_adapter_set_skip_initialscan(th_dvb_adapter_t *tda, int on); - -void dvb_adapter_set_skip_checksubscr(th_dvb_adapter_t *tda, int on); - -void dvb_adapter_set_qmon(th_dvb_adapter_t *tda, int on); - -void dvb_adapter_set_idleclose(th_dvb_adapter_t *tda, int on); - -void dvb_adapter_set_poweroff(th_dvb_adapter_t *tda, int on); - -void dvb_adapter_set_sidtochan(th_dvb_adapter_t *tda, int on); - -void dvb_adapter_set_nitoid(th_dvb_adapter_t *tda, int nitoid); - -void dvb_adapter_set_diseqc_version(th_dvb_adapter_t *tda, unsigned int v); - -void dvb_adapter_set_diseqc_repeats(th_dvb_adapter_t *tda, - unsigned int repeats); - -void dvb_adapter_set_disable_pmt_monitor(th_dvb_adapter_t *tda, int on); - -void dvb_adapter_set_full_mux_rx(th_dvb_adapter_t *tda, int r); - -void dvb_adapter_clone(th_dvb_adapter_t *dst, th_dvb_adapter_t *src); - -int dvb_adapter_destroy(th_dvb_adapter_t *tda); +void dvb_adapter_stop(th_dvb_adapter_t *tda); void dvb_adapter_notify(th_dvb_adapter_t *tda); @@ -601,5 +603,18 @@ struct th_subscription *dvb_subscription_create_from_tdmi(th_dvb_mux_instance_t const char *name, streaming_target_t *st); + +/** + * DVB Hardware + */ +idnode_t **dvb_hardware_get_childs(struct idnode *self); +const char *dvb_hardware_get_title(struct idnode *self); + +void *dvb_hardware_create(const idclass_t *class, size_t size, + dvb_hardware_t *parent, const char *uuid, + const char *name); + +void dvb_linux_init(void); + #endif /* DVB_H_ */ diff --git a/src/dvb/dvb_fe.c b/src/dvb/dvb_fe.c index 916fe523..b8758b7f 100644 --- a/src/dvb/dvb_fe.c +++ b/src/dvb/dvb_fe.c @@ -390,7 +390,7 @@ dvb_fe_tune_tdmi(th_dvb_mux_instance_t *tdmi, const char *reason) free(tda->tda_tune_reason); tda->tda_tune_reason = strdup(reason); - dvb_adapter_start(tda); + abort(); // dvb_adapter_start(tda); // Make sure dvb_mux_stop() did the right thing assert(tda->tda_current_tdmi == NULL); diff --git a/src/dvb/dvb_hardware.c b/src/dvb/dvb_hardware.c new file mode 100644 index 00000000..0c8bed61 --- /dev/null +++ b/src/dvb/dvb_hardware.c @@ -0,0 +1,82 @@ +/* + * Generic DVB hardware stuff + * Copyright (C) 2013 Andreas Öman + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +#include "tvheadend.h" +#include "dvb.h" + + +struct dvb_hardware_queue dvb_adapters; + + +/** + * + */ +idnode_t ** +dvb_hardware_get_childs(struct idnode *self) +{ + dvb_hardware_t *dh = (dvb_hardware_t *)self; + dvb_hardware_t *c; + int cnt = 1; + + TAILQ_FOREACH(c, &dh->dh_childs, dh_parent_link) + cnt++; + + idnode_t **v = malloc(sizeof(idnode_t *) * cnt); + cnt = 0; + TAILQ_FOREACH(c, &dh->dh_childs, dh_parent_link) + v[cnt++] = &c->dh_id; + // qsort(v, cnt, sizeof(idnode_t *), svcsortcmp); + v[cnt] = NULL; + return v; + +} + + +/** + * + */ +const char * +dvb_hardware_get_title(struct idnode *self) +{ + dvb_hardware_t *dh = (dvb_hardware_t *)self; + return dh->dh_name; +} + + +/** + * + */ +void * +dvb_hardware_create(const idclass_t *class, size_t size, + dvb_hardware_t *parent, const char *uuid, + const char *name) +{ + dvb_hardware_t *dh = calloc(1, size); + idnode_insert(&dh->dh_id, uuid, class); + + TAILQ_INIT(&dh->dh_childs); + + if(parent == NULL) { + TAILQ_INSERT_TAIL(&dvb_adapters, dh, dh_parent_link); + } else { + TAILQ_INSERT_TAIL(&parent->dh_childs, dh, dh_parent_link); + } + dh->dh_name = strdup(name); + return dh; +} diff --git a/src/dvb/dvb_linux.c b/src/dvb/dvb_linux.c new file mode 100644 index 00000000..8727f463 --- /dev/null +++ b/src/dvb/dvb_linux.c @@ -0,0 +1,218 @@ +/* + * DVB for Linux + * Copyright (C) 2013 Andreas Öman + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include +#include +#include +#include +#include + +#include "tvheadend.h" +#include "dvb.h" +#include "dvb_support.h" + + +typedef struct linux_dvb_frontend { + dvb_hardware_t ldf_dh; + int ldf_adapterid; + int ldf_frontend; + + int ldf_fd; // if -1, frontend is closed + +} linux_dvb_frontend_t; + + + + +static const idclass_t linux_dvb_hardware_class = { + .ic_class = "linux_dvb_hardware", + .ic_get_childs = dvb_hardware_get_childs, + .ic_get_title = dvb_hardware_get_title, + .ic_properties = (const property_t[]){ + { + "name", "Name", PT_STR, + offsetof(dvb_hardware_t, dh_name), + .notify = &idnode_notify_title_changed, + }, {}}, +}; + + + +static const idclass_t linux_dvb_adapter_class = { + .ic_class = "linux_dvb_adapter", + .ic_super = &linux_dvb_hardware_class, +}; + + +static const idclass_t linux_dvb_frontend_class = { + .ic_class = "linux_dvb_frontend", + .ic_super = &linux_dvb_hardware_class, +}; + + + + + + + + + + +static const idclass_t linux_dvbc_frontend_class = { + .ic_leaf = 1, + .ic_class = "linux_dvbc_frontend", + .ic_super = &linux_dvb_frontend_class, +}; + +static const idclass_t linux_dvbt_frontend_class = { + .ic_leaf = 1, + .ic_class = "linux_dvbt_frontend", + .ic_super = &linux_dvb_frontend_class, +}; + +static const idclass_t linux_atsc_frontend_class = { + .ic_leaf = 1, + .ic_class = "linux_atsc_frontend", + .ic_super = &linux_dvb_frontend_class, +}; + +static const idclass_t linux_dvbs_frontend_class = { + .ic_class = "linux_dvbs_frontend", + .ic_super = &linux_dvb_frontend_class, +}; + + + +/** + * + */ +static void +linux_dvb_frontend_create(dvb_hardware_t *parent, int adapterid, + int frontendid, const struct dvb_frontend_info *dfi) +{ + const idclass_t *class; + + switch(dfi->type) { + case FE_OFDM: + class = &linux_dvbt_frontend_class; + break; + case FE_QAM: + class = &linux_dvbc_frontend_class; + break; + case FE_QPSK: + class = &linux_dvbs_frontend_class; + break; + case FE_ATSC: + class = &linux_atsc_frontend_class; + break; + default: + return; + } + + // dvb_hardware_t *fe = + dvb_hardware_create(class, + sizeof(linux_dvb_frontend_t), parent, NULL, dfi->name); +} + + +/** + * + */ +static void +add_adapter(int aid) +{ + int frontends; + int demuxers; + int dvrs; + int i; + char path[PATH_MAX]; + dvb_hardware_t *a = NULL; + + for(frontends = 0; frontends < 32; frontends++) { + snprintf(path, sizeof(path), "/dev/dvb/adapter%d/frontend%d", + aid, frontends); + if(access(path, R_OK | W_OK)) + break; + } + + if(frontends == 0) + return; // Nothing here + + for(demuxers = 0; demuxers < 32; demuxers++) { + snprintf(path, sizeof(path), "/dev/dvb/adapter%d/demux%d", + aid, demuxers); + if(access(path, R_OK | W_OK)) + break; + } + + for(dvrs = 0; dvrs < 32; dvrs++) { + snprintf(path, sizeof(path), "/dev/dvb/adapter%d/dvr%d", + aid, dvrs); + if(access(path, R_OK | W_OK)) + break; + } + + tvhlog(LOG_INFO, "DVB", + "Linux DVB adapter %d: %d frontends, %d demuxers, %d DVRs", + aid, frontends, demuxers, dvrs); + + for(i = 0; i < frontends; i++) { + + snprintf(path, sizeof(path), "/dev/dvb/adapter%d/frontend%d", aid, i); + + int fd = tvh_open(path, O_RDWR | O_NONBLOCK, 0); + if(fd == -1) { + tvhlog(LOG_ALERT, "DVB", + "Unable to open %s -- %s", path, strerror(errno)); + continue; + } + + struct dvb_frontend_info dfi; + + int r = ioctl(fd, FE_GET_INFO, &dfi); + close(fd); + if(r) { + tvhlog(LOG_ALERT, "DVB", "%s: Unable to query adapter", path); + continue; + } + + if(a == NULL) { + char name[512]; + snprintf(name, sizeof(name), "/dev/dvb/adapter%d", aid); + + a = dvb_hardware_create(&linux_dvb_adapter_class, sizeof(dvb_hardware_t), + NULL, NULL, name); + } + linux_dvb_frontend_create(a, aid, i, &dfi); + } +} + + +/** + * + */ +void +dvb_linux_init(void) +{ + int i; + for(i = 0 ; i < 32; i++) + add_adapter(i); +} + + diff --git a/src/dvb/dvb_multiplex.c b/src/dvb/dvb_multiplex.c index 232670e9..16c73edb 100644 --- a/src/dvb/dvb_multiplex.c +++ b/src/dvb/dvb_multiplex.c @@ -1233,7 +1233,7 @@ dvb_subscription_create_from_tdmi(th_dvb_mux_instance_t *tdmi, streaming_target_t *st) { th_subscription_t *s; - th_dvb_adapter_t *tda = tdmi->tdmi_adapter; + // th_dvb_adapter_t *tda = tdmi->tdmi_adapter; s = subscription_create(INT32_MAX, name, st, SUBSCRIPTION_RAW_MPEGTS, NULL, NULL, NULL, NULL); @@ -1244,10 +1244,11 @@ dvb_subscription_create_from_tdmi(th_dvb_mux_instance_t *tdmi, dvb_mux_tune(tdmi->tdmi_mux, "Full mux subscription", 99999); abort(); +#if 0 pthread_mutex_lock(&tda->tda_delivery_mutex); streaming_target_connect(&tda->tda_streaming_pad, &s->ths_input); pthread_mutex_unlock(&tda->tda_delivery_mutex); - +#endif notify_reload("subscriptions"); return s; } diff --git a/src/dvb/dvb_support.c b/src/dvb/dvb_support.c index fe994229..23945bb3 100644 --- a/src/dvb/dvb_support.c +++ b/src/dvb/dvb_support.c @@ -429,18 +429,6 @@ dvb_polarisation_to_str_long(int pol) } -th_dvb_adapter_t * -dvb_adapter_find_by_identifier(const char *identifier) -{ - th_dvb_adapter_t *tda; - - TAILQ_FOREACH(tda, &dvb_adapters, tda_global_link) - if(!strcmp(identifier, tda->tda_identifier)) - return tda; - return NULL; -} - - /** * */ diff --git a/src/idnode.c b/src/idnode.c index 1f2a221d..8894affe 100644 --- a/src/idnode.c +++ b/src/idnode.c @@ -194,11 +194,47 @@ add_params(struct idnode *self, const idclass_t *ic, htsmsg_t *p) static const char * idnode_get_title(idnode_t *in) { - if(in->in_class->ic_get_title != NULL) { - return in->in_class->ic_get_title(in); - } else { - return idnode_uuid_as_str(in); + const idclass_t *ic = in->in_class; + for(; ic != NULL; ic = ic->ic_super) { + if(ic->ic_get_title != NULL) + return ic->ic_get_title(in); } + return idnode_uuid_as_str(in); +} + + +/** + * + */ +idnode_t ** +idnode_get_childs(idnode_t *in) +{ + if(in == NULL) + return NULL; + + const idclass_t *ic = in->in_class; + for(; ic != NULL; ic = ic->ic_super) { + if(ic->ic_get_childs != NULL) + return ic->ic_get_childs(in); + } + return NULL; +} + + +/** + * + */ +int +idnode_is_leaf(idnode_t *in) +{ + const idclass_t *ic = in->in_class; + if(ic->ic_leaf) + return 1; + for(; ic != NULL; ic = ic->ic_super) { + if(ic->ic_get_childs != NULL) + return 0; + } + return 1; } diff --git a/src/idnode.h b/src/idnode.h index 52fa1d24..01d06ead 100644 --- a/src/idnode.h +++ b/src/idnode.h @@ -10,6 +10,7 @@ typedef struct idclass { const struct idclass *ic_super; const char *ic_class; const char *ic_caption; + int ic_leaf; struct htsmsg *(*ic_serialize)(struct idnode *self); struct idnode **(*ic_get_childs)(struct idnode *self); const char *(*ic_get_title)(struct idnode *self); @@ -32,6 +33,10 @@ const char *idnode_uuid_as_str(const idnode_t *in); void *idnode_find(const char *uuid, const idclass_t *class); +idnode_t **idnode_get_childs(idnode_t *in); + +int idnode_is_leaf(idnode_t *in); + void idnode_unlink(idnode_t *in); htsmsg_t *idnode_serialize(struct idnode *self); @@ -45,3 +50,4 @@ void idnode_update_all_props(idnode_t *in, void idnode_notify_title_changed(void *obj); + diff --git a/src/tvadapters.c b/src/tvadapters.c new file mode 100644 index 00000000..632cf55d --- /dev/null +++ b/src/tvadapters.c @@ -0,0 +1,40 @@ +/* + * TV Adapters + * Copyright (C) 2013 Andreas Öman + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "tvheadend.h" +#include "tvadapters.h" +#include "dvb/dvb.h" + +/** + * + */ +idnode_t ** +tv_adapters_root(void) +{ + dvb_hardware_t *dh; + int cnt = 1; + TAILQ_FOREACH(dh, &dvb_adapters, dh_parent_link) + cnt++; + + idnode_t **v = malloc(sizeof(idnode_t *) * cnt); + cnt = 0; + TAILQ_FOREACH(dh, &dvb_adapters, dh_parent_link) + v[cnt++] = &dh->dh_id; + v[cnt] = NULL; + return v; +} diff --git a/src/tvadapters.h b/src/tvadapters.h new file mode 100644 index 00000000..56b70525 --- /dev/null +++ b/src/tvadapters.h @@ -0,0 +1,5 @@ +#pragma once + +#include "idnode.h" + +idnode_t **tv_adapters_root(void); diff --git a/src/webui/extjs.c b/src/webui/extjs.c index 4f8e3bac..94f8d07d 100644 --- a/src/webui/extjs.c +++ b/src/webui/extjs.c @@ -47,6 +47,7 @@ #include "config2.h" #include "lang_codes.h" #include "subscriptions.h" +#include "tvadapters.h" /** * @@ -1813,6 +1814,7 @@ extjs_service_update(htsmsg_t *in) } } +#if 0 /** * */ @@ -1844,6 +1846,7 @@ extjs_tvadapter(http_connection_t *hc, const char *remain, void *opaque) http_output_content(hc, "text/x-json; charset=UTF-8"); return 0; } +#endif /** * @@ -1928,17 +1931,14 @@ extjs_get_idnode(http_connection_t *hc, const char *remain, void *opaque, if(!strcmp(s, "root")) { v = rootfn(); } else { - idnode_t *n = idnode_find(s, NULL); - v = n != NULL && n->in_class->ic_get_childs != NULL ? - n->in_class->ic_get_childs(n) : NULL; + v = idnode_get_childs(idnode_find(s, NULL)); } if(v != NULL) { int i; for(i = 0; v[i] != NULL; i++) { htsmsg_t *m = idnode_serialize(v[i]); - if(v[i]->in_class->ic_get_childs == NULL) - htsmsg_add_u32(m, "leaf", 1); + htsmsg_add_u32(m, "leaf", idnode_is_leaf(v[i])); htsmsg_add_msg(out, NULL, m); } } @@ -1995,6 +1995,15 @@ extjs_item_update(http_connection_t *hc, const char *remain, void *opaque) } +/** + * + */ +static int +extjs_tvadapters(http_connection_t *hc, const char *remain, void *opaque) +{ + return extjs_get_idnode(hc, remain, opaque, &tv_adapters_root); +} + /** @@ -2022,9 +2031,12 @@ extjs_start(void) http_path_add("/mergechannel", NULL, extjs_mergechannel, ACCESS_ADMIN); http_path_add("/iptv/services", NULL, extjs_iptvservices, ACCESS_ADMIN); http_path_add("/servicedetails", NULL, extjs_servicedetails, ACCESS_ADMIN); - http_path_add("/tv/adapter", NULL, extjs_tvadapter, ACCESS_ADMIN); + // http_path_add("/tv/adapter", NULL, extjs_tvadapter, ACCESS_ADMIN); http_path_add("/item/update", NULL, extjs_item_update, ACCESS_ADMIN); + http_path_add("/tvadapters", + NULL, extjs_tvadapters, ACCESS_ADMIN); + #if ENABLE_LINUXDVB extjs_start_dvb(); #endif diff --git a/src/webui/extjs_dvb.c b/src/webui/extjs_dvb.c index 4173b425..efc11cc1 100644 --- a/src/webui/extjs_dvb.c +++ b/src/webui/extjs_dvb.c @@ -45,7 +45,7 @@ - +#if 0 /** * */ @@ -83,8 +83,10 @@ extjs_dvblocations(http_connection_t *hc, const char *remain, void *opaque) http_output_content(hc, "text/x-json; charset=UTF-8"); return 0; } +#endif +#if 0 /** * */ @@ -102,7 +104,6 @@ json_single_record(htsmsg_t *rec, const char *root) } - /** * */ @@ -249,6 +250,7 @@ extjs_dvbadapter(http_connection_t *hc, const char *remain, void *opaque) http_output_content(hc, "text/x-json; charset=UTF-8"); return 0; } +#endif #if 0 @@ -666,18 +668,6 @@ extjs_dvb_copymux(http_connection_t *hc, const char *remain, void *opaque) #endif -/** - * - */ -void -extjs_list_dvb_adapters(htsmsg_t *array) -{ - th_dvb_adapter_t *tda; - TAILQ_FOREACH(tda, &dvb_adapters, tda_global_link) - htsmsg_add_msg(array, NULL, dvb_adapter_build_msg(tda)); -} - - /** * */ @@ -696,13 +686,13 @@ 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); diff --git a/src/webui/extjs_v4l.c b/src/webui/extjs_v4l.c index ad1d4833..10556124 100644 --- a/src/webui/extjs_v4l.c +++ b/src/webui/extjs_v4l.c @@ -265,6 +265,7 @@ extjs_v4lservices(http_connection_t *hc, const char *remain, void *opaque) return 0; } +#if 0 /** * @@ -277,6 +278,7 @@ extjs_list_v4l_adapters(htsmsg_t *array) TAILQ_FOREACH(va, &v4l_adapters, va_global_link) htsmsg_add_msg(array, NULL, v4l_adapter_build_msg(va)); } +#endif /** diff --git a/src/webui/statedump.c b/src/webui/statedump.c index 96df49a8..4582c364 100644 --- a/src/webui/statedump.c +++ b/src/webui/statedump.c @@ -75,7 +75,6 @@ dumpchannels(htsbuf_queue_t *hq) } } -#if ENABLE_LINUXDVB #if 0 static void dumptransports(htsbuf_queue_t *hq, struct service_list *l, int indent) @@ -120,7 +119,6 @@ dumptransports(htsbuf_queue_t *hq, struct service_list *l, int indent) } } -#endif @@ -171,10 +169,6 @@ page_statedump(http_connection_t *hc, const char *remain, void *opaque) tvh_binshasum[19]); dumpchannels(hq); - -#if ENABLE_LINUXDVB - dumpdvbadapters(hq); -#endif http_output_content(hc, "text/plain; charset=UTF-8"); return 0; diff --git a/src/webui/static/app/dvb_networks.js b/src/webui/static/app/dvb_networks.js index eb99f540..dea3b169 100644 --- a/src/webui/static/app/dvb_networks.js +++ b/src/webui/static/app/dvb_networks.js @@ -33,13 +33,12 @@ tvheadend.item_editor = function(item) { } var panel = new Ext.FormPanel({ - labelWidth: 75, // label settings here cascade unless overridden - url:'save-form.php', + labelWidth: 150, // label settings here cascade unless overridden frame:true, title: 'Parameters', bodyStyle:'padding:5px 5px 0', - width: 350, - defaults: {width: 230}, + width: 500, + defaults: {width: 330}, defaultType: 'textfield', items: fields, @@ -72,12 +71,12 @@ tvheadend.item_editor = function(item) { /** * */ -tvheadend.dvb_networks = function() { +tvheadend.item_browser = function(url, title) { var current = null; var loader = new Ext.tree.TreeLoader({ - dataUrl: 'dvb/networks' + dataUrl: url }); var tree = new Ext.tree.TreePanel({ @@ -86,7 +85,7 @@ tvheadend.dvb_networks = function() { border: false, root : new Ext.tree.AsyncTreeNode({ id : 'root', - text: 'DVB Networks' + text: title }), listeners: { click: function(n) { @@ -114,7 +113,7 @@ tvheadend.dvb_networks = function() { var panel = new Ext.Panel({ - title: 'DVB Networks', + title: title, layout: 'hbox', flex: 1, padding: 5, @@ -132,3 +131,12 @@ tvheadend.dvb_networks = function() { return panel; } + + +/** + * + */ +tvheadend.dvb_networks = function() { + return tvheadend.item_browser('/dvb/networks', 'DVB Networks'); +} + diff --git a/src/webui/static/app/tvadapters.js b/src/webui/static/app/tvadapters.js index 1644835f..781cdd74 100644 --- a/src/webui/static/app/tvadapters.js +++ b/src/webui/static/app/tvadapters.js @@ -1,6 +1,7 @@ /** * Datastore for adapters */ +/* tvheadend.tvAdapterStore = new Ext.data.JsonStore({ root : 'entries', id : 'identifier', @@ -71,10 +72,11 @@ tvheadend.tvadapters = function() { return panel; } - +*/ /** * */ +/* tvheadend.showTransportDetails = function(data) { html = ''; @@ -106,3 +108,8 @@ tvheadend.showTransportDetails = function(data) { }); win.show(); } +*/ + +tvheadend.tvadapters = function() { + return tvheadend.item_browser('/tvadapters', 'TV Adapters'); +} \ No newline at end of file diff --git a/src/webui/webui.h b/src/webui/webui.h index 300d32f6..31176207 100644 --- a/src/webui/webui.h +++ b/src/webui/webui.h @@ -33,12 +33,10 @@ size_t html_escaped_len(const char *src); const char* html_escape(char *dst, const char *src, size_t len); #if ENABLE_LINUXDVB -void extjs_list_dvb_adapters(htsmsg_t *array); void extjs_start_dvb(void); #endif #if ENABLE_V4L -void extjs_list_v4l_adapters(htsmsg_t *array); void extjs_start_v4l(void); #endif