From e4a510deb6e59b95cadaddac41d2d07578223cfa Mon Sep 17 00:00:00 2001 From: Adam Sutton Date: Mon, 24 Jun 2013 10:09:47 +0100 Subject: [PATCH] linxudvb: remove deprecated code Some bits are still incomplete, but I can refer to copies from now on. --- src/input/mpegts/linuxdvb/diseqc.c | 122 -- src/input/mpegts/linuxdvb/diseqc.h | 16 - src/input/mpegts/linuxdvb/dvb.c | 32 - src/input/mpegts/linuxdvb/dvb.h | 640 ------- src/input/mpegts/linuxdvb/dvb_adapter.c | 502 ------ src/input/mpegts/linuxdvb/dvb_fe.c | 474 ------ src/input/mpegts/linuxdvb/dvb_hardware.c | 82 - .../mpegts/linuxdvb/dvb_input_filtered.c | 261 --- src/input/mpegts/linuxdvb/dvb_input_raw.c | 177 -- src/input/mpegts/linuxdvb/dvb_linux.c | 218 --- src/input/mpegts/linuxdvb/dvb_multiplex.c | 1478 ----------------- src/input/mpegts/linuxdvb/dvb_network.c | 255 --- src/input/mpegts/linuxdvb/dvb_preconf.c | 205 --- src/input/mpegts/linuxdvb/dvb_preconf.h | 28 - src/input/mpegts/linuxdvb/dvb_satconf.c | 340 ---- src/input/mpegts/linuxdvb/dvb_service.c | 499 ------ src/input/mpegts/linuxdvb/dvb_tables.c | 1255 -------------- 17 files changed, 6584 deletions(-) delete mode 100755 src/input/mpegts/linuxdvb/diseqc.c delete mode 100644 src/input/mpegts/linuxdvb/diseqc.h delete mode 100644 src/input/mpegts/linuxdvb/dvb.c delete mode 100644 src/input/mpegts/linuxdvb/dvb.h delete mode 100644 src/input/mpegts/linuxdvb/dvb_adapter.c delete mode 100644 src/input/mpegts/linuxdvb/dvb_fe.c delete mode 100644 src/input/mpegts/linuxdvb/dvb_hardware.c delete mode 100644 src/input/mpegts/linuxdvb/dvb_input_filtered.c delete mode 100644 src/input/mpegts/linuxdvb/dvb_input_raw.c delete mode 100644 src/input/mpegts/linuxdvb/dvb_linux.c delete mode 100644 src/input/mpegts/linuxdvb/dvb_multiplex.c delete mode 100644 src/input/mpegts/linuxdvb/dvb_network.c delete mode 100644 src/input/mpegts/linuxdvb/dvb_preconf.c delete mode 100644 src/input/mpegts/linuxdvb/dvb_preconf.h delete mode 100644 src/input/mpegts/linuxdvb/dvb_satconf.c delete mode 100644 src/input/mpegts/linuxdvb/dvb_service.c delete mode 100644 src/input/mpegts/linuxdvb/dvb_tables.c diff --git a/src/input/mpegts/linuxdvb/diseqc.c b/src/input/mpegts/linuxdvb/diseqc.c deleted file mode 100755 index 29c948d3..00000000 --- a/src/input/mpegts/linuxdvb/diseqc.c +++ /dev/null @@ -1,122 +0,0 @@ -#include -#include -#include - -#include "tvheadend.h" -#include "diseqc.h" - -/*--------------------------------------------------------------------------*/ - -static inline void -msleep(uint32_t msec) -{ - struct timespec req = { msec / 1000, 1000000 * (msec % 1000) }; - - while (nanosleep(&req, &req)) - ; -} - -int -diseqc_send_msg(int fe_fd, __u8 framing_byte, __u8 address, __u8 cmd, - __u8 data_1, __u8 data_2, __u8 data_3, __u8 msg_len) -{ - int err; - struct dvb_diseqc_master_cmd message; - - tvhtrace("diseqc", "sending %X %X %X %X %X %X", - framing_byte, address, cmd, data_1, data_2, data_3); - - message.msg[0] = framing_byte; - message.msg[1] = address; - message.msg[2] = cmd; - message.msg[3] = data_1; - message.msg[4] = data_2; - message.msg[5] = data_3; - message.msg_len = msg_len; - if ((err = ioctl(fe_fd, FE_DISEQC_SEND_MASTER_CMD, &message))) { - tvhlog(LOG_ERR, "diseqc", "error sending diseqc command"); - return err; - } - return 0; -} - -int -diseqc_setup(int fe_fd, int lnb_num, int voltage, int band, - uint32_t version, uint32_t repeats) -{ - int i = (lnb_num % 4) * 4 + voltage * 2 + (band ? 1 : 0); - int j = lnb_num / 4; - int k, err; - - tvhtrace("diseqc", - "fe_fd=%i, lnb_num=%i, voltage=%i, band=%i, version=%i, repeats=%i", - fe_fd, lnb_num, voltage, band, version, repeats); - - /* verify lnb number and diseqc data */ - if(lnb_num < 0 || lnb_num >=64 || i < 0 || i >= 16 || j < 0 || j >= 16) - return -1; - - /* turn off continuous tone */ - tvhtrace("diseqc", "disabling continuous tone"); - if ((err = ioctl(fe_fd, FE_SET_TONE, SEC_TONE_OFF))) { - tvhlog(LOG_ERR, "diseqc", "error trying to turn off continuous tone"); - return err; - } - - /* set lnb voltage */ - tvhtrace("diseqc", "setting lnb voltage to %iV", (i/2) % 2 ? 18 : 13); - if ((err = ioctl(fe_fd, FE_SET_VOLTAGE, (i/2) % 2 ? SEC_VOLTAGE_18 : SEC_VOLTAGE_13))) { - tvhlog(LOG_ERR, "diseqc", "error setting lnb voltage"); - return err; - } - msleep(15); - - if (repeats == 0) { /* uncommited msg, wait 15ms, commited msg */ - if ((err = diseqc_send_msg(fe_fd, 0xE0, 0x10, 0x39, 0xF0 | j, 0, 0, 4))) - return err; - msleep(15); - if ((err = diseqc_send_msg(fe_fd, 0xE0, 0x10, 0x38, 0xF0 | i, 0, 0, 4))) - return err; - } else { /* commited msg, 25ms, uncommited msg, 25ms, commited msg, etc */ - if ((err = diseqc_send_msg(fe_fd, 0xE0, 0x10, 0x38, 0xF0 | i, 0, 0, 4))) - return err; - for (k = 0; k < repeats; k++) { - msleep(25); - if ((err = diseqc_send_msg(fe_fd, 0xE0, 0x10, 0x39, 0xF0 | j, 0, 0, 4))) - return err; - msleep(25); - if ((err = diseqc_send_msg(fe_fd, 0xE1, 0x10, 0x38, 0xF0 | i, 0, 0, 4))) - return err; - } - } - msleep(15); - - /* set toneburst */ - tvhtrace("diseqc", (i/4) % 2 ? "sending mini diseqc B" : "sending mini diseqc A"); - if ((err = ioctl(fe_fd, FE_DISEQC_SEND_BURST, (i/4) % 2 ? SEC_MINI_B : SEC_MINI_A))) { - tvhlog(LOG_ERR, "diseqc", "error sending mini diseqc command"); - return err; - } - msleep(15); - - /* set continuous tone */ - tvhtrace("diseqc", i % 2 ? "enabling continous tone" : "disabling continuous tone"); - if ((err = ioctl(fe_fd, FE_SET_TONE, i % 2 ? SEC_TONE_ON : SEC_TONE_OFF))) { - tvhlog(LOG_ERR, "diseqc", "error setting continuous tone"); - return err; - } - return 0; -} - -int -diseqc_voltage_off(int fe_fd) -{ - int err; - - tvhtrace("diseqc", "sending diseqc voltage off command"); - if ((err = ioctl(fe_fd, FE_SET_VOLTAGE, SEC_VOLTAGE_OFF))) { - tvhlog(LOG_ERR, "diseqc", "error sending diseqc voltage off command"); - return err; - } - return 0; -} diff --git a/src/input/mpegts/linuxdvb/diseqc.h b/src/input/mpegts/linuxdvb/diseqc.h deleted file mode 100644 index 852a7948..00000000 --- a/src/input/mpegts/linuxdvb/diseqc.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef __DISEQC_H__ -#define __DISEQC_H__ - -#include -#include - -/** - * set up the switch to position/voltage/tone - */ -int diseqc_send_msg(int fe_fd, __u8 framing_byte, __u8 address, __u8 cmd, - __u8 data_1, __u8 data_2, __u8 data_3, __u8 msg_len); -int diseqc_setup(int fe_fd, int lnb_num, int voltage, int band, - uint32_t version, uint32_t repeats); -int diseqc_voltage_off(int fe_fd); - -#endif diff --git a/src/input/mpegts/linuxdvb/dvb.c b/src/input/mpegts/linuxdvb/dvb.c deleted file mode 100644 index 533e9450..00000000 --- a/src/input/mpegts/linuxdvb/dvb.c +++ /dev/null @@ -1,32 +0,0 @@ -/* - * TV Input - Linux DVB interface - * Copyright (C) 2007 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" -#include "dvb_support.h" -#include "dvb_charset.h" - -void -dvb_init(uint32_t adapter_mask, const char *rawfile) -{ - TAILQ_INIT(&dvb_adapters); - dvb_charset_init(); - dvb_network_init(); - dvb_linux_init(); -} diff --git a/src/input/mpegts/linuxdvb/dvb.h b/src/input/mpegts/linuxdvb/dvb.h deleted file mode 100644 index 0f3defbd..00000000 --- a/src/input/mpegts/linuxdvb/dvb.h +++ /dev/null @@ -1,640 +0,0 @@ -/* - * TV Input - Linux DVB interface - * Copyright (C) 2007 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 . - */ - -#ifndef DVB_H_ -#define DVB_H_ - -#include -#include -#include -#include "htsmsg.h" -#include "psi.h" -#include "idnode.h" - -struct service; -struct th_dvb_table; -struct th_dvb_mux_instance; - -#define TDA_OPT_FE 0x1 -#define TDA_OPT_DVR 0x2 -#define TDA_OPT_DMX 0x4 -#define TDA_OPT_PWR 0x8 -#define TDA_OPT_ALL (TDA_OPT_FE | TDA_OPT_DVR | TDA_OPT_DMX | TDA_OPT_PWR) - -#define DVB_VER_INT(maj,min) (((maj) << 16) + (min)) - -#define DVB_VER_ATLEAST(maj, min) \ - (DVB_VER_INT(DVB_API_VERSION, DVB_API_VERSION_MINOR) >= DVB_VER_INT(maj, min)) - -TAILQ_HEAD(th_dvb_adapter_queue, th_dvb_adapter); -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); -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 - */ -typedef struct dvb_satconf { - char *sc_id; - TAILQ_ENTRY(dvb_satconf) sc_adapter_link; - int sc_port; // diseqc switchport (0 - 63) - - char *sc_name; - char *sc_comment; - char *sc_lnb; - -} dvb_satconf_t; - - -enum polarisation { - POLARISATION_HORIZONTAL = 0x00, - POLARISATION_VERTICAL = 0x01, - POLARISATION_CIRCULAR_LEFT = 0x02, - POLARISATION_CIRCULAR_RIGHT = 0x03 -}; - -#define DVB_FEC_ERROR_LIMIT 20 - -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; -#if DVB_API_VERSION >= 5 - fe_modulation_t dmc_fe_modulation; - fe_delivery_system_t dmc_fe_delsys; - fe_rolloff_t dmc_fe_rolloff; -#endif -} dvb_mux_conf_t; - - - -/** - * - */ -typedef struct dvb_network { - idnode_t dn_id; - - LIST_ENTRY(dvb_network) dn_global_link; - - 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; - - int dn_fe_type; // Frontend types for this network (FE_QPSK, etc) - - struct dvb_mux_list dn_muxes; - - uint32_t dn_disable_pmt_monitor; - uint32_t dn_autodiscovery; - 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; - - - -/** - * - */ -typedef struct dvb_mux { - idnode_t dm_id; - LIST_ENTRY(dvb_mux) dm_network_link; - 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; - - TAILQ_HEAD(, epggrab_ota_mux) dm_epg_grab; - - gtimer_t dm_initial_scan_timeout; - - TAILQ_ENTRY(dvb_mux) dm_scan_link; - 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; - - 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; - - int dm_enabled; - -} dvb_mux_t; - - - - -/** - * DVB Mux instance - */ -typedef struct th_dvb_mux_instance { - - dvb_mux_t *tdmi_mux; - 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_signal; - uint32_t tdmi_ber, tdmi_unc; - float tdmi_unc_avg; - float tdmi_snr; - -#define TDMI_FEC_ERR_HISTOGRAM_SIZE 10 - uint32_t tdmi_fec_err_histogram[TDMI_FEC_ERR_HISTOGRAM_SIZE]; - int tdmi_fec_err_ptr; - - - enum { - TDMI_FE_UNKNOWN, - TDMI_FE_NO_SIGNAL, - TDMI_FE_FAINT_SIGNAL, - TDMI_FE_BAD_SIGNAL, - TDMI_FE_CONSTANT_FEC, - TDMI_FE_BURSTY_FEC, - TDMI_FE_OK, - } tdmi_fe_status; - - int tdmi_quality; - - int tdmi_tune_failed; // Adapter failed to tune this frequency - // Don't try again - - struct th_subscription_list tdmi_subscriptions; - -} th_dvb_mux_instance_t; - - - - - -/** - * When in raw mode we need to enqueue raw TS packet - * to a different thread because we need to hold - * global_lock when doing delivery of the tables - */ -TAILQ_HEAD(dvb_table_feed_queue, dvb_table_feed); - -typedef struct dvb_table_feed { - TAILQ_ENTRY(dvb_table_feed) dtf_link; - uint8_t dtf_tsb[188]; -} dvb_table_feed_t; - - - - -/** - * 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) - */ -typedef struct th_dvb_adapter { - -#if 1 - int tda_instance; - - - 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; - - th_dvb_mux_instance_t *tda_current_tdmi; - char *tda_tune_reason; // Reason for last tune - - int tda_table_epollfd; - - uint32_t tda_enabled; - - int tda_locked; - time_t tda_fe_monitor; - - const char *tda_rootpath; - char *tda_identifier; - uint32_t tda_idleclose; - uint32_t tda_skip_initialscan; - uint32_t tda_qmon; - uint32_t tda_poweroff; - uint32_t tda_sidtochan; - uint32_t tda_diseqc_version; - uint32_t tda_diseqc_repeats; - int32_t tda_full_mux_rx; - uint32_t tda_grace_period; - uint32_t tda_snr_valid; - char *tda_displayname; - - int tda_fe_type; - struct dvb_frontend_info *tda_fe_info; // result of FE_GET_INFO ioctl() - - char *tda_fe_path; - int tda_fe_fd; - - int tda_adapter_num; - - char *tda_demux_path; - - char *tda_dvr_path; - pthread_t tda_dvr_thread; - th_pipe_t tda_dvr_pipe; - - int tda_hostconnection; - - pthread_mutex_t tda_delivery_mutex; - struct service_list tda_transports; /* Currently bound transports */ - - gtimer_t tda_fe_monitor_timer; - - int tda_sat; // Set if this adapter is a satellite receiver (DVB-S, etc) - - struct dvb_satconf_queue tda_satconfs; - - - uint32_t tda_last_fec; - - int tda_unc_is_delta; /* 1 if we believe FE_READ_UNCORRECTED_BLOCKS - * return dela values */ - - uint32_t tda_extrapriority; // extra priority for choosing the best adapter/service - - 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 dvb_mux *dm, struct th_dvb_table *s); - void (*tda_close_table)(struct dvb_mux *dm, struct th_dvb_table *s); - - int tda_rawmode; - - int tda_bytes; - - // Full mux streaming, protected via the delivery mutex - - streaming_pad_t tda_streaming_pad; - - - struct dvb_table_feed_queue tda_table_feed; - pthread_cond_t tda_table_feed_cond; // Bound to tda_delivery_mutex - - // PIDs that needs to be requeued and processed as tables - uint8_t tda_table_filter[8192]; - -#endif - -} th_dvb_adapter_t; - -/** - * DVB table - */ -typedef struct th_dvb_table { - /** - * Flags, must never be changed after creation. - * We inspect it without holding global_lock - */ - int tdt_flags; - - /** - * Cycle queue - * Tables that did not get a fd or filter in hardware will end up here - * waiting for any other table to be received so it can reuse that fd. - * Only linked if fd == -1 - */ - TAILQ_ENTRY(th_dvb_table) tdt_pending_link; - - /** - * File descriptor for filter - */ - int tdt_fd; - - LIST_ENTRY(th_dvb_table) tdt_link; - th_dvb_mux_instance_t *tdt_tdmi; - - char *tdt_name; - - void *tdt_opaque; - int (*tdt_callback)(dvb_mux_t *dm, uint8_t *buf, int len, - uint8_t tableid, void *opaque); - - - int tdt_count; - int tdt_pid; - - int tdt_id; - - int tdt_table; - int tdt_mask; - - int tdt_destroyed; - int tdt_refcount; - - psi_section_t tdt_sect; // Manual reassembly - -} th_dvb_table_t; - - -extern struct dvb_network_list dvb_networks; -extern struct dvb_hardware_queue dvb_adapters; - -void dvb_init(uint32_t adapter_mask, const char *rawfile); - -/** - * DVB Adapter - */ -void dvb_adapter_init(uint32_t adapter_mask, const char *rawfile); - -void dvb_adapter_start(th_dvb_adapter_t *tda, int opt); - -void dvb_adapter_stop(th_dvb_adapter_t *tda, int opt); - -void dvb_adapter_notify(th_dvb_adapter_t *tda); - -htsmsg_t *dvb_adapter_build_msg(th_dvb_adapter_t *tda); - -htsmsg_t *dvb_fe_opts(th_dvb_adapter_t *tda, const char *which); - -void dvb_adapter_set_extrapriority(th_dvb_adapter_t *tda, int extrapriority); - -void dvb_adapter_poweroff(th_dvb_adapter_t *tda); - -void dvb_input_filtered_setup(th_dvb_adapter_t *tda); - -void dvb_input_raw_setup(th_dvb_adapter_t *tda); - - - -/** - * DVB Multiplex - */ -const char* dvb_mux_fec2str(int fec); -const char* dvb_mux_delsys2str(int delsys); -const char* dvb_mux_qam2str(int qam); -const char* dvb_mux_rolloff2str(int rolloff); - -int dvb_mux_str2bw(const char *str); -int dvb_mux_str2qam(const char *str); -int dvb_mux_str2fec(const char *str); -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(dvb_mux_t *dm); - -void dvb_mux_load(dvb_network_t *dn); - -void dvb_mux_destroy(dvb_mux_t *dm); - -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, - dvb_satconf_t *satconf, int create, dvb_mux_t *src); - -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, int force); - -void dvb_mux_set_onid(dvb_mux_t *mux, uint16_t onid, int force); - -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(dvb_mux_t *dm); - -void dvb_mux_notify(dvb_mux_t *dm); - -const char *dvb_mux_add_by_params(dvb_network_t *dn, - int freq, - int symrate, - int bw, - int constellation, - int delsys, - int tmode, - int guard, - int hier, - int fechi, - int feclo, - 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 - -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, const char *reason); - -void dvb_create_tdmis(dvb_mux_t *dm); - -int tdmi_current_weight(const th_dvb_mux_instance_t *tdmi); - - -/** - * DVB Transport (aka DVB service) - */ -void dvb_service_load(dvb_mux_t *dm); - -struct service *dvb_service_find(dvb_mux_t *dm, - uint16_t sid, int pmt_pid, - const char *identifier); - -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); - -void dvb_service_notify_by_adapter(th_dvb_adapter_t *tda); - -/** - * DVB Frontend - */ - -//void dvb_fe_stop(th_dvb_adapter_t *tda, int retune); - - -/** - * DVB Tables - */ -void dvb_table_init(th_dvb_adapter_t *tda); - -void dvb_table_add_default(dvb_mux_t *dm); - -void dvb_table_flush_all(dvb_mux_t *dm); - -void dvb_table_add_pmt(dvb_mux_t *dm, int pmt_pid); - -void dvb_table_rem_pmt(dvb_mux_t *dm, int pmt_pid); - -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(dvb_mux_t *dm, uint8_t *ptr, int len, - uint8_t tableid, void *opaque); - -#define TDT_CRC 0x1 -#define TDT_QUICKREQ 0x2 -#define TDT_CA 0x4 -#define TDT_TDT 0x8 - -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, const char *uuid); - -//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); - - -/** - * Satellite configuration - */ -void dvb_satconf_init(th_dvb_adapter_t *tda); - -htsmsg_t *dvb_satconf_list(th_dvb_adapter_t *tda); - -htsmsg_t *dvb_lnblist_get(void); - -dvb_satconf_t *dvb_satconf_entry_find(th_dvb_adapter_t *tda, - const char *id, int create); - -void dvb_lnb_get_frequencies(const char *id, - int *f_low, int *f_hi, int *f_switch); - - -/** - * Raw demux - */ -struct th_subscription; -struct th_subscription *dvb_subscription_create_from_tdmi(th_dvb_mux_instance_t *tdmi, - const char *name, - streaming_target_t *st, - const char *hostname, - const char *username, - const char *client); - - -/** - * 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/input/mpegts/linuxdvb/dvb_adapter.c b/src/input/mpegts/linuxdvb/dvb_adapter.c deleted file mode 100644 index b09468e8..00000000 --- a/src/input/mpegts/linuxdvb/dvb_adapter.c +++ /dev/null @@ -1,502 +0,0 @@ -/* - * TV Input - Linux DVB interface - * Copyright (C) 2007 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 . - */ - -#define _GNU_SOURCE -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "settings.h" - -#include "tvheadend.h" -#include "dvb.h" -#include "dvb_support.h" -#include "tsdemux.h" -#include "notify.h" -#include "service.h" -#include "epggrab.h" -#include "diseqc.h" -#include "atomic.h" - -static void *dvb_adapter_input_dvr(void *aux); - -/** - * - */ -void -dvb_adapter_start ( th_dvb_adapter_t *tda, int opt ) -{ - if(tda->tda_enabled == 0) { - tvhlog(LOG_INFO, "dvb", "Adapter \"%s\" cannot be started - it's disabled", tda->tda_displayname); - return; - } - - /* Default to ALL */ - if (!opt) - opt = TDA_OPT_ALL; - - /* Open front end */ - if ((opt & TDA_OPT_FE) && (tda->tda_fe_fd == -1)) { - tda->tda_fe_fd = tvh_open(tda->tda_fe_path, O_RDWR | O_NONBLOCK, 0); - if (tda->tda_fe_fd == -1) return; - tvhlog(LOG_DEBUG, "dvb", "%s opened frontend %s", tda->tda_rootpath, tda->tda_fe_path); - } - - /* Start DVR thread */ - if ((opt & TDA_OPT_DVR) && (tda->tda_dvr_pipe.rd == -1)) { - int err = tvh_pipe(O_NONBLOCK, &tda->tda_dvr_pipe); - assert(err != -1); - pthread_create(&tda->tda_dvr_thread, NULL, dvb_adapter_input_dvr, tda); - tvhlog(LOG_DEBUG, "dvb", "%s started dvr thread", tda->tda_rootpath); - } -} - -void -dvb_adapter_stop ( th_dvb_adapter_t *tda, int opt ) -{ - assert(tda->tda_current_tdmi == NULL); - - /* Poweroff */ - if (opt & TDA_OPT_PWR) - dvb_adapter_poweroff(tda); - - /* Stop DVR thread */ - if ((opt & TDA_OPT_DVR) && (tda->tda_dvr_pipe.rd != -1)) { - tvhlog(LOG_DEBUG, "dvb", "%s stopping thread", tda->tda_rootpath); - int err = tvh_write(tda->tda_dvr_pipe.wr, "", 1); - assert(!err); - pthread_join(tda->tda_dvr_thread, NULL); - close(tda->tda_dvr_pipe.rd); - close(tda->tda_dvr_pipe.wr); - tda->tda_dvr_pipe.rd = -1; - tvhlog(LOG_DEBUG, "dvb", "%s stopped thread", tda->tda_rootpath); - } - - dvb_adapter_notify(tda); - - /* Don't close FE */ - if (!tda->tda_idleclose && tda->tda_enabled) return; - - /* Close front end */ - if ((opt & TDA_OPT_FE) && (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; - } -} - -/** - * Install RAW PES filter - */ -static int -dvb_adapter_raw_filter(th_dvb_adapter_t *tda) -{ - int dmx = -1; - struct dmx_pes_filter_params dmx_param; - - dmx = tvh_open(tda->tda_demux_path, O_RDWR, 0); - if(dmx == -1) { - tvhlog(LOG_ALERT, "dvb", "Unable to open %s -- %s", - tda->tda_demux_path, strerror(errno)); - return -1; - } - - memset(&dmx_param, 0, sizeof(dmx_param)); - dmx_param.pid = 0x2000; - dmx_param.input = DMX_IN_FRONTEND; - dmx_param.output = DMX_OUT_TS_TAP; - dmx_param.pes_type = DMX_PES_OTHER; - dmx_param.flags = DMX_IMMEDIATE_START; - - if(ioctl(dmx, DMX_SET_PES_FILTER, &dmx_param) == -1) { - tvhlog(LOG_ERR, "dvb", - "Unable to configure demuxer \"%s\" for all PIDs -- %s", - tda->tda_demux_path, strerror(errno)); - close(dmx); - return -1; - } - - return dmx; -} - -/** - * - */ -static void * -dvb_adapter_input_dvr(void *aux) -{ - th_dvb_adapter_t *tda = aux; - int fd = -1, i, r, c, efd, nfds, dmx = -1; - uint8_t tsb[188 * 10]; - service_t *t; - struct epoll_event ev; - int delay = 10; - - /* Install RAW demux */ - if (tda->tda_rawmode) { - if ((dmx = dvb_adapter_raw_filter(tda)) == -1) { - tvhlog(LOG_ALERT, "dvb", "Unable to install raw mux filter"); - return NULL; - } - } - - /* Open DVR */ - if ((fd = tvh_open(tda->tda_dvr_path, O_RDONLY | O_NONBLOCK, 0)) == -1) { - close(dmx); - return NULL; - } - - /* Create poll */ - efd = epoll_create(2); - memset(&ev, 0, sizeof(ev)); - ev.events = EPOLLIN; - ev.data.fd = tda->tda_dvr_pipe.rd; - epoll_ctl(efd, EPOLL_CTL_ADD, tda->tda_dvr_pipe.rd, &ev); - ev.data.fd = fd; - epoll_ctl(efd, EPOLL_CTL_ADD, fd, &ev); - - r = i = 0; - while(1) { - - /* Wait for input */ - nfds = epoll_wait(efd, &ev, 1, delay); - - /* No data */ - if (nfds < 1) continue; - - /* Exit */ - if (ev.data.fd != fd) break; - - /* Read data */ - c = read(fd, tsb+r, sizeof(tsb)-r); - if (c < 0) { - if (errno == EAGAIN || errno == EINTR) - continue; - else if (errno == EOVERFLOW) { - tvhlog(LOG_WARNING, "dvb", "\"%s\" read() EOVERFLOW", - tda->tda_identifier); - continue; - } else { - // TODO: should we try to recover? - tvhlog(LOG_ERR, "dvb", "\"%s\" read() error %d", - tda->tda_identifier, errno); - break; - } - } - r += c; - atomic_add(&tda->tda_bytes, c); - - /* not enough data */ - if (r < 188) continue; - - int wakeup_table_feed = 0; // Just wanna wakeup once - - pthread_mutex_lock(&tda->tda_delivery_mutex); - - if(LIST_FIRST(&tda->tda_streaming_pad.sp_targets) != NULL) { - streaming_message_t sm; - pktbuf_t *pb = pktbuf_alloc(tsb, r); - memset(&sm, 0, sizeof(sm)); - sm.sm_type = SMT_MPEGTS; - sm.sm_data = pb; - streaming_pad_deliver(&tda->tda_streaming_pad, &sm); - pktbuf_ref_dec(pb); - } - - /* Process */ - while (r >= 188) { - - /* sync */ - if (tsb[i] == 0x47) { - int pid = (tsb[i+1] & 0x1f) << 8 | tsb[i+2]; - - if(tda->tda_table_filter[pid]) { - if(!(tsb[i+1] & 0x80)) { // Only dispatch to table parser if not error - dvb_table_feed_t *dtf = malloc(sizeof(dvb_table_feed_t)); - memcpy(dtf->dtf_tsb, tsb + i, 188); - TAILQ_INSERT_TAIL(&tda->tda_table_feed, dtf, dtf_link); - wakeup_table_feed = 1; - } - } else { - LIST_FOREACH(t, &tda->tda_transports, s_active_link) - ts_recv_packet1(t, tsb + i, NULL); - } - - i += 188; - r -= 188; - - /* no sync */ - } else { - tvhlog(LOG_DEBUG, "dvb", "\"%s\" ts sync lost", tda->tda_identifier); - if (ts_resync(tsb, &r, &i)) break; - tvhlog(LOG_DEBUG, "dvb", "\"%s\" ts sync found", tda->tda_identifier); - } - } - - if(wakeup_table_feed) - pthread_cond_signal(&tda->tda_table_feed_cond); - - pthread_mutex_unlock(&tda->tda_delivery_mutex); - - /* reset buffer */ - if (r) memmove(tsb, tsb+i, r); - i = 0; - } - - if(dmx != -1) - close(dmx); - close(efd); - close(fd); - return NULL; -} - - -/** - * - */ -htsmsg_t * -dvb_adapter_build_msg(th_dvb_adapter_t *tda) -{ - htsmsg_t *m = htsmsg_create_map(); - int fdiv; - - htsmsg_add_str(m, "identifier", tda->tda_identifier); - htsmsg_add_str(m, "name", tda->tda_displayname); - - htsmsg_add_str(m, "type", "dvb"); - - if(tda->tda_current_tdmi != NULL) { - th_dvb_mux_instance_t *tdmi = tda->tda_current_tdmi; - - 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); - 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) - return m; - - htsmsg_add_str(m, "path", tda->tda_rootpath); - htsmsg_add_str(m, "hostconnection", - hostconnection2str(tda->tda_hostconnection)); - htsmsg_add_str(m, "devicename", tda->tda_fe_info->name); - - htsmsg_add_str(m, "deliverySystem", - dvb_adaptertype_to_str(tda->tda_fe_type) ?: ""); - - htsmsg_add_u32(m, "satConf", tda->tda_sat); - - 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); - htsmsg_add_u32(m, "freqStep", tda->tda_fe_info->frequency_stepsize / fdiv); - - htsmsg_add_u32(m, "symrateMin", tda->tda_fe_info->symbol_rate_min); - htsmsg_add_u32(m, "symrateMax", tda->tda_fe_info->symbol_rate_max); - return m; -} - - -/** - * - */ -void -dvb_adapter_notify(th_dvb_adapter_t *tda) -{ - notify_by_msg("tvAdapter", dvb_adapter_build_msg(tda)); -} - - -/** - * - */ -static void -fe_opts_add(htsmsg_t *a, const char *title, int value) -{ - htsmsg_t *v = htsmsg_create_map(); - - htsmsg_add_str(v, "title", title); - htsmsg_add_u32(v, "id", value); - htsmsg_add_msg(a, NULL, v); -} - -/** - * - */ -htsmsg_t * -dvb_fe_opts(th_dvb_adapter_t *tda, const char *which) -{ - htsmsg_t *a = htsmsg_create_list(); - fe_caps_t c = tda->tda_fe_info->caps; - - if(!strcmp(which, "constellations")) { - if(c & FE_CAN_QAM_AUTO) fe_opts_add(a, "Auto", QAM_AUTO); - if(c & FE_CAN_QPSK) { - fe_opts_add(a, "QPSK", QPSK); -#if DVB_API_VERSION >= 5 - fe_opts_add(a, "PSK_8", PSK_8); - fe_opts_add(a, "APSK_16", APSK_16); - fe_opts_add(a, "APSK_32", APSK_32); -#endif - } - if(c & FE_CAN_QAM_16) fe_opts_add(a, "QAM-16", QAM_16); - if(c & FE_CAN_QAM_32) fe_opts_add(a, "QAM-32", QAM_32); - if(c & FE_CAN_QAM_64) fe_opts_add(a, "QAM-64", QAM_64); - if(c & FE_CAN_QAM_128) fe_opts_add(a, "QAM-128", QAM_128); - if(c & FE_CAN_QAM_256) fe_opts_add(a, "QAM-256", QAM_256); - return a; - } - - if(!strcmp(which, "delsys")) { - if(c & FE_CAN_QPSK) { -#if DVB_API_VERSION >= 5 - fe_opts_add(a, "SYS_DVBS", SYS_DVBS); - fe_opts_add(a, "SYS_DVBS2", SYS_DVBS2); -#else - fe_opts_add(a, "SYS_DVBS", -1); -#endif - } - return a; - } - - if(!strcmp(which, "transmissionmodes")) { - if(c & FE_CAN_TRANSMISSION_MODE_AUTO) - fe_opts_add(a, "Auto", TRANSMISSION_MODE_AUTO); - - fe_opts_add(a, "2k", TRANSMISSION_MODE_2K); - fe_opts_add(a, "8k", TRANSMISSION_MODE_8K); - return a; - } - - if(!strcmp(which, "bandwidths")) { - if(c & FE_CAN_BANDWIDTH_AUTO) - fe_opts_add(a, "Auto", BANDWIDTH_AUTO); - - fe_opts_add(a, "8 MHz", BANDWIDTH_8_MHZ); - fe_opts_add(a, "7 MHz", BANDWIDTH_7_MHZ); - fe_opts_add(a, "6 MHz", BANDWIDTH_6_MHZ); - return a; - } - - if(!strcmp(which, "guardintervals")) { - if(c & FE_CAN_GUARD_INTERVAL_AUTO) - fe_opts_add(a, "Auto", GUARD_INTERVAL_AUTO); - - fe_opts_add(a, "1/32", GUARD_INTERVAL_1_32); - fe_opts_add(a, "1/16", GUARD_INTERVAL_1_16); - fe_opts_add(a, "1/8", GUARD_INTERVAL_1_8); - fe_opts_add(a, "1/4", GUARD_INTERVAL_1_4); - return a; - } - - if(!strcmp(which, "hierarchies")) { - if(c & FE_CAN_HIERARCHY_AUTO) - fe_opts_add(a, "Auto", HIERARCHY_AUTO); - - fe_opts_add(a, "None", HIERARCHY_NONE); - fe_opts_add(a, "1", HIERARCHY_1); - fe_opts_add(a, "2", HIERARCHY_2); - fe_opts_add(a, "4", HIERARCHY_4); - return a; - } - - if(!strcmp(which, "fec")) { - if(c & FE_CAN_FEC_AUTO) - fe_opts_add(a, "Auto", FEC_AUTO); - - fe_opts_add(a, "None", FEC_NONE); - - fe_opts_add(a, "1/2", FEC_1_2); - fe_opts_add(a, "2/3", FEC_2_3); - fe_opts_add(a, "3/4", FEC_3_4); - fe_opts_add(a, "4/5", FEC_4_5); -#if DVB_API_VERSION >= 5 - fe_opts_add(a, "3/5", FEC_3_5); -#endif - fe_opts_add(a, "5/6", FEC_5_6); - fe_opts_add(a, "6/7", FEC_6_7); - fe_opts_add(a, "7/8", FEC_7_8); - fe_opts_add(a, "8/9", FEC_8_9); -#if DVB_API_VERSION >= 5 - fe_opts_add(a, "9/10", FEC_9_10); -#endif - return a; - } - - - if(!strcmp(which, "polarisations")) { - fe_opts_add(a, "Horizontal", POLARISATION_HORIZONTAL); - fe_opts_add(a, "Vertical", POLARISATION_VERTICAL); - fe_opts_add(a, "Circular left", POLARISATION_CIRCULAR_LEFT); - fe_opts_add(a, "Circular right", POLARISATION_CIRCULAR_RIGHT); - return a; - } - - htsmsg_destroy(a); - return NULL; -} - -/** - * Turn off the adapter - */ -void -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_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/input/mpegts/linuxdvb/dvb_fe.c b/src/input/mpegts/linuxdvb/dvb_fe.c deleted file mode 100644 index 3b858a70..00000000 --- a/src/input/mpegts/linuxdvb/dvb_fe.c +++ /dev/null @@ -1,474 +0,0 @@ -/* - * TV Input - Linux DVB interface - * Copyright (C) 2007 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 - -#include -#include -#include -#include - -#include -#include - -#include "tvheadend.h" -#include "dvb.h" -#include "dvb_support.h" -#include "diseqc.h" -#include "notify.h" -#include "dvr/dvr.h" -#include "service.h" -#include "streaming.h" -#include "atomic.h" - -#include "epggrab.h" - -/** - * Return uncorrected block (since last read) - * - * Some adapters report delta themselfs, some return ever increasing value - * we need to deal with that ourselfs - */ -static int -dvb_fe_get_unc(th_dvb_adapter_t *tda) -{ - uint32_t fec; - int d, r; - - if(ioctl(tda->tda_fe_fd, FE_READ_UNCORRECTED_BLOCKS, &fec)) - return 0; // read failed, just say 0 - - if(tda->tda_unc_is_delta) - return fec; - - d = (int)fec - (int)tda->tda_last_fec; - - if(d < 0) { - tda->tda_unc_is_delta = 1; - tvhlog(LOG_DEBUG, "dvb", - "%s: FE_READ_UNCORRECTED_BLOCKS returns delta updates (delta=%d)", - tda->tda_displayname, d); - return fec; - } - - r = fec - tda->tda_last_fec; - - tda->tda_last_fec = fec; - return r; -} - - - -/** - * Front end monitor - * - * Monitor status every second - */ -static void -dvb_fe_monitor(void *aux) -{ - th_dvb_adapter_t *tda = aux; - fe_status_t fe_status; - int status, v, vv, i, fec, q, bw; - th_dvb_mux_instance_t *tdmi = tda->tda_current_tdmi; - signal_status_t sigstat; - streaming_message_t sm; - struct service *t; - - int notify = 0; - - if(tdmi == NULL) - return; - - /** - * Read out front end status - */ - - if(ioctl(tda->tda_fe_fd, FE_READ_STATUS, &fe_status)) - status = TDMI_FE_UNKNOWN; - else if(fe_status & FE_HAS_LOCK) - status = -1; - else if(fe_status & (FE_HAS_SYNC | FE_HAS_VITERBI | FE_HAS_CARRIER)) - status = TDMI_FE_BAD_SIGNAL; - else if(fe_status & FE_HAS_SIGNAL) - status = TDMI_FE_FAINT_SIGNAL; - else - status = TDMI_FE_NO_SIGNAL; - - /** - * Waiting for initial lock - */ - if(tda->tda_locked == 0) { - - /* Read */ - if (status == -1) { - tda->tda_locked = 1; - dvb_adapter_start(tda, TDA_OPT_ALL); - gtimer_arm(&tda->tda_fe_monitor_timer, dvb_fe_monitor, tda, 1); - - /* Install table handlers */ - dvb_table_add_default(tdmi->tdmi_mux); - epggrab_mux_start(tdmi->tdmi_mux); - - /* Service filters */ - pthread_mutex_lock(&tda->tda_delivery_mutex); - LIST_FOREACH(t, &tda->tda_transports, s_active_link) { - if (t->s_dvb_mux == tdmi->tdmi_mux) { - tda->tda_open_service(tda, t); - dvb_table_add_pmt(tdmi->tdmi_mux, t->s_pmt_pid); - } - } - pthread_mutex_unlock(&tda->tda_delivery_mutex); - - /* Re-arm (50ms) */ - } else { - gtimer_arm_ms(&tda->tda_fe_monitor_timer, dvb_fe_monitor, tda, 50); - - /* Monitor (1 per sec) */ - if (dispatch_clock < tda->tda_fe_monitor) - return; - tda->tda_fe_monitor = dispatch_clock + 1; - } - - } else { - gtimer_arm(&tda->tda_fe_monitor_timer, dvb_fe_monitor, tda, 1); - } - - /* - * Update stats - */ - if(status == -1) { - /* Read FEC counter (delta) */ - - fec = dvb_fe_get_unc(tda); - - if(tdmi->tdmi_unc != fec) { - tdmi->tdmi_unc = fec; - notify = 1; - } - - tdmi->tdmi_fec_err_histogram[tdmi->tdmi_fec_err_ptr++] = fec; - if(tdmi->tdmi_fec_err_ptr == TDMI_FEC_ERR_HISTOGRAM_SIZE) - tdmi->tdmi_fec_err_ptr = 0; - - v = vv = 0; - for(i = 0; i < TDMI_FEC_ERR_HISTOGRAM_SIZE; i++) { - if(tdmi->tdmi_fec_err_histogram[i] > DVB_FEC_ERROR_LIMIT) - v++; - vv += tdmi->tdmi_fec_err_histogram[i]; - } - - float avg = (float)vv / TDMI_FEC_ERR_HISTOGRAM_SIZE; - - if(tdmi->tdmi_unc_avg != avg) { - tdmi->tdmi_unc_avg = avg; - notify = 1; - } - - if(v == 0) { - status = TDMI_FE_OK; - } else if(v == 1) { - status = TDMI_FE_BURSTY_FEC; - } else { - status = TDMI_FE_CONSTANT_FEC; - } - - int v; - /* bit error rate */ - if(ioctl(tda->tda_fe_fd, FE_READ_BER, &v) != -1 && v != tdmi->tdmi_ber) { - tdmi->tdmi_ber = v; - notify = 1; - } - - /* signal strength */ - if(ioctl(tda->tda_fe_fd, FE_READ_SIGNAL_STRENGTH, &v) != -1 && v != tdmi->tdmi_signal) { - tdmi->tdmi_signal = v; - notify = 1; - } - - /* signal/noise ratio */ - if(tda->tda_snr_valid) { - if(ioctl(tda->tda_fe_fd, FE_READ_SNR, &v) != -1) { - float snr = v / 10.0; - if(tdmi->tdmi_snr != snr) { - tdmi->tdmi_snr = snr; - notify = 1; - } - } - } - } - - if(status != tdmi->tdmi_fe_status) { - tdmi->tdmi_fe_status = status; - - tvhlog(LOG_DEBUG, - "dvb", "\"%s\" on adapter \"%s\", status changed to %s", - dvb_mux_nicename(tdmi->tdmi_mux), tda->tda_displayname, - dvb_mux_status(tdmi)); - notify = 1; - } - - if(status != TDMI_FE_UNKNOWN) { - if(tda->tda_qmon) { - q = tdmi->tdmi_quality + (status - TDMI_FE_OK + 1); - q = MAX(MIN(q, 100), 0); - } else { - q = 100; - } - if(q != tdmi->tdmi_quality) { - tdmi->tdmi_quality = q; - notify = 1; - } - } - - bw = atomic_exchange(&tda->tda_bytes, 0); - - 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); - htsmsg_add_u32(m, "signal", tdmi->tdmi_signal); - - if(tda->tda_snr_valid) - htsmsg_add_dbl(m, "snr", tdmi->tdmi_snr); - htsmsg_add_u32(m, "ber", tdmi->tdmi_ber); - htsmsg_add_u32(m, "unc", tdmi->tdmi_unc); - notify_by_msg("dvbMux", m); -#endif - - 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)); - if(tda->tda_snr_valid) - htsmsg_add_dbl(m, "snr", tdmi->tdmi_snr); - htsmsg_add_u32(m, "ber", tdmi->tdmi_ber); - htsmsg_add_u32(m, "unc", tdmi->tdmi_unc); - htsmsg_add_dbl(m, "uncavg", tdmi->tdmi_unc_avg); - htsmsg_add_u32(m, "bw", bw); - 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); - sigstat.snr = tdmi->tdmi_snr; - sigstat.signal = tdmi->tdmi_signal; - sigstat.ber = tdmi->tdmi_ber; - sigstat.unc = tdmi->tdmi_unc; - sm.sm_type = SMT_SIGNAL_STATUS; - sm.sm_data = &sigstat; - 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); - } -} - -#if DVB_API_VERSION >= 5 - -static struct dtv_property clear_p[] = { - { .cmd = DTV_CLEAR }, -}; - -static struct dtv_properties clear_cmdseq = { - .num = 1, - .props = clear_p -}; - -/** - * - */ -static int -dvb_fe_tune_s2(th_dvb_adapter_t *tda, dvb_mux_conf_t *dmc) -{ - struct dvb_frontend_parameters *p = &dmc->dmc_fe_params; - int r; - - if ((ioctl(tda->tda_fe_fd, FE_SET_PROPERTY, &clear_cmdseq)) != 0) - return -1; - - struct dvb_frontend_event ev; - - /* Support for legacy satellite tune, with the new API. */ - struct dtv_property _dvbs_cmdargs[] = { - { .cmd = DTV_DELIVERY_SYSTEM, .u.data = dmc->dmc_fe_delsys }, - { .cmd = DTV_FREQUENCY, .u.data = p->frequency }, - { .cmd = DTV_MODULATION, .u.data = dmc->dmc_fe_modulation }, - { .cmd = DTV_SYMBOL_RATE, .u.data = p->u.qpsk.symbol_rate }, - { .cmd = DTV_INNER_FEC, .u.data = p->u.qpsk.fec_inner }, - { .cmd = DTV_INVERSION, .u.data = INVERSION_AUTO }, - { .cmd = DTV_ROLLOFF, .u.data = dmc->dmc_fe_rolloff }, - { .cmd = DTV_PILOT, .u.data = PILOT_AUTO }, - { .cmd = DTV_TUNE }, - }; - - struct dtv_properties _dvbs_cmdseq = { - .num = 9, - .props = _dvbs_cmdargs - }; - - /* discard stale QPSK events */ - while (1) { - if (ioctl(tda->tda_fe_fd, FE_GET_EVENT, &ev) == -1) - break; - } - - /* do tuning now */ - r = ioctl(tda->tda_fe_fd, FE_SET_PROPERTY, &_dvbs_cmdseq); - - return r; - -} - -#endif - - - -/** - * - */ -int -dvb_fe_tune_tdmi(th_dvb_mux_instance_t *tdmi, const char *reason) -{ - th_dvb_adapter_t *tda = tdmi->tdmi_adapter; - 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; - - if(tda->tda_enabled == 0) - return SM_CODE_TUNING_FAILED; - - 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); - - //abort(); - dvb_adapter_start(tda, TDA_OPT_FE | TDA_OPT_PWR); - - // Make sure dvb_mux_stop() did the right thing - assert(tda->tda_current_tdmi == NULL); - - if(tda->tda_fe_type == FE_QPSK) { - - /* DVB-S */ - int port, lowfreq, hifreq, switchfreq, hiband, pol, dbsbs; - - lowfreq = 9750000; - hifreq = 10600000; - switchfreq = 11700000; - port = 0; - dbsbs = 0; -#if 0 - dvb_satconf_t *sc; - if((sc = dm->dm_conf.dmc_satconf) != NULL) { - port = sc->sc_port; - - if(sc->sc_lnb != NULL) - dvb_lnb_get_frequencies(sc->sc_lnb, &lowfreq, &hifreq, &switchfreq); - if(!strcmp(sc->sc_id ?: "", "DBS Bandstacked")) - dbsbs = 1; - } -#endif - - if(dbsbs) { - hiband = 0; - 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 = dm->dm_conf.dmc_polarisation; - if(hiband) - p->frequency = abs(p->frequency - hifreq); - else - p->frequency = abs(p->frequency - lowfreq); - } - - if ((r = diseqc_setup(tda->tda_fe_fd, port, - pol == POLARISATION_HORIZONTAL || - pol == POLARISATION_CIRCULAR_LEFT, - hiband, tda->tda_diseqc_version, - tda->tda_diseqc_repeats)) != 0) - tvhlog(LOG_ERR, "dvb", "diseqc setup failed %d\n", r); - } - -#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)", tda->tda_rootpath, dvb_mux_nicename(dm), 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\"", - 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, dvb_mux_nicename(dm), strerror(errno), p->frequency); - if (errno == EINVAL) - tdmi->tdmi_tune_failed = 1; - return SM_CODE_TUNING_FAILED; - } - - dm->dm_current_tdmi = tdmi; - - time(&tda->tda_fe_monitor); - tda->tda_fe_monitor += 4; // wait a few secs before monitoring (unlocked) - gtimer_arm_ms(&tda->tda_fe_monitor_timer, dvb_fe_monitor, tda, 50); - - dvb_adapter_notify(tda); - - return r; -} diff --git a/src/input/mpegts/linuxdvb/dvb_hardware.c b/src/input/mpegts/linuxdvb/dvb_hardware.c deleted file mode 100644 index 0c8bed61..00000000 --- a/src/input/mpegts/linuxdvb/dvb_hardware.c +++ /dev/null @@ -1,82 +0,0 @@ -/* - * 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/input/mpegts/linuxdvb/dvb_input_filtered.c b/src/input/mpegts/linuxdvb/dvb_input_filtered.c deleted file mode 100644 index 9040dcd7..00000000 --- a/src/input/mpegts/linuxdvb/dvb_input_filtered.c +++ /dev/null @@ -1,261 +0,0 @@ -/* - * TV Input - Linux DVB interface - * Copyright (C) 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 . - */ - -/** - * DVB input using hardware filters - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "tvheadend.h" -#include "dvb.h" -#include "service.h" - -/** - * Install filters for a service - * - * global_lock must be held - */ -static void -open_service(th_dvb_adapter_t *tda, service_t *s) -{ - struct dmx_pes_filter_params dmx_param; - int fd; - elementary_stream_t *st; - - TAILQ_FOREACH(st, &s->s_components, es_link) { - if(st->es_pid >= 0x2000) - continue; - - if(st->es_demuxer_fd != -1) - continue; - - fd = tvh_open(tda->tda_demux_path, O_RDWR, 0); - st->es_cc_valid = 0; - - if(fd == -1) { - st->es_demuxer_fd = -1; - tvhlog(LOG_ERR, "dvb", - "\"%s\" unable to open demuxer \"%s\" for pid %d -- %s", - s->s_nicename, tda->tda_demux_path, - st->es_pid, strerror(errno)); - continue; - } - - memset(&dmx_param, 0, sizeof(dmx_param)); - dmx_param.pid = st->es_pid; - dmx_param.input = DMX_IN_FRONTEND; - dmx_param.output = DMX_OUT_TS_TAP; - dmx_param.pes_type = DMX_PES_OTHER; - dmx_param.flags = DMX_IMMEDIATE_START; - - 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_nicename, tda->tda_demux_path, - st->es_pid, strerror(errno)); - close(fd); - fd = -1; - } - - st->es_demuxer_fd = fd; - } -} - - -/** - * Remove filters for a service - * - * global_lock must be held - */ -static void -close_service(th_dvb_adapter_t *tda, service_t *s) -{ - elementary_stream_t *es; - - TAILQ_FOREACH(es, &s->s_components, es_link) { - if(es->es_demuxer_fd != -1) { - close(es->es_demuxer_fd); - es->es_demuxer_fd = -1; - } - } -} - - - - -/** - * - */ -static void -open_table(dvb_mux_t *dm, th_dvb_table_t *tdt) -{ - th_dvb_adapter_t *tda = dm->dm_current_tdmi->tdmi_adapter; - struct epoll_event e; - static int tdt_id_tally; - - tdt->tdt_fd = tvh_open(tda->tda_demux_path, O_RDWR, 0); - - if(tdt->tdt_fd != -1) { - - tdt->tdt_id = ++tdt_id_tally; - - e.events = EPOLLIN; - e.data.u64 = ((uint64_t)tdt->tdt_fd << 32) | tdt->tdt_id; - - if(epoll_ctl(tda->tda_table_epollfd, EPOLL_CTL_ADD, tdt->tdt_fd, &e)) { - close(tdt->tdt_fd); - tdt->tdt_fd = -1; - } else { - - struct dmx_sct_filter_params fp = {0}; - - fp.filter.filter[0] = tdt->tdt_table; - fp.filter.mask[0] = tdt->tdt_mask; - - if(tdt->tdt_flags & TDT_CRC) - fp.flags |= DMX_CHECK_CRC; - fp.flags |= DMX_IMMEDIATE_START; - fp.pid = tdt->tdt_pid; - - if(ioctl(tdt->tdt_fd, DMX_SET_FILTER, &fp)) { - close(tdt->tdt_fd); - tdt->tdt_fd = -1; - } - } - } - - if(tdt->tdt_fd == -1) - TAILQ_INSERT_TAIL(&dm->dm_table_queue, tdt, tdt_pending_link); -} - - -/** - * Close FD for the given table and put table on the pending list - */ -static void -tdt_close_fd(dvb_mux_t *dm, th_dvb_table_t *tdt) -{ - th_dvb_adapter_t *tda = dm->dm_current_tdmi->tdmi_adapter; - - assert(tdt->tdt_fd != -1); - - epoll_ctl(tda->tda_table_epollfd, EPOLL_CTL_DEL, tdt->tdt_fd, NULL); - close(tdt->tdt_fd); - - tdt->tdt_fd = -1; - TAILQ_INSERT_TAIL(&dm->dm_table_queue, tdt, tdt_pending_link); -} - - - -/** - * - */ -static void * -dvb_table_input(void *aux) -{ - th_dvb_adapter_t *tda = aux; - int r, i, tid, fd, x; - struct epoll_event ev[1]; - uint8_t sec[4096]; - dvb_mux_t *dm; - th_dvb_table_t *tdt; - int64_t cycle_barrier = 0; - - while(1) { - x = epoll_wait(tda->tda_table_epollfd, ev, sizeof(ev) / sizeof(ev[0]), -1); - - for(i = 0; i < x; i++) { - - tid = ev[i].data.u64 & 0xffffffff; - fd = ev[i].data.u64 >> 32; - - if(!(ev[i].events & EPOLLIN)) - continue; - - if((r = read(fd, sec, sizeof(sec))) < 3) - continue; - - pthread_mutex_lock(&global_lock); - if((dm = tda->tda_current_tdmi->tdmi_mux) != NULL) { - LIST_FOREACH(tdt, &dm->dm_tables, tdt_link) - if(tdt->tdt_id == tid) - break; - - if(tdt != NULL) { - dvb_table_dispatch(sec, r, tdt); - - /* Any tables pending (that wants a filter/fd), close this one */ - if(TAILQ_FIRST(&dm->dm_table_queue) != NULL && - cycle_barrier < getmonoclock()) { - tdt_close_fd(dm, tdt); - cycle_barrier = getmonoclock() + 100000; - tdt = TAILQ_FIRST(&dm->dm_table_queue); - assert(tdt != NULL); - TAILQ_REMOVE(&dm->dm_table_queue, tdt, tdt_pending_link); - - open_table(dm, tdt); - } - } - } - pthread_mutex_unlock(&global_lock); - } - } - return NULL; -} - - -static void -close_table(dvb_mux_t *dm, th_dvb_table_t *tdt) -{ - - if(tdt->tdt_fd == -1) { - 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); - } -} - -/** - * - */ -void -dvb_input_filtered_setup(th_dvb_adapter_t *tda) -{ - tda->tda_open_service = open_service; - tda->tda_close_service = close_service; - tda->tda_open_table = open_table; - tda->tda_close_table = close_table; - - pthread_t ptid; - tda->tda_table_epollfd = epoll_create(50); - pthread_create(&ptid, NULL, dvb_table_input, tda); -} - diff --git a/src/input/mpegts/linuxdvb/dvb_input_raw.c b/src/input/mpegts/linuxdvb/dvb_input_raw.c deleted file mode 100644 index 7176e0ef..00000000 --- a/src/input/mpegts/linuxdvb/dvb_input_raw.c +++ /dev/null @@ -1,177 +0,0 @@ -/* - * TV Input - Linux DVB interface - * Copyright (C) 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 . - */ - -/** - * DVB input from a raw transport stream - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "tvheadend.h" -#include "dvb.h" -#include "service.h" - -/** - * Install filters for a service - * - * global_lock must be held - */ -static void -open_service(th_dvb_adapter_t *tda, service_t *s) -{ - // NOP -- We receive all PIDs anyway -} - - -/** - * Remove filters for a service - * - * global_lock must be held - */ -static void -close_service(th_dvb_adapter_t *tda, service_t *s) -{ - // NOP -- open_service() is a NOP -} - - -/** - * - */ -static void -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; -} - - -/** - * - */ -static void -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; -} - - -/** - * - */ -static void -got_section(const uint8_t *data, size_t len, void *opaque) -{ - th_dvb_table_t *tdt = opaque; - dvb_table_dispatch((uint8_t *)data, len, tdt); -} - - - -/** - * All the tables can be destroyed from any of the callbacks - * so we need to be a bit careful here - */ -static void -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[dm->dm_num_tables], *tdt; - int i = 0; - LIST_FOREACH(tdt, &dm->dm_tables, tdt_link) { - vec[i++] = tdt; - tdt->tdt_refcount++; - } - 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) { - if(tdt->tdt_pid == pid) - psi_section_reassemble(&tdt->tdt_sect, dtf->dtf_tsb, - 0, got_section, tdt); - } - dvb_table_release(tdt); - } -} - -/** - * - */ -static void * -dvb_table_input(void *aux) -{ - th_dvb_adapter_t *tda = aux; - th_dvb_mux_instance_t *tdmi; - dvb_table_feed_t *dtf; - - while(1) { - - pthread_mutex_lock(&tda->tda_delivery_mutex); - - while((dtf = TAILQ_FIRST(&tda->tda_table_feed)) == NULL) - pthread_cond_wait(&tda->tda_table_feed_cond, &tda->tda_delivery_mutex); - TAILQ_REMOVE(&tda->tda_table_feed, dtf, dtf_link); - - pthread_mutex_unlock(&tda->tda_delivery_mutex); - - pthread_mutex_lock(&global_lock); - - if((tdmi = tda->tda_current_tdmi) != NULL) - dvb_table_raw_dispatch(tdmi->tdmi_mux, dtf); - - pthread_mutex_unlock(&global_lock); - free(dtf); - } - return NULL; -} - - -/** - * - */ -void -dvb_input_raw_setup(th_dvb_adapter_t *tda) -{ - tda->tda_rawmode = 1; - tda->tda_open_service = open_service; - tda->tda_close_service = close_service; - tda->tda_open_table = open_table; - tda->tda_close_table = close_table; - - TAILQ_INIT(&tda->tda_table_feed); - pthread_cond_init(&tda->tda_table_feed_cond, NULL); - - pthread_t ptid; - pthread_create(&ptid, NULL, dvb_table_input, tda); - -} - diff --git a/src/input/mpegts/linuxdvb/dvb_linux.c b/src/input/mpegts/linuxdvb/dvb_linux.c deleted file mode 100644 index 8727f463..00000000 --- a/src/input/mpegts/linuxdvb/dvb_linux.c +++ /dev/null @@ -1,218 +0,0 @@ -/* - * 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/input/mpegts/linuxdvb/dvb_multiplex.c b/src/input/mpegts/linuxdvb/dvb_multiplex.c deleted file mode 100644 index e0489044..00000000 --- a/src/input/mpegts/linuxdvb/dvb_multiplex.c +++ /dev/null @@ -1,1478 +0,0 @@ -/* - * TV Input - Linux DVB interface - * Copyright (C) 2007 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 -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "settings.h" - -#include "tvheadend.h" -#include "dvb.h" -#include "channels.h" -#include "teletext.h" -#include "psi.h" -#include "dvb_support.h" -#include "notify.h" -#include "subscriptions.h" -#include "epggrab.h" - -static struct strtab muxfestatustab[] = { - { "Unknown", TDMI_FE_UNKNOWN }, - { "No signal", TDMI_FE_NO_SIGNAL }, - { "Faint signal", TDMI_FE_FAINT_SIGNAL }, - { "Bad signal", TDMI_FE_BAD_SIGNAL }, - { "Constant FEC", TDMI_FE_CONSTANT_FEC }, - { "Bursty FEC", TDMI_FE_BURSTY_FEC }, - { "OK", TDMI_FE_OK }, -}; - -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_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, - offsetof(dvb_mux_t, dm_enabled) - }, {}} -}; - -/** - * - */ -static void -mux_link_initial(dvb_network_t *dn, dvb_mux_t *dm) -{ - assert(dm->dm_scan_status == DM_SCAN_DONE); - - 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 - */ -const char * -dvb_mux_status(th_dvb_mux_instance_t *tdmi) -{ - return val2str(tdmi->tdmi_fe_status, muxfestatustab) ?: "Invalid"; -} - - -/** - * - */ -static int -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; - fd = labs(fd); - return fd < 2000 && - a->dmc_polarisation == b->dmc_polarisation; -} - - -/** - * Return 0 if configuration does not differ. return 1 if it does - */ -static int -dcm_compare_conf(int adapter_type, - const struct dvb_mux_conf *a, - const struct dvb_mux_conf *b) -{ - switch(adapter_type) { - case FE_OFDM: - return memcmp(&a->dmc_fe_params.u.ofdm, - &b->dmc_fe_params.u.ofdm, - sizeof(a->dmc_fe_params.u.ofdm)); - case FE_QAM: - return memcmp(&a->dmc_fe_params.u.qam, - &b->dmc_fe_params.u.qam, - sizeof(a->dmc_fe_params.u.qam)); - case FE_ATSC: - return memcmp(&a->dmc_fe_params.u.vsb, - &b->dmc_fe_params.u.vsb, - sizeof(a->dmc_fe_params.u.vsb)); - case FE_QPSK: - return memcmp(&a->dmc_fe_params.u.qpsk, - &b->dmc_fe_params.u.qpsk, - sizeof(a->dmc_fe_params.u.qpsk)) -#if DVB_API_VERSION >= 5 - || a->dmc_fe_modulation != b->dmc_fe_modulation - || a->dmc_fe_delsys != b->dmc_fe_delsys - || a->dmc_fe_rolloff != b->dmc_fe_rolloff -#endif -; - } - return 0; -} - -/** - * Create a new mux on the given adapter, return NULL if it already exists - */ -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 needscan, - const char *uuid, dvb_satconf_t *satconf, - int create, dvb_mux_t *src) -{ - dvb_mux_t *dm; - - lock_assert(&global_lock); - -#if TODO_FIX_THIS - if (!satconf) - satconf = dmc->dmc_satconf; -#endif - - /* HACK - we hash/compare based on 2KHz spacing and compare on +/-500Hz */ - LIST_FOREACH(dm, &dn->dn_muxes, dm_network_link) { - if(dmc_compare_key(&dm->dm_conf, dmc)) - break; /* Mux already exist */ - } - - if(dm != NULL) { - /* Update stuff ... */ - int save = 0; - char buf2[1024]; - buf2[0] = 0; - int master = 0; - if (!src) - master = 1; - else if (src->dm_network_id == dm->dm_network_id) - master = 1; - - /* Network ID */ - if(tsid != 0xFFFF && dm->dm_transport_stream_id != tsid) { - if (dm->dm_transport_stream_id == 0xFFFF || master) { - dm->dm_transport_stream_id = tsid; - save = 1; - } - } - if(onid && dm->dm_network_id != onid) { - if (!dm->dm_network_id || master) { - dm->dm_network_id = onid; - save = 1; - } - } - if(network && *network && strcmp(dm->dm_network_name ?: "", network)) { - if (!dm->dm_network_name || master) { - free(dm->dm_network_name); - dm->dm_network_name = strdup(network); - save = 1; - } - } - - /* Tuning Info */ - // TODO: same protection here? - if(dm->dm_dn->dn_autodiscovery && - dcm_compare_conf(dn->dn_fe_type, &dm->dm_conf, dmc)) { -#if DVB_API_VERSION >= 5 - snprintf(buf2, sizeof(buf2), " ("); - if (dm->dm_conf.dmc_fe_modulation != dmc->dmc_fe_modulation) - sprintf(buf2, "%s %s->%s, ", buf2, - dvb_mux_qam2str(dm->dm_conf.dmc_fe_modulation), - dvb_mux_qam2str(dmc->dmc_fe_modulation)); - if (dm->dm_conf.dmc_fe_delsys != dmc->dmc_fe_delsys) - sprintf(buf2, "%s %s->%s, ", buf2, - dvb_mux_delsys2str(dm->dm_conf.dmc_fe_delsys), - dvb_mux_delsys2str(dmc->dmc_fe_delsys)); - if (dm->dm_conf.dmc_fe_rolloff != dmc->dmc_fe_rolloff) - sprintf(buf2, "%s %s->%s, ", buf2, - dvb_mux_rolloff2str(dm->dm_conf.dmc_fe_rolloff), - dvb_mux_rolloff2str(dmc->dmc_fe_rolloff)); - sprintf(buf2, "%s)", buf2); -#endif - - memcpy(&dm->dm_conf, dmc, sizeof(struct dvb_mux_conf)); - save = 1; - } - - if(save) { - dvb_mux_save(dm); - tvhlog(LOG_DEBUG, "dvb", - "Configuration for mux \"%s\" updated by %s%s", - dvb_mux_nicename(dm), source, buf2); - dvb_mux_notify(dm); - } - - return NULL; - } - - if (!create) - return NULL; - - 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; - TAILQ_INIT(&dm->dm_epg_grab); - TAILQ_INIT(&dm->dm_table_queue); - - 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, - dn->dn_fe_type == FE_QPSK ? - dvb_polarisation_to_str(dmc->dmc_polarisation) : ""); - dm->dm_local_identifier = strdup(identifier); - - dm->dm_enabled = enabled; - - memcpy(&dm->dm_conf, dmc, sizeof(struct dvb_mux_conf)); - - if(source != NULL) { - tvhlog(LOG_NOTICE, "dvb", "New mux \"%s\" created by %s", - dvb_mux_nicename(dm), source); - - dvb_mux_save(dm); - } - - dvb_service_load(dm); - - if(enabled && needscan) { - dn->dn_initial_scan_num_mux++; - mux_link_initial(dn, dm); - } -#if TODO_FIX_THIS - dvb_adapter_notify(tda); -#endif - - return dm; -} - - -/** - * - */ -static 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(dvb_mux_t *dm) -{ - th_dvb_mux_instance_t *tdmi; - dvb_network_t *dn = dm->dm_dn; - - lock_assert(&global_lock); - - LIST_REMOVE(dm, dm_network_link); - - while((tdmi = LIST_FIRST(&dm->dm_tdmis)) != NULL) - dvb_tdmi_destroy(tdmi); - - 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; - } - - - epggrab_mux_delete(dm); - - free(dm->dm_local_identifier); - idnode_unlink(&dm->dm_id); - free(dm); -} - - -#if DVB_API_VERSION >= 5 -static struct strtab rollofftab[] = { - { "ROLLOFF_35", ROLLOFF_35 }, - { "ROLLOFF_20", ROLLOFF_20 }, - { "ROLLOFF_25", ROLLOFF_25 }, - { "ROLLOFF_AUTO", ROLLOFF_AUTO } -}; - -static struct strtab delsystab[] = { - { "SYS_UNDEFINED", SYS_UNDEFINED }, - { "SYS_DVBC_ANNEX_AC", SYS_DVBC_ANNEX_AC }, - { "SYS_DVBC_ANNEX_B", SYS_DVBC_ANNEX_B }, - { "SYS_DVBT", SYS_DVBT }, - { "SYS_DSS", SYS_DSS }, - { "SYS_DVBS", SYS_DVBS }, - { "SYS_DVBS2", SYS_DVBS2 }, - { "SYS_DVBH", SYS_DVBH }, - { "SYS_ISDBT", SYS_ISDBT }, - { "SYS_ISDBS", SYS_ISDBS }, - { "SYS_ISDBC", SYS_ISDBC }, - { "SYS_ATSC", SYS_ATSC }, - { "SYS_ATSCMH", SYS_ATSCMH }, - { "SYS_DMBTH", SYS_DMBTH }, - { "SYS_CMMB", SYS_CMMB }, - { "SYS_DAB", SYS_DAB } -}; -#endif - - -static struct strtab fectab[] = { - { "NONE", FEC_NONE }, - { "1/2", FEC_1_2 }, - { "2/3", FEC_2_3 }, - { "3/4", FEC_3_4 }, - { "4/5", FEC_4_5 }, - { "5/6", FEC_5_6 }, - { "6/7", FEC_6_7 }, - { "7/8", FEC_7_8 }, - { "8/9", FEC_8_9 }, - { "AUTO", FEC_AUTO }, -#if DVB_API_VERSION >= 5 - { "3/5", FEC_3_5 }, - { "9/10", FEC_9_10 } -#endif -}; - -static struct strtab qamtab[] = { - { "QPSK", QPSK }, - { "QAM16", QAM_16 }, - { "QAM32", QAM_32 }, - { "QAM64", QAM_64 }, - { "QAM128", QAM_128 }, - { "QAM256", QAM_256 }, - { "AUTO", QAM_AUTO }, - { "8VSB", VSB_8 }, - { "16VSB", VSB_16 }, -#if DVB_API_VERSION >= 5 - { "PSK_8", PSK_8 }, - { "APSK_16", APSK_16 }, - { "APSK_32", APSK_32 }, - { "DQPSK", DQPSK } -#endif -}; - - -static struct strtab bwtab[] = { - { "8MHz", BANDWIDTH_8_MHZ }, - { "7MHz", BANDWIDTH_7_MHZ }, - { "6MHz", BANDWIDTH_6_MHZ }, - { "AUTO", BANDWIDTH_AUTO }, -#if DVB_VER_ATLEAST(5,3) - { "5MHz", BANDWIDTH_5_MHZ }, - { "10MHz", BANDWIDTH_10_MHZ }, - { "1712kHz", BANDWIDTH_1_712_MHZ}, -#endif -}; - -static struct strtab modetab[] = { - { "2k", TRANSMISSION_MODE_2K }, - { "8k", TRANSMISSION_MODE_8K }, - { "AUTO", TRANSMISSION_MODE_AUTO }, -#if DVB_VER_ATLEAST(5,3) - { "1k", TRANSMISSION_MODE_1K }, - { "2k", TRANSMISSION_MODE_16K }, - { "32k", TRANSMISSION_MODE_32K }, -#endif -}; - -static struct strtab guardtab[] = { - { "1/32", GUARD_INTERVAL_1_32 }, - { "1/16", GUARD_INTERVAL_1_16 }, - { "1/8", GUARD_INTERVAL_1_8 }, - { "1/4", GUARD_INTERVAL_1_4 }, - { "AUTO", GUARD_INTERVAL_AUTO }, -#if DVB_VER_ATLEAST(5,3) - { "1/128", GUARD_INTERVAL_1_128 }, - { "19/128", GUARD_INTERVAL_19_128 }, - { "19/256", GUARD_INTERVAL_19_256}, -#endif -}; - -static struct strtab hiertab[] = { - { "NONE", HIERARCHY_NONE }, - { "1", HIERARCHY_1 }, - { "2", HIERARCHY_2 }, - { "4", HIERARCHY_4 }, - { "AUTO", HIERARCHY_AUTO } -}; - -static struct strtab poltab[] = { - { "Vertical", POLARISATION_VERTICAL }, - { "Horizontal", POLARISATION_HORIZONTAL }, - { "Left", POLARISATION_CIRCULAR_LEFT }, - { "Right", POLARISATION_CIRCULAR_RIGHT }, -}; - -/** - * for external use - */ -const char* dvb_mux_fec2str(int fec) { - return val2str(fec, fectab); -} - -#if DVB_API_VERSION >= 5 -/** - * for external use - */ -const char* dvb_mux_delsys2str(int delsys) { - return val2str(delsys, delsystab); -} - -/** - * for external use - */ -const char* dvb_mux_qam2str(int qam) { - return val2str(qam, qamtab); -} - -/** - * for external use - */ -const char* dvb_mux_rolloff2str(int rolloff) { - return val2str(rolloff, rollofftab); -} -#endif - -/** - * for external use - */ -int dvb_mux_str2bw(const char *str) -{ - return str2val(str, bwtab); -} - -int dvb_mux_str2qam(const char *str) -{ - return str2val(str, qamtab); -} - -int dvb_mux_str2fec(const char *str) -{ - return str2val(str, fectab); -} - -int dvb_mux_str2mode(const char *str) -{ - return str2val(str, modetab); -} - -int dvb_mux_str2guard(const char *str) -{ - return str2val(str, guardtab); -} - -int dvb_mux_str2hier(const char *str) -{ - return str2val(str, hiertab); -} - -/** - * - */ -void -dvb_mux_save(dvb_mux_t *dm) -{ - 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, "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); - 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, "needscan", dm->dm_scan_status != DM_SCAN_DONE); - - if(dm->dm_default_authority) - htsmsg_add_str(m, "default_authority", dm->dm_default_authority); - - switch(dm->dm_dn->dn_fe_type) { - case FE_OFDM: - htsmsg_add_str(m, "bandwidth", - val2str(f->u.ofdm.bandwidth, bwtab)); - - htsmsg_add_str(m, "constellation", - val2str(f->u.ofdm.constellation, qamtab)); - - htsmsg_add_str(m, "transmission_mode", - val2str(f->u.ofdm.transmission_mode, modetab)); - - htsmsg_add_str(m, "guard_interval", - val2str(f->u.ofdm.guard_interval, guardtab)); - - htsmsg_add_str(m, "hierarchy", - val2str(f->u.ofdm.hierarchy_information, hiertab)); - - htsmsg_add_str(m, "fec_hi", - val2str(f->u.ofdm.code_rate_HP, fectab)); - - htsmsg_add_str(m, "fec_lo", - val2str(f->u.ofdm.code_rate_LP, fectab)); - break; - - case FE_QPSK: - htsmsg_add_u32(m, "symbol_rate", f->u.qpsk.symbol_rate); - - htsmsg_add_str(m, "fec", - val2str(f->u.qpsk.fec_inner, fectab)); - - htsmsg_add_str(m, "polarisation", - val2str(dmc->dmc_polarisation, poltab)); - -#if DVB_API_VERSION >= 5 - htsmsg_add_str(m, "modulation", - val2str(dmc->dmc_fe_modulation, qamtab)); - - htsmsg_add_str(m, "delivery_system", - val2str(dmc->dmc_fe_delsys, delsystab)); - - htsmsg_add_str(m, "rolloff", - val2str(dmc->dmc_fe_rolloff, rollofftab)); -#endif - break; - - case FE_QAM: - htsmsg_add_u32(m, "symbol_rate", f->u.qam.symbol_rate); - - htsmsg_add_str(m, "fec", - val2str(f->u.qam.fec_inner, fectab)); - - htsmsg_add_str(m, "constellation", - val2str(f->u.qam.modulation, qamtab)); - break; - - case FE_ATSC: - htsmsg_add_str(m, "constellation", - val2str(f->u.vsb.modulation, qamtab)); - break; - } - - hts_settings_save(m, "dvb/networks/%s/muxes/%s/config", - idnode_uuid_as_str(&dm->dm_dn->dn_id), - dm->dm_local_identifier); - - htsmsg_destroy(m); -} - -/** - * - */ -static const char * -dvb_mux_create_by_msg(dvb_network_t *dn, htsmsg_t *m, const char *fname) -{ - dvb_mux_t *dm; - struct dvb_mux_conf dmc; - const char *s; - int r; - unsigned int onid, tsid, enabled; - - memset(&dmc, 0, sizeof(dmc)); - dmc.dmc_fe_params.inversion = INVERSION_AUTO; - htsmsg_get_u32(m, "frequency", &dmc.dmc_fe_params.frequency); - - switch(dn->dn_fe_type) { - case FE_OFDM: - s = htsmsg_get_str(m, "bandwidth"); - if(s == NULL || (r = str2val(s, bwtab)) < 0) - return "Invalid bandwidth"; - dmc.dmc_fe_params.u.ofdm.bandwidth = r; - - s = htsmsg_get_str(m, "constellation"); - if(s == NULL || (r = str2val(s, qamtab)) < 0) - return "Invalid QAM constellation"; - dmc.dmc_fe_params.u.ofdm.constellation = r; - - s = htsmsg_get_str(m, "transmission_mode"); - if(s == NULL || (r = str2val(s, modetab)) < 0) - return "Invalid transmission mode"; - dmc.dmc_fe_params.u.ofdm.transmission_mode = r; - - s = htsmsg_get_str(m, "guard_interval"); - if(s == NULL || (r = str2val(s, guardtab)) < 0) - return "Invalid guard interval"; - dmc.dmc_fe_params.u.ofdm.guard_interval = r; - - s = htsmsg_get_str(m, "hierarchy"); - if(s == NULL || (r = str2val(s, hiertab)) < 0) - return "Invalid heirarchy information"; - dmc.dmc_fe_params.u.ofdm.hierarchy_information = r; - - s = htsmsg_get_str(m, "fec_hi"); - if(s == NULL || (r = str2val(s, fectab)) < 0) - return "Invalid hi-FEC"; - dmc.dmc_fe_params.u.ofdm.code_rate_HP = r; - - s = htsmsg_get_str(m, "fec_lo"); - if(s == NULL || (r = str2val(s, fectab)) < 0) - return "Invalid lo-FEC"; - dmc.dmc_fe_params.u.ofdm.code_rate_LP = r; - break; - - case FE_QPSK: - htsmsg_get_u32(m, "symbol_rate", &dmc.dmc_fe_params.u.qpsk.symbol_rate); - if(dmc.dmc_fe_params.u.qpsk.symbol_rate == 0) - return "Invalid symbol rate"; - - s = htsmsg_get_str(m, "fec"); - if(s == NULL || (r = str2val(s, fectab)) < 0) - return "Invalid FEC"; - dmc.dmc_fe_params.u.qpsk.fec_inner = r; - - s = htsmsg_get_str(m, "polarisation"); - if(s == NULL || (r = str2val(s, poltab)) < 0) - return "Invalid polarisation"; - dmc.dmc_polarisation = r; - -#if DVB_API_VERSION >= 5 - s = htsmsg_get_str(m, "modulation"); - if(s == NULL || (r = str2val(s, qamtab)) < 0) { - r = str2val("QPSK", qamtab); - tvhlog(LOG_INFO, - "dvb", "no modulation for mux found, defaulting to QPSK"); - } - dmc.dmc_fe_modulation = r; - - s = htsmsg_get_str(m, "delivery_system"); - if(s == NULL || (r = str2val(s, delsystab)) < 0) { - r = str2val("SYS_DVBS", delsystab); - tvhlog(LOG_INFO, - "dvb", "no delivery system for mux found, defaulting to SYS_DVBS"); - } - dmc.dmc_fe_delsys = r; - - s = htsmsg_get_str(m, "rolloff"); - if(s == NULL || (r = str2val(s, rollofftab)) < 0) { - r = str2val("ROLLOFF_35", rollofftab); - tvhlog(LOG_INFO, - "dvb", "no rolloff for mux found, defaulting to ROLLOFF_35"); - } - dmc.dmc_fe_rolloff = r; -#endif - break; - - case FE_QAM: - htsmsg_get_u32(m, "symbol_rate", &dmc.dmc_fe_params.u.qam.symbol_rate); - if(dmc.dmc_fe_params.u.qam.symbol_rate == 0) - return "Invalid symbol rate"; - - s = htsmsg_get_str(m, "constellation"); - if(s == NULL || (r = str2val(s, qamtab)) < 0) - return "Invalid QAM constellation"; - dmc.dmc_fe_params.u.qam.modulation = r; - - s = htsmsg_get_str(m, "fec"); - if(s == NULL || (r = str2val(s, fectab)) < 0) - return "Invalid FEC"; - dmc.dmc_fe_params.u.qam.fec_inner = r; - break; - - case FE_ATSC: - s = htsmsg_get_str(m, "constellation"); - if(s == NULL || (r = str2val(s, qamtab)) < 0) - return "Invalid VSB constellation"; - dmc.dmc_fe_params.u.vsb.modulation = r; - - break; - } - - if(htsmsg_get_u32(m, "transportstreamid", &tsid)) - tsid = 0xffff; - if(htsmsg_get_u32(m, "originalnetworkid", &onid)) - onid = 0; - - 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), - uuid, NULL, 1, NULL); - 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; -} - - -/** - * - */ -void -dvb_mux_load(dvb_network_t *dn) -{ - htsmsg_t *l, *c; - htsmsg_field_t *f; - - if((l = hts_settings_load_r(1, "dvb/networks/%s/muxes", - 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); -} - - - -/** - * - */ -void -dvb_mux_set_networkname(dvb_mux_t *dm, const char *networkname) -{ - htsmsg_t *m; - - if (!networkname || !*networkname) - return; - - if (!strcmp(dm->dm_network_name ?: "", networkname)) - return; - - free(dm->dm_network_name); - dm->dm_network_name = strdup(networkname); - - dvb_mux_save(dm); - - m = htsmsg_create_map(); - htsmsg_add_str(m, "id", dm->dm_local_identifier); - htsmsg_add_str(m, "network", dm->dm_network_name ?: ""); - notify_by_msg("dvbMux", m); -} - - -/** - * - */ -void -dvb_mux_set_tsid(dvb_mux_t *dm, uint16_t tsid, int force) -{ - htsmsg_t *m; - - if (!force) - if (dm->dm_transport_stream_id != 0xFFFF || tsid == 0xFFFF) - return; - - if (dm->dm_transport_stream_id == tsid) - return; - - dm->dm_transport_stream_id = tsid; - - dvb_mux_save(dm); - - m = htsmsg_create_map(); - 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); -} - -/** - * - */ -void -dvb_mux_set_onid(dvb_mux_t *dm, uint16_t onid, int force) -{ - htsmsg_t *m; - - if (!force) - if (dm->dm_network_id != 0 || onid == 0) - return; - - if (dm->dm_network_id == onid) - return; - - dm->dm_network_id = onid; - - dvb_mux_save(dm); - - m = htsmsg_create_map(); - 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); -} - -/** - * - */ -static void -dvb_mux_modulation(char *buf, size_t size, const dvb_mux_t *dm) -{ - const dvb_mux_conf_t *dmc = &dm->dm_conf; - const struct dvb_frontend_parameters *f = &dmc->dmc_fe_params; - - switch(dm->dm_dn->dn_fe_type) { - case FE_OFDM: - snprintf(buf, size, "%s, %s, %s-mode", - val2str(f->u.ofdm.constellation, qamtab), - val2str(f->u.ofdm.bandwidth, bwtab), - val2str(f->u.ofdm.transmission_mode, modetab)); - break; - - case FE_QPSK: -#if DVB_API_VERSION >= 5 - snprintf(buf, size, "%d kBaud, %s, %s", f->u.qpsk.symbol_rate / 1000, - 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 - break; - - case FE_QAM: - snprintf(buf, size, "%s, %d kBaud", - val2str(f->u.qam.modulation, qamtab), - f->u.qpsk.symbol_rate / 1000); - break; - - case FE_ATSC: - snprintf(buf, size, "%s", val2str(f->u.vsb.modulation, qamtab)); - break; - default: - snprintf(buf, size, "Unknown"); - break; - } -} - - -/** - * - */ -htsmsg_t * -dvb_mux_build_msg(dvb_mux_t *dm) -{ - htsmsg_t *m = htsmsg_create_map(); - char buf[100]; - -#if TODO_FIX_THIS - htsmsg_add_str(m, "adapterId", tdmi->tdmi_adapter->tda_identifier); -#endif - - 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 ?: ""); - - htsmsg_add_str(m, "freq", dvb_mux_nicefreq(dm)); - - dvb_mux_modulation(buf, sizeof(buf), dm); - htsmsg_add_str(m, "mod", buf); - - const dvb_mux_conf_t *dmc = &dm->dm_conf; - - htsmsg_add_str(m, "pol", - dvb_polarisation_to_str_long(dmc->dmc_polarisation)); - - if(dm->dm_transport_stream_id != 0xffff) - htsmsg_add_u32(m, "muxid", dm->dm_transport_stream_id); - - if(dm->dm_network_id) - htsmsg_add_u32(m, "onid", dm->dm_network_id); - - return m; -} - - -/** - * - */ -void -dvb_mux_notify(dvb_mux_t *dm) -{ - // notify_by_msg("dvbMux", dvb_mux_build_msg(tdmi)); -} - - -/** - * - */ -const char * -dvb_mux_add_by_params(dvb_network_t *dn, - int freq, - int symrate, - int bw, - int constellation, - int delsys, - int tmode, - int guard, - int hier, - int fechi, - int feclo, - int fec, - int polarisation, - const char *satconf) -{ - struct dvb_mux_conf dmc; - - memset(&dmc, 0, sizeof(dmc)); - dmc.dmc_fe_params.inversion = INVERSION_AUTO; - - switch(dn->dn_fe_type) { - case FE_OFDM: - dmc.dmc_fe_params.frequency = freq * 1000; - if(!val2str(bw, bwtab)) - return "Invalid bandwidth"; - - if(!val2str(constellation, qamtab)) - return "Invalid QAM constellation"; - - if(!val2str(tmode, modetab)) - return "Invalid transmission mode"; - - if(!val2str(guard, guardtab)) - return "Invalid guard interval"; - - if(!val2str(hier, hiertab)) - return "Invalid hierarchy"; - - if(!val2str(fechi, fectab)) - return "Invalid FEC Hi"; - - if(!val2str(feclo, fectab)) - return "Invalid FEC Lo"; - - dmc.dmc_fe_params.u.ofdm.bandwidth = bw; - dmc.dmc_fe_params.u.ofdm.constellation = constellation; - dmc.dmc_fe_params.u.ofdm.transmission_mode = tmode; - dmc.dmc_fe_params.u.ofdm.guard_interval = guard; - dmc.dmc_fe_params.u.ofdm.hierarchy_information = hier; - dmc.dmc_fe_params.u.ofdm.code_rate_HP = fechi; - dmc.dmc_fe_params.u.ofdm.code_rate_LP = feclo; - polarisation = 0; - break; - - case FE_QAM: - dmc.dmc_fe_params.frequency = freq * 1000; - - if(!val2str(constellation, qamtab)) - return "Invalid QAM constellation"; - - if(!val2str(fec, fectab)) - return "Invalid FEC"; - - dmc.dmc_fe_params.u.qam.symbol_rate = symrate; - dmc.dmc_fe_params.u.qam.modulation = constellation; - dmc.dmc_fe_params.u.qam.fec_inner = fec; - polarisation = 0; - break; - - case FE_QPSK: - dmc.dmc_fe_params.frequency = freq; - - if(!val2str(fec, fectab)) - return "Invalid FEC"; - - if(!val2str(polarisation, poltab)) - return "Invalid polarisation"; - - dmc.dmc_fe_params.u.qpsk.symbol_rate = symrate; - dmc.dmc_fe_params.u.qpsk.fec_inner = fec; - -#if DVB_API_VERSION >= 5 - if(!val2str(constellation, qamtab)) - return "Invalid QPSK constellation"; - - if(!val2str(delsys, delsystab)) - return "Invalid delivery system"; - - dmc.dmc_fe_delsys = delsys; - dmc.dmc_fe_modulation = constellation; -#endif - break; - - case FE_ATSC: - dmc.dmc_fe_params.frequency = freq * 1000; - - if(!val2str(constellation, qamtab)) - return "Invalid VSB constellation"; - - dmc.dmc_fe_params.u.vsb.modulation = constellation; - break; - - } - - dmc.dmc_polarisation = polarisation; - - dvb_mux_t *dm = dvb_mux_create(dn, &dmc, 0, 0xffff, NULL, NULL, 1, 1, NULL, NULL, 1, NULL); - - if(dm == NULL) - return "Mux already exist"; - - return NULL; -} - -#if 0 -/** - * - */ -int -dvb_mux_copy(th_dvb_adapter_t *dst, th_dvb_mux_instance_t *tdmi_src, - dvb_satconf_t *satconf) -{ - th_dvb_mux_instance_t *tdmi_dst; - service_t *t_src, *t_dst; - elementary_stream_t *st_src, *st_dst; - caid_t *caid_src, *caid_dst; - - tdmi_dst = dvb_mux_create(dst, - &tdmi_src->tdmi_conf, - tdmi_src->tdmi_network_id, - tdmi_src->tdmi_transport_stream_id, - tdmi_src->tdmi_network, - "copy operation", tdmi_src->tdmi_enabled, - 1, NULL, satconf, 1, tdmi_src); - - if(tdmi_dst == NULL) - return -1; // Already exist - - 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); - - t_dst->s_pcr_pid = t_src->s_pcr_pid; - t_dst->s_enabled = t_src->s_enabled; - t_dst->s_servicetype = t_src->s_servicetype; - t_dst->s_scrambled = t_src->s_scrambled; - - if(t_src->s_provider != NULL) - t_dst->s_provider = strdup(t_src->s_provider); - - if(t_src->s_svcname != NULL) - t_dst->s_svcname = strdup(t_src->s_svcname); - - if(t_src->s_dvb_charset != NULL) - t_dst->s_dvb_charset = strdup(t_src->s_dvb_charset); - - if(t_src->s_ch != NULL) - service_map_channel(t_dst, t_src->s_ch, 0); - - pthread_mutex_lock(&t_src->s_stream_mutex); - pthread_mutex_lock(&t_dst->s_stream_mutex); - - TAILQ_FOREACH(st_src, &t_src->s_components, es_link) { - - - st_dst = service_stream_create(t_dst, - st_src->es_pid, - st_src->es_type); - - memcpy(st_dst->es_lang, st_src->es_lang, 4); - st_dst->es_frame_duration = st_src->es_frame_duration; - - LIST_FOREACH(caid_src, &st_src->es_caids, link) { - caid_dst = malloc(sizeof(caid_t)); - - caid_dst->caid = caid_src->caid; - caid_dst->providerid = caid_src->providerid; - caid_dst->delete_me = 0; - LIST_INSERT_HEAD(&st_dst->es_caids, caid_dst, link); - } - } - - pthread_mutex_unlock(&t_dst->s_stream_mutex); - pthread_mutex_unlock(&t_src->s_stream_mutex); - - t_dst->s_config_save(t_dst); // Save config - - } - dvb_mux_save(tdmi_dst); - return 0; -} -#endif - -dvb_mux_t * -dvb_mux_find(dvb_network_t *dn, const char *netname, uint16_t onid, - uint16_t tsid, int enabled) -{ - 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 { - 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; -} - - -/** - * - */ -th_subscription_t * -dvb_subscription_create_from_tdmi(th_dvb_mux_instance_t *tdmi, - const char *name, - streaming_target_t *st, - const char *hostname, - const char *username, - const char *client) -{ - th_subscription_t *s; -#if 0 - streaming_message_t *sm; - streaming_start_t *ss; - int r; - th_dvb_adapter_t *tda = tdmi->tdmi_adapter; - char buf[100]; - th_dvb_adapter_t *tda = tdmi->tdmi_adapter; -#endif - - s = subscription_create(INT32_MAX, name, st, SUBSCRIPTION_RAW_MPEGTS, - NULL, hostname, username, client); - - - s->ths_tdmi = tdmi; - LIST_INSERT_HEAD(&tdmi->tdmi_subscriptions, s, ths_tdmi_link); - - dvb_mux_tune(tdmi->tdmi_mux, "Full mux subscription", 99999); - abort(); -#if 0 ->>>>>>> origin/dvbnetworks - pthread_mutex_lock(&tda->tda_delivery_mutex); - - streaming_target_connect(&tda->tda_streaming_pad, &s->ths_input); - - if(r) { - sm = streaming_msg_create_code(SMT_NOSTART, SM_CODE_NO_INPUT); - streaming_target_deliver(s->ths_output, sm); - } else { - ss = calloc(1, sizeof(streaming_start_t)); - ss->ss_num_components = 0; - ss->ss_refcount = 1; - - ss->ss_si.si_type = S_MPEG_TS; - ss->ss_si.si_device = strdup(tdmi->tdmi_adapter->tda_rootpath); - ss->ss_si.si_adapter = strdup(tdmi->tdmi_adapter->tda_displayname); - ss->ss_si.si_service = strdup("Full mux subscription"); - - if(tdmi->tdmi_network != NULL) - ss->ss_si.si_network = strdup(tdmi->tdmi_network); - - dvb_mux_nicename(buf, sizeof(buf), tdmi); - ss->ss_si.si_mux = strdup(buf); - - - sm = streaming_msg_create_data(SMT_START, ss); - streaming_target_deliver(s->ths_output, sm); - } - - pthread_mutex_unlock(&tda->tda_delivery_mutex); -#endif - notify_reload("subscriptions"); - return s; -} - - - -/** - * - */ -static const char * -dvb_mux_get_title(struct idnode *self) -{ - return dvb_mux_nicename((dvb_mux_t *)self); -} - -/** - * - */ -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; -} - - - -/** - * These are created on the fly - */ -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); - } - } -} - - - -/** - * - */ -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); - - 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; -} - - -/** - * - */ -int -tdmi_current_weight(const th_dvb_mux_instance_t *tdmi) -{ - 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; -} - - -/** - * - */ -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; - - lock_assert(&global_lock); - - if(dm->dm_current_tdmi == NULL) { - - dvb_create_tdmis(dm); - - 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; - - 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_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(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); - } - - return 0; -} diff --git a/src/input/mpegts/linuxdvb/dvb_network.c b/src/input/mpegts/linuxdvb/dvb_network.c deleted file mode 100644 index 74c8a14b..00000000 --- a/src/input/mpegts/linuxdvb/dvb_network.c +++ /dev/null @@ -1,255 +0,0 @@ -/* - * 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 - -#include "tvheadend.h" -#include "packet.h" -#include "dvb.h" -#include "epggrab.h" -#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 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) - }, { - "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) - }, {}}, -}; - -/** - * - */ -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); - return NULL; - } - - dn->dn_fe_type = fe_type; - TAILQ_INIT(&dn->dn_initial_scan_pending_queue); - 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; -} - - -/** - * - */ -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) -{ - const char *s = htsmsg_get_str(m, "type"); - if(s == NULL) - return; - - 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); -} - - -/** - * - */ -static void -dvb_network_save(idnode_t *in) -{ - dvb_network_t *dn = (dvb_network_t *)in; - htsmsg_t *m = htsmsg_create_map(); - - lock_assert(&global_lock); - - 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(in)); - - htsmsg_destroy(m); -} - - -/** - * - */ -static void -dvb_network_initial_scan(void *aux) -{ - dvb_network_t *dn = aux; - dvb_mux_t *dm; - - while((dm = TAILQ_FIRST(&dn->dn_initial_scan_pending_queue)) != NULL) { - assert(dm->dm_scan_status == DM_SCAN_PENDING); - if(dvb_mux_tune(dm, "initial scan", 1)) - break; - assert(dm->dm_scan_status == DM_SCAN_CURRENT); - } - 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((l = hts_settings_load_r(1, "dvb/networks")) == 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_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/input/mpegts/linuxdvb/dvb_preconf.c b/src/input/mpegts/linuxdvb/dvb_preconf.c deleted file mode 100644 index f6e2ca23..00000000 --- a/src/input/mpegts/linuxdvb/dvb_preconf.c +++ /dev/null @@ -1,205 +0,0 @@ -/* - * TV headend - Code for configuring DVB muxes - * This code is based on code from linux dvb-apps - * - * 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 "settings.h" - -#include - -#include "tvheadend.h" -#include "dvb.h" -#include "dvb_preconf.h" -#include "muxes.h" - -/** - * - */ -static void -dvb_mux_preconf_add(dvb_network_t *dn, const network_t *net, - const char *source) -{ - const mux_t *m; - struct dvb_mux_conf dmc; - - LIST_FOREACH(m, &net->muxes, link) { - - memset(&dmc, 0, sizeof(dmc)); - - dmc.dmc_fe_params.inversion = INVERSION_AUTO; - dmc.dmc_fe_params.frequency = m->freq; - - 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; - dmc.dmc_fe_params.u.ofdm.transmission_mode = m->tmode; - dmc.dmc_fe_params.u.ofdm.guard_interval = m->guard; - dmc.dmc_fe_params.u.ofdm.hierarchy_information = m->hierarchy; - dmc.dmc_fe_params.u.ofdm.code_rate_HP = m->fechp; - dmc.dmc_fe_params.u.ofdm.code_rate_LP = m->feclp; - break; - - case FE_QPSK: -#if DVB_API_VERSION >= 5 - dmc.dmc_fe_delsys = SYS_DVBS; -#endif - dmc.dmc_fe_params.u.qpsk.symbol_rate = m->symrate; - dmc.dmc_fe_params.u.qpsk.fec_inner = m->fec; - - switch(m->polarisation) { - case 'V': - dmc.dmc_polarisation = POLARISATION_VERTICAL; - break; - case 'H': - dmc.dmc_polarisation = POLARISATION_HORIZONTAL; - break; - case 'L': - dmc.dmc_polarisation = POLARISATION_CIRCULAR_LEFT; - break; - case 'R': - dmc.dmc_polarisation = POLARISATION_CIRCULAR_RIGHT; - break; - default: - abort(); - } - - break; - - case FE_QAM: - dmc.dmc_fe_params.u.qam.symbol_rate = m->symrate; - dmc.dmc_fe_params.u.qam.modulation = m->constellation; - dmc.dmc_fe_params.u.qam.fec_inner = m->fec; - break; - - case FE_ATSC: - dmc.dmc_fe_params.u.vsb.modulation = m->constellation; - break; - } - -#if TODO_FIX_THIS - dmc.dmc_satconf = dvb_satconf_entry_find(tda, satconf, 0); -#endif - - dvb_mux_create(dn, &dmc, 0, 0xffff, NULL, source, 1, 1, NULL, NULL, 1, NULL); - } -} - - -/** - * - */ -int -dvb_mux_preconf_add_network(dvb_network_t *dn, const char *id) -{ - region_list_t *list; - const region_t *r; - const network_t *n; - char source[100]; - - snprintf(source, sizeof(source), "built-in configuration from \"%s\"", id); - - switch(dn->dn_fe_type) { - case FE_QAM: - list = ®ions_DVBC; - break; - case FE_QPSK: - list = ®ions_DVBS; - break; - case FE_OFDM: - list = ®ions_DVBT; - break; - case FE_ATSC: - list = ®ions_ATSC; - break; - default: - return -1; - } - - LIST_FOREACH(r, list, link) { - LIST_FOREACH(n, &r->networks, link) { - if(!strcmp(n->id, id)) { - dvb_mux_preconf_add(dn, n, source); - break; - } - } - } - return 0; -} - -/** - * - */ -htsmsg_t * -dvb_mux_preconf_get_node(int fetype, const char *node) -{ - region_list_t *list = NULL; - const region_t *r; - const network_t *n; - htsmsg_t *out, *e; - - switch(fetype) { - case FE_QAM: - list = ®ions_DVBC; - break; - case FE_QPSK: - list = ®ions_DVBS; - break; - case FE_OFDM: - list = ®ions_DVBT; - break; - case FE_ATSC: - list = ®ions_ATSC; - break; - default: - tvhlog(LOG_ERR, "DVB", "No built-in config for fetype %d", fetype); - return NULL; - } - - out = htsmsg_create_list(); - - if(!strcmp(node, "root")) { - LIST_FOREACH(r, list, link) { - e = htsmsg_create_map(); - htsmsg_add_u32(e, "leaf", 0); - htsmsg_add_str(e, "text", r->name); - htsmsg_add_str(e, "id", r->id); - htsmsg_add_msg(out, NULL, e); - } - return out; - } - - LIST_FOREACH(r, list, link) - if (!strcmp(node, r->id)) - break; - if (!r) return out; - - LIST_FOREACH(n, &r->networks, link) { - e = htsmsg_create_map(); - htsmsg_add_u32(e, "leaf", 1); - htsmsg_add_str(e, "text", n->name); - htsmsg_add_str(e, "id", n->id); - htsmsg_add_msg(out, NULL, e); - } - - return out; -} diff --git a/src/input/mpegts/linuxdvb/dvb_preconf.h b/src/input/mpegts/linuxdvb/dvb_preconf.h deleted file mode 100644 index a3c14da3..00000000 --- a/src/input/mpegts/linuxdvb/dvb_preconf.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - * TV headend - Code for configuring DVB muxes - * Copyright (C) 2007 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 . - */ - -#ifndef DVB_MUXCONFIG_H_ -#define DVB_MUXCONFIG_H_ - -#include "htsmsg.h" - -htsmsg_t *dvb_mux_preconf_get_node(int fetype, const char *node); - -int dvb_mux_preconf_add_network(dvb_network_t *dn, const char *id); - -#endif /* DVB_MUXCONFIG_H */ diff --git a/src/input/mpegts/linuxdvb/dvb_satconf.c b/src/input/mpegts/linuxdvb/dvb_satconf.c deleted file mode 100644 index b0d609de..00000000 --- a/src/input/mpegts/linuxdvb/dvb_satconf.c +++ /dev/null @@ -1,340 +0,0 @@ -/* - * Satconf - * Copyright (C) 2009 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 - -#include -#include - -#include "tvheadend.h" -#include "dvb.h" -#include "dtable.h" -#include "notify.h" - -/** - * - */ -static void -satconf_notify(th_dvb_adapter_t *tda) -{ - htsmsg_t *m = htsmsg_create_map(); - - htsmsg_add_str(m, "adapterId", tda->tda_identifier); - notify_by_msg("dvbSatConf", m); -} - - -/** - * - */ -dvb_satconf_t * -dvb_satconf_entry_find(th_dvb_adapter_t *tda, const char *id, int create) -{ - char buf[20]; - dvb_satconf_t *sc; - static int tally; - - if(id != NULL) { - TAILQ_FOREACH(sc, &tda->tda_satconfs, sc_adapter_link) - if(!strcmp(sc->sc_id, id)) - return sc; - } - if(create == 0) - return NULL; - - if(id == NULL) { - tally++; - snprintf(buf, sizeof(buf), "%d", tally); - id = buf; - } else { - tally = MAX(atoi(id), tally); - } - - sc = calloc(1, sizeof(dvb_satconf_t)); - sc->sc_id = strdup(id); - sc->sc_lnb = strdup("Universal"); - TAILQ_INSERT_TAIL(&tda->tda_satconfs, sc, sc_adapter_link); - - return sc; -} - - -/** - * - */ -static void -satconf_destroy(th_dvb_adapter_t *tda, dvb_satconf_t *sc) -{ - TAILQ_REMOVE(&tda->tda_satconfs, sc, sc_adapter_link); - free(sc->sc_id); - free(sc->sc_name); - free(sc->sc_comment); - free(sc); -} - - -/** - * - */ -static htsmsg_t * -satconf_record_build(dvb_satconf_t *sc) -{ - htsmsg_t *m = htsmsg_create_map(); - - htsmsg_add_str(m, "id", sc->sc_id); - htsmsg_add_u32(m, "port", sc->sc_port); - htsmsg_add_str(m, "name", sc->sc_name ?: ""); - htsmsg_add_str(m, "comment", sc->sc_comment ?: ""); - htsmsg_add_str(m, "lnb", sc->sc_lnb); - return m; -} - - -/** - * - */ -static htsmsg_t * -satconf_entry_update(void *opaque, const char *id, htsmsg_t *values, - int maycreate) -{ - th_dvb_adapter_t *tda = opaque; - uint32_t u32; - dvb_satconf_t *sc; - - if((sc = dvb_satconf_entry_find(tda, id, maycreate)) == NULL) - return NULL; - - lock_assert(&global_lock); - - tvh_str_update(&sc->sc_name, htsmsg_get_str(values, "name")); - tvh_str_update(&sc->sc_comment, htsmsg_get_str(values, "comment")); - tvh_str_update(&sc->sc_lnb, htsmsg_get_str(values, "lnb")); - - if(!htsmsg_get_u32(values, "port", &u32)) - sc->sc_port = u32; - - satconf_notify(tda); - - return satconf_record_build(sc); -} - - -/** - * - */ -static int -satconf_entry_delete(void *opaque, const char *id) -{ - th_dvb_adapter_t *tda = opaque; - dvb_satconf_t *sc; - - if((sc = dvb_satconf_entry_find(tda, id, 0)) == NULL) - return -1; - satconf_destroy(tda, sc); - satconf_notify(tda); - return 0; -} - - -/** - * - */ -static htsmsg_t * -satconf_entry_get_all(void *opaque) -{ - th_dvb_adapter_t *tda = opaque; - htsmsg_t *r = htsmsg_create_list(); - dvb_satconf_t *sc; - - TAILQ_FOREACH(sc, &tda->tda_satconfs, sc_adapter_link) - htsmsg_add_msg(r, NULL, satconf_record_build(sc)); - - return r; -} - - -/** - * - */ -static htsmsg_t * -satconf_entry_get(void *opaque, const char *id) -{ - th_dvb_adapter_t *tda = opaque; - dvb_satconf_t *sc; - if((sc = dvb_satconf_entry_find(tda, id, 0)) == NULL) - return NULL; - return satconf_record_build(sc); -} - - -/** - * - */ -static htsmsg_t * -satconf_entry_create(void *opaque) -{ - th_dvb_adapter_t *tda = opaque; - return satconf_record_build(dvb_satconf_entry_find(tda, NULL, 1)); -} - - -/** - * - */ -static const dtable_class_t satconf_dtc = { - .dtc_record_get = satconf_entry_get, - .dtc_record_get_all = satconf_entry_get_all, - .dtc_record_create = satconf_entry_create, - .dtc_record_update = satconf_entry_update, - .dtc_record_delete = satconf_entry_delete, - .dtc_read_access = ACCESS_ADMIN, - .dtc_write_access = ACCESS_ADMIN, - .dtc_mutex = &global_lock, -}; - - -/** - * - */ -void -dvb_satconf_init(th_dvb_adapter_t *tda) -{ - dtable_t *dt; - char name[256]; - dvb_satconf_t *sc; - htsmsg_t *r; - - snprintf(name, sizeof(name), "dvbsatconf/%s", tda->tda_identifier); - - dt = dtable_create(&satconf_dtc, name, tda); - if(!dtable_load(dt)) { - sc = dvb_satconf_entry_find(tda, NULL, 1); - sc->sc_comment = strdup("Default satconf entry"); - sc->sc_name = strdup("Default (Port 0, Universal LNB)"); - - r = satconf_record_build(sc); - dtable_record_store(dt, sc->sc_id, r); - htsmsg_destroy(r); - } -} - - -/** - * - */ -htsmsg_t * -dvb_satconf_list(th_dvb_adapter_t *tda) -{ - dvb_satconf_t *sc; - htsmsg_t *array = htsmsg_create_list(); - htsmsg_t *m; - - TAILQ_FOREACH(sc, &tda->tda_satconfs, sc_adapter_link) { - m = htsmsg_create_map(); - htsmsg_add_str(m, "identifier", sc->sc_id); - htsmsg_add_str(m, "name", sc->sc_name ?: ""); - htsmsg_add_msg(array, NULL, m); - } - return array; -} - - -/** - * - */ -static void -add_to_lnblist(htsmsg_t *array, const char *n) -{ - htsmsg_t *m = htsmsg_create_map(); - htsmsg_add_str(m, "identifier", n); - htsmsg_add_msg(array, NULL, m); -} - - -/** - * - */ -htsmsg_t * -dvb_lnblist_get(void) -{ - htsmsg_t *array = htsmsg_create_list(); - - add_to_lnblist(array, "Universal"); - add_to_lnblist(array, "DBS"); - add_to_lnblist(array, "DBS Bandstacked"); - add_to_lnblist(array, "Standard"); - add_to_lnblist(array, "Enhanced"); - add_to_lnblist(array, "C-Band"); - add_to_lnblist(array, "C-Multi"); - add_to_lnblist(array, "Circular 10750"); - add_to_lnblist(array, "Ku 11300"); - return array; -} - - -/** - * - */ -void -dvb_lnb_get_frequencies(const char *id, int *f_low, int *f_hi, int *f_switch) -{ - if(!strcmp(id, "Universal")) { - *f_low = 9750000; - *f_hi = 10600000; - *f_switch = 11700000; - } else if(!strcmp(id, "DBS")) { - *f_low = 11250000; - *f_hi = 0; - *f_switch = 0; - } else if(!strcmp(id, "DBS Bandstacked")) { - *f_low = 11250000; - *f_hi = 14350000; - *f_switch = 0; - } else if(!strcmp(id, "Standard")) { - *f_low = 10000000; - *f_hi = 0; - *f_switch = 0; - } else if(!strcmp(id, "Enhanced")) { - *f_low = 9750000; - *f_hi = 0; - *f_switch = 0; - } else if(!strcmp(id, "C-Band")) { - *f_low = 5150000; - *f_hi = 0; - *f_switch = 0; - } else if(!strcmp(id, "C-Multi")) { - *f_low = 5150000; - *f_hi = 5750000; - *f_switch = 0; - } else if(!strcmp(id, "Circular 10750")) { - *f_low = 10750000; - *f_hi = 0; - *f_switch = 0; - } else if(!strcmp(id, "Ku 11300")) { - *f_low = 11300000; - *f_hi = 0; - *f_switch = 0; - } -} diff --git a/src/input/mpegts/linuxdvb/dvb_service.c b/src/input/mpegts/linuxdvb/dvb_service.c deleted file mode 100644 index b79d3e52..00000000 --- a/src/input/mpegts/linuxdvb/dvb_service.c +++ /dev/null @@ -1,499 +0,0 @@ -/* - * TV Input - Linux DVB interface - * Copyright (C) 2007 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 -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "settings.h" - -#include "tvheadend.h" -#include "dvb.h" -#include "channels.h" -#include "subscriptions.h" -#include "psi.h" -#include "dvb_support.h" -#include "notify.h" - -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) - }, { - }} -}; - - -/** - * Switch the adapter (which is implicitly tied to our transport) - * to receive the given transport. - * - * But we only do this if 'weight' is higher than all of the current - * transports that is subscribing to the adapter - */ -static int -dvb_service_start(service_t *s, int instance) -{ - 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); - - LIST_FOREACH(tdmi, &dm->dm_tdmis, tdmi_mux_link) - if(tdmi->tdmi_adapter->tda_instance == instance) - break; - - assert(tdmi != NULL); // We should always find this instance - - r = dvb_fe_tune_tdmi(tdmi, "service start"); - - 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); - if (tda->tda_locked) { - tda->tda_open_service(tda, s); - dvb_table_add_pmt(dm, s->s_pmt_pid); - } - } - - return r; -} - -/** - * - */ -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; -} - - -/** - * - */ -static void -dvb_service_stop(service_t *s) -{ - th_dvb_adapter_t *tda = dvb_service_get_tda(s); - lock_assert(&global_lock); - - pthread_mutex_lock(&tda->tda_delivery_mutex); - LIST_REMOVE(s, s_active_link); - pthread_mutex_unlock(&tda->tda_delivery_mutex); - - tda->tda_close_service(tda, s); - - s->s_status = SERVICE_IDLE; -} - - -/** - * - */ -static void -dvb_service_refresh(service_t *s) -{ - th_dvb_adapter_t *tda = dvb_service_get_tda(s); - lock_assert(&global_lock); - 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)); - } -} - -/** - * - */ -static int -dvb_service_is_enabled(service_t *t) -{ - return t->s_dvb_mux->dm_enabled; -#if TODO_FIX_THIS - th_dvb_adapter_t *tda = tdmi->tdmi_adapter; - return tda->tda_enabled && tdmi->tdmi_enabled && t->s_enabled && t->s_pmt_pid; -#endif -} - - -/** - * - */ -static void -dvb_service_save(service_t *t) -{ - htsmsg_t *m = htsmsg_create_map(); - - 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); - htsmsg_add_u32(m, "scrambled", t->s_scrambled); - htsmsg_add_u32(m, "channel", t->s_channel_number); - - if(t->s_provider != NULL) - htsmsg_add_str(m, "provider", t->s_provider); - - if(t->s_svcname != NULL) - htsmsg_add_str(m, "servicename", t->s_svcname); - - if(t->s_ch != NULL) { - htsmsg_add_str(m, "channelname", t->s_ch->ch_name); - htsmsg_add_u32(m, "mapped", 1); - } - - 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) - htsmsg_add_str(m, "default_authority", t->s_default_authority); - - if(t->s_prefcapid) - htsmsg_add_u32(m, "prefcapid", t->s_prefcapid); - - pthread_mutex_lock(&t->s_stream_mutex); - psi_save_service_settings(m, t); - pthread_mutex_unlock(&t->s_stream_mutex); - - dvb_mux_t *dm = t->s_dvb_mux; - - hts_settings_save(m, "dvb/networks/%s/muxes/%s/services/%04x", - idnode_uuid_as_str(&dm->dm_dn->dn_id), - dm->dm_local_identifier, - t->s_dvb_service_id); - - htsmsg_destroy(m); -} - - -/** - * Load config for the given mux - */ -void -dvb_service_load(dvb_mux_t *dm) -{ - htsmsg_t *l, *c; - htsmsg_field_t *f; - uint32_t sid, pmt; - const char *s; - unsigned int u32; - service_t *t; - - lock_assert(&global_lock); - - l = hts_settings_load("dvb/networks/%s/muxes/%s/services", - idnode_uuid_as_str(&dm->dm_dn->dn_id), - dm->dm_local_identifier); - if(l == NULL) - return; - - HTSMSG_FOREACH(f, l) { - if((c = htsmsg_get_map_by_field(f)) == NULL) - continue; - - if(htsmsg_get_u32(c, "service_id", &sid)) - continue; - - if(htsmsg_get_u32(c, "pmt", &pmt)) - continue; - - 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)) - u32 = 0; - t->s_scrambled = u32; - - if(htsmsg_get_u32(c, "channel", &u32)) - u32 = 0; - t->s_channel_number = u32; - - s = htsmsg_get_str(c, "provider"); - t->s_provider = s ? strdup(s) : NULL; - - s = htsmsg_get_str(c, "servicename"); - t->s_svcname = s ? strdup(s) : NULL; - - pthread_mutex_lock(&t->s_stream_mutex); - service_make_nicename(t); - psi_load_service_settings(c, t); - pthread_mutex_unlock(&t->s_stream_mutex); - - if (!(s = htsmsg_get_str(c, "dvb_charset"))) - s = htsmsg_get_str(c, "dvb_default_charset"); - t->s_dvb_charset = s ? strdup(s) : NULL; - - s = htsmsg_get_str(c, "default_authority"); - t->s_default_authority = s ? strdup(s) : NULL; - - if(htsmsg_get_u32(c, "dvb_eit_enable", &u32)) - u32 = 1; - t->s_dvb_eit_enable = u32; - - s = htsmsg_get_str(c, "channelname"); - if(htsmsg_get_u32(c, "mapped", &u32)) - u32 = 0; - - if(s && u32) - service_map_channel(t, channel_find_by_name(s, 1, 0), 0); - - if(htsmsg_get_u32(c, "prefcapid", &u32)) - u32 = 0; - t->s_prefcapid = u32; - - /* HACK - force save for old config */ - if(uuid == NULL) { - // If service config on disk lacked UUID (for whatever reason), - // write it back - dvb_service_save(t); - } - } - htsmsg_destroy(l); -} - - - -/** - * Generate a descriptive name for the source - */ -static void -dvb_service_setsourceinfo(service_t *t, struct source_info *si) -{ - dvb_mux_t *dm = t->s_dvb_mux; - - memset(si, 0, sizeof(struct source_info)); - - lock_assert(&global_lock); - - si->si_type = S_MPEG_TS; - - if(dm->dm_network_name != NULL) - si->si_network = strdup(dm->dm_network_name); - - si->si_mux = strdup(dvb_mux_nicename(dm)); - - if(t->s_provider != NULL) - si->si_provider = strdup(t->s_provider); - - if(t->s_svcname != NULL) - si->si_service = strdup(t->s_svcname); -} - - -/** - * - */ -static int -dvb_grace_period(service_t *t) -{ -#if TODO_FIX_THIS - if (t->s_dvb_mux_instance && t->s_dvb_mux_instance->tdmi_adapter) - return t->s_dvb_mux_instance->tdmi_adapter->tda_grace_period ?: 10; -#endif - return 10; -} - - - -/* - * Find transport based on the DVB identification - */ -service_t * -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 (dm != NULL) { - LIST_FOREACH(svc, &dm->dm_services, s_group_link) { - if (sid != svc->s_dvb_service_id) continue; - if (enabled && !svc->s_enabled) continue; - if (epgprimary && !service_is_primary_epg(svc)) continue; - return svc; - } - } 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 { - 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; -} - - -/** - * Find a transport based on 'serviceid' on the given mux - * - * If it cannot be found we create it if 'pmt_pid' is also set - */ -service_t * -dvb_service_find(dvb_mux_t *dm, uint16_t sid, int pmt_pid, const char *uuid) -{ - return dvb_service_find2(dm, sid, pmt_pid, uuid, NULL); -} - - -/** - * - */ -service_t * -dvb_service_find2(dvb_mux_t *dm, uint16_t sid, int pmt_pid, - const char *uuid, int *save) -{ - service_t *t; - - lock_assert(&global_lock); - - LIST_FOREACH(t, &dm->dm_services, s_group_link) { - if(t->s_dvb_service_id == sid) - break; - } - - /* Existing - updated PMT_PID if required */ - if (t) { - if (pmt_pid && pmt_pid != t->s_pmt_pid) { - t->s_pmt_pid = pmt_pid; - *save = 1; - } - return t; - } - - if(pmt_pid == 0) - return NULL; - - tvhlog(LOG_DEBUG, "dvb", "Add service \"0x%x\" on \"%s\"", sid, - dvb_mux_nicename(dm)); - - t = service_create(uuid, S_MPEG_TS, &dvb_service_class); - - if (save) *save = 1; - - t->s_dvb_service_id = sid; - t->s_pmt_pid = pmt_pid; - - t->s_start_feed = dvb_service_start; - t->s_refresh_feed = dvb_service_refresh; - t->s_stop_feed = dvb_service_stop; - t->s_config_save = dvb_service_save; - t->s_setsourceinfo = dvb_service_setsourceinfo; - t->s_grace_period = dvb_grace_period; - t->s_is_enabled = dvb_service_is_enabled; - t->s_enlist = dvb_service_enlist; - - 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); - return t; -} - - -/** - * - */ -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; - } -} - - -/** - * - */ -void -dvb_service_notify_by_adapter(th_dvb_adapter_t *tda) -{ - htsmsg_t *m = htsmsg_create_map(); - htsmsg_add_str(m, "adapterId", tda->tda_identifier); - notify_by_msg("dvbService", m); -} - diff --git a/src/input/mpegts/linuxdvb/dvb_tables.c b/src/input/mpegts/linuxdvb/dvb_tables.c deleted file mode 100644 index 938d10a6..00000000 --- a/src/input/mpegts/linuxdvb/dvb_tables.c +++ /dev/null @@ -1,1255 +0,0 @@ -/* - * DVB Table support - * Copyright (C) 2007 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 -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "tvheadend.h" -#include "dvb.h" -#include "dvb_support.h" -#include "epg.h" -#include "channels.h" -#include "psi.h" -#include "notify.h" -#include "cwc.h" -#include "tvhtime.h" - -/** - * - */ -static void -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; - - 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; - - dvb_mux_save(dm); - - tvhlog(LOG_DEBUG, "dvb", "\"%s\" initial scan completed for \"%s\"", - tda->tda_rootpath, dvb_mux_nicename(dm)); - dvb_mux_initial_scan_done(dm); -} - - -/** - * - */ -void -dvb_table_dispatch(uint8_t *sec, int r, th_dvb_table_t *tdt) -{ - if(tdt->tdt_destroyed) - return; - - int chkcrc = tdt->tdt_flags & TDT_CRC; - int tableid, len; - 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 */ - if(chkcrc && tvh_crc32(sec, r, 0xffffffff)) - return; - - r -= 3; - tableid = sec[0]; - len = ((sec[1] & 0x0f) << 8) | sec[2]; - - if(len < r) - return; - - if((tableid & tdt->tdt_mask) != tdt->tdt_table) - return; - - ptr = &sec[3]; - if(chkcrc) len -= 4; /* Strip trailing CRC */ - - if(tdt->tdt_flags & TDT_CA) - 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(dm, ptr, len, tableid, tdt); - else - ret = tdt->tdt_callback(dm, ptr, len, tableid, tdt->tdt_opaque); - - if(ret == 0) - tdt->tdt_count++; - - if(tdt->tdt_flags & TDT_QUICKREQ) - dvb_table_fastswitch(tdmi); -} - - -/** - * - */ -void -dvb_table_release(th_dvb_table_t *tdt) -{ - if(--tdt->tdt_refcount == 0) - free(tdt); -} - - -/** - * - */ -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); - dm->dm_num_tables--; - tda->tda_close_table(dm, tdt); - free(tdt->tdt_name); - tdt->tdt_destroyed = 1; - dvb_table_release(tdt); -} - - -/** - * Add a new DVB table - */ -void -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_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 - // sure how well this will work! I know Andreas has some thoughts on - // this - LIST_FOREACH(t, &dm->dm_tables, tdt_link) { - if(pid == t->tdt_pid && - t->tdt_callback == callback && t->tdt_opaque == opaque) { - return; - } - } - - th_dvb_table_t *tdt = calloc(1, sizeof(th_dvb_table_t)); - tdt->tdt_refcount = 1; - tdt->tdt_name = strdup(name); - tdt->tdt_callback = callback; - tdt->tdt_opaque = opaque; - tdt->tdt_pid = pid; - tdt->tdt_flags = flags; - tdt->tdt_table = tableid; - tdt->tdt_mask = mask; - tdt->tdt_tdmi = tdmi; - LIST_INSERT_HEAD(&dm->dm_tables, tdt, tdt_link); - dm->dm_num_tables++; - tdt->tdt_fd = -1; - - tdmi->tdmi_adapter->tda_open_table(dm, tdt); -} - -/** - * DVB Descriptor; Service - */ -static int -dvb_desc_service(uint8_t *ptr, int len, uint8_t *typep, - char *provider, size_t providerlen, - char *name, size_t namelen) -{ - int r; - - if(len < 2) - return -1; - - *typep = ptr[0]; - - ptr++; - len--; - - if((r = dvb_get_string_with_len(provider, providerlen, ptr, len, NULL, NULL)) < 0) - return -1; - ptr += r; len -= r; - - if((r = dvb_get_string_with_len(name, namelen, ptr, len, NULL, NULL)) < 0) - return -1; - ptr += r; len -= r; - return 0; -} - -/** - * DVB Descriptor: Default authority - */ -static int -dvb_desc_def_authority(uint8_t *ptr, int len, char *defauth, size_t dalen) -{ - int r; - if ((r = dvb_get_string(defauth, dalen, ptr, len, NULL, NULL)) < 0) - return -1; - return 0; -} - -static int -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]; - dvb_network_t *dn = dm->dm_dn; - - if (tableid != 0x4a) return -1; - bdlen = ((buf[5] & 0xf) << 8) | buf[6]; - if (bdlen+7 > len) return -1; - buf += 7; - len -= 7; - - /* Bouquet Desc */ - i = 0; - // TODO: parse top level descriptors? - buf += bdlen; - len -= bdlen; - - tslen = ((buf[0] & 0xf) << 8) | buf[1]; - if (tslen+2 > len) return -1; - buf += 2; - len -= 2; - - /* Transport Loop */ - i = 0; - while (i+6 < tslen) { - tsid = buf[i] << 8 | buf[i+1]; - onid = buf[i+2] << 8 | buf[i+3]; - tdlen = ((buf[i+4] & 0xf) << 8) | buf[i+5]; - if (tdlen+i+6 > tslen) break; - i += 6; - j = 0; - - /* 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 (dm != NULL) { - int save = 0; - *crid = 0; - while (j+2 < tdlen) { - dtag = buf[i+j]; - dlen = buf[i+j+1]; - if (dlen+j+2 > tdlen) break; - j += 2; - switch (dtag) { - case DVB_DESC_DEF_AUTHORITY: - dvb_desc_def_authority(buf+i+j, dlen, crid, sizeof(crid)); - break; - } - j += dlen; - } - 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(dm); - } - - i += tdlen; - } - - return 0; -} - -/** - * DVB SDT (Service Description Table) - */ -static int -dvb_sdt_callback(dvb_mux_t *dm, uint8_t *ptr, int len, - uint8_t tableid, void *opaque) -{ - service_t *t; - uint16_t service_id; - uint16_t tsid, onid; - int free_ca_mode; - int dllen; - uint8_t dtag, dlen; - - char crid[257]; - char provider[256]; - char chname0[256], *chname; - uint8_t stype; -#if ENABLE_TRACE - uint8_t running_status; -#endif - int l; - uint8_t *dlptr, *dptr; - - dvb_network_t *dn = dm->dm_dn; - - if (tableid != 0x42 && tableid != 0x46) return -1; - - if(len < 8) return -1; - - tsid = ptr[0] << 8 | ptr[1]; - onid = ptr[5] << 8 | ptr[6]; - - tvhtrace("sdt", "onid %04X tsid %04X", onid, tsid); - tvhlog_hexdump("sdt", ptr, len); - - /* Find Transport Stream */ - if (tableid == 0x42) { - dvb_mux_set_tsid(dm, tsid, 0); - dvb_mux_set_onid(dm, onid, 0); - if(dm->dm_transport_stream_id != tsid || dm->dm_network_id != onid) - return -1; - } else { - LIST_FOREACH(dm, &dn->dn_muxes, dm_network_link) - if(dm->dm_transport_stream_id == tsid && - dm->dm_network_id != onid) - break; - if (!dm) return 0; - } - - // version = ptr[2] >> 1 & 0x1f; - // section_number = ptr[3]; - // last_section_number = ptr[4]; - // reserved = ptr[7]; - - if((ptr[2] & 1) == 0) { - /* current_next_indicator == next, skip this */ - return -1; - } - - len -= 8; - ptr += 8; - - while(len >= 5) { - int save = 0; - service_id = ptr[0] << 8 | ptr[1]; - // reserved = ptr[2]; -#if ENABLE_TRACE - running_status = (ptr[3] >> 5) & 0x7; -#endif - free_ca_mode = (ptr[3] >> 4) & 0x1; - dllen = ((ptr[3] & 0x0f) << 8) | ptr[4]; - dlptr = ptr + 5; - tvhtrace("sdt", " sid %04X running %d free_ca %d dllen %d", - service_id, running_status, free_ca_mode, dllen); - - ptr += (5 + dllen); - len -= (5 + dllen); - if (len < 0) - break; - - if (!(t = dvb_service_find(dm, service_id, 0, NULL))) - continue; - - stype = 0; - chname = NULL; - *crid = 0; - - while(dllen > 2) { - dtag = dlptr[0]; - dlen = dlptr[1]; - dptr = dlptr + 2; - - dlptr += (2 + dlen); - dllen -= (2 + dlen); - - if(dllen < 0) break; - - switch(dtag) { - case DVB_DESC_SERVICE: - if(dvb_desc_service(dptr, dlen, &stype, - provider, sizeof(provider), - chname0, sizeof(chname0)) == 0) { - tvhtrace("sdt", " stype = %d, provider = %s, name = %s", - stype, provider, chname0); - chname = chname0; - /* Some providers insert spaces. - Clean up that (both heading and trailing) */ - while(*chname <= 32 && *chname != 0) - chname++; - - l = strlen(chname); - while(l > 1 && chname[l - 1] <= 32) { - chname[l - 1] = 0; - l--; - } - - if(l == 0) { - chname = chname0; - snprintf(chname0, sizeof(chname0), "noname-sid-0x%x", service_id); - } - } - break; - case DVB_DESC_DEF_AUTHORITY: - dvb_desc_def_authority(dptr, dlen, crid, sizeof(crid)); - break; - } - } - - if(t->s_servicetype != stype || - t->s_scrambled != free_ca_mode) { - t->s_servicetype = stype; - t->s_scrambled = free_ca_mode; - save = 1; - } - - if (chname && (strcmp(t->s_provider ?: "", provider) || - strcmp(t->s_svcname ?: "", chname))) { - int save2 = 0; - int master = 0; - if (t->s_dvb_mux && t->s_dvb_mux->dm_network_id && - t->s_dvb_mux->dm_network_id == dm->dm_network_id) - master = 1; - - if (!t->s_provider || master) { - free(t->s_provider); - t->s_provider = strdup(provider); - save2 = 1; - } - - if (!t->s_svcname || master) { - free(t->s_svcname); - t->s_svcname = strdup(chname); - save2 = 1; - } - - if (save2) { - pthread_mutex_lock(&t->s_stream_mutex); - service_make_nicename(t); - pthread_mutex_unlock(&t->s_stream_mutex); - save = 1; - } - } - - if (*crid && strcmp(t->s_default_authority ?: "", crid)) { - free(t->s_default_authority); - t->s_default_authority = strdup(crid); - save = 1; - } - - if (save) { - t->s_config_save(t); - service_refresh_channel(t); - } - } - return 0; -} - -/* - * Combined PID 0x11 callback, for stuff commonly found on that PID - */ -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(dm, ptr, len, tableid, opaque); - else if (tableid == 0x4a) - return dvb_bat_callback(dm, ptr, len, tableid, opaque); - return -1; -} - -/** - * PAT - Program Allocation table - */ -static int -dvb_pat_callback(dvb_mux_t *dm, uint8_t *ptr, int len, - uint8_t tableid, void *opaque) -{ - uint16_t service, pmt, tsid; - - if(len < 5) - return -1; - - if((ptr[2] & 1) == 0) { - /* current_next_indicator == next, skip this */ - return -1; - } - - tsid = (ptr[0] << 8) | ptr[1]; - dvb_mux_set_tsid(dm, tsid, 0); - if (dm->dm_transport_stream_id != tsid) - return -1; - - ptr += 5; - len -= 5; - - while(len >= 4) { - service = ptr[0] << 8 | ptr[1]; - pmt = (ptr[2] & 0x1f) << 8 | ptr[3]; - - if(service != 0 && pmt != 0) { - int save = 0; - 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; - len -= 4; - } - return 0; -} - - -/** - * CA - Conditional Access - */ -static int -dvb_ca_callback(dvb_mux_t *dm, uint8_t *ptr, int len, - uint8_t tableid, void *opaque) -{ -#if ENABLE_CWC - cwc_emm(ptr, len, (uintptr_t)opaque, (void *)dm); -#endif - return 0; -} - -/** - * CAT - Conditional Access Table - */ -static int -dvb_cat_callback(dvb_mux_t *dm, uint8_t *ptr, int len, - uint8_t tableid, void *opaque) -{ - int tag, tlen; - uint16_t pid; - uintptr_t caid; - - if((ptr[2] & 1) == 0) { - /* current_next_indicator == next, skip this */ - return -1; - } - - ptr += 5; - len -= 5; - - while(len > 2) { - tag = *ptr++; - tlen = *ptr++; - len -= 2; - switch(tag) { - case DVB_DESC_CA: - caid = ( ptr[0] << 8) | ptr[1]; - pid = ((ptr[2] & 0x1f) << 8) | ptr[3]; - - if(pid == 0) - break; - - tdt_add(dm, 0, 0, dvb_ca_callback, (void *)caid, "CA", - TDT_CA, pid); - break; - - default: - break; - } - - ptr += tlen; - len -= tlen; - } - return 0; -} - - -/** - * Tables for delivery descriptor parsing - */ -static const fe_code_rate_t fec_tab [16] = { - FEC_AUTO, FEC_1_2, FEC_2_3, FEC_3_4, - FEC_5_6, FEC_7_8, FEC_8_9, -#if DVB_API_VERSION >= 5 - FEC_3_5, -#else - FEC_NONE, -#endif - FEC_4_5, -#if DVB_API_VERSION >= 5 - FEC_9_10, -#else - FEC_NONE, -#endif - FEC_NONE, FEC_NONE, - FEC_NONE, FEC_NONE, FEC_NONE, FEC_NONE -}; - - -static const fe_modulation_t qam_tab [6] = { - QAM_AUTO, QAM_16, QAM_32, QAM_64, QAM_128, QAM_256 -}; - -static const fe_bandwidth_t bandwidth_tab [8] = { - BANDWIDTH_8_MHZ, BANDWIDTH_7_MHZ, BANDWIDTH_6_MHZ, BANDWIDTH_AUTO, - BANDWIDTH_AUTO, BANDWIDTH_AUTO, BANDWIDTH_AUTO, BANDWIDTH_AUTO -}; - -static const fe_modulation_t constellation_tab [4] = { - QPSK, QAM_16, QAM_64, QAM_AUTO -}; - -static const fe_code_rate_t code_rate_tab [8] = { - FEC_1_2, FEC_2_3, FEC_3_4, FEC_5_6, FEC_7_8, FEC_AUTO, FEC_AUTO, FEC_AUTO -}; - -static const fe_guard_interval_t guard_interval_tab [4] = { - GUARD_INTERVAL_1_32, GUARD_INTERVAL_1_16, GUARD_INTERVAL_1_8, GUARD_INTERVAL_1_4 -}; - -static const fe_transmit_mode_t transmission_mode_tab [4] = { - TRANSMISSION_MODE_2K, - TRANSMISSION_MODE_8K, -#if DVB_VER_ATLEAST(5,3) - TRANSMISSION_MODE_4K, -#else - TRANSMISSION_MODE_AUTO, /* For older DVB API versions - hope the device can detect */ -#endif - TRANSMISSION_MODE_AUTO -}; - -static const fe_hierarchy_t hierarchy_info_tab [8] = { - HIERARCHY_NONE, HIERARCHY_1, HIERARCHY_2, HIERARCHY_4, - HIERARCHY_NONE, HIERARCHY_1, HIERARCHY_2, HIERARCHY_4 -}; - -/** - * Cable delivery descriptor - */ -static int -dvb_table_cable_delivery(dvb_mux_t *dm, uint8_t *ptr, int len, - uint16_t tsid, uint16_t onid, const char *netname) -{ - struct dvb_mux_conf dmc; - int freq, symrate; - - if(len < 11) - return -1; - - memset(&dmc, 0, sizeof(dmc)); - dmc.dmc_fe_params.inversion = INVERSION_AUTO; - - freq = - bcdtoint(ptr[0]) * 1000000 + bcdtoint(ptr[1]) * 10000 + - bcdtoint(ptr[2]) * 100 + bcdtoint(ptr[3]); - - if(!freq) - return -1; - - dmc.dmc_fe_params.frequency = freq * 100; - tvhtrace("nit", " dvb-c frequency %d", dmc.dmc_fe_params.frequency); - - symrate = - bcdtoint(ptr[7]) * 100000 + bcdtoint(ptr[8]) * 1000 + - bcdtoint(ptr[9]) * 10 + (ptr[10] >> 4); - - dmc.dmc_fe_params.u.qam.symbol_rate = symrate * 100; - - - if((ptr[6] & 0x0f) > 5) - dmc.dmc_fe_params.u.qam.modulation = QAM_AUTO; - else - dmc.dmc_fe_params.u.qam.modulation = qam_tab[ptr[6] & 0x0f]; - - dmc.dmc_fe_params.u.qam.fec_inner = fec_tab[ptr[10] & 0x07]; - - dvb_mux_create(dm->dm_dn, &dmc, onid, tsid, netname, - "automatic mux discovery", 1, 1, NULL, NULL, - dm->dm_dn->dn_autodiscovery, dm); - return 0; -} - -/** - * Satellite delivery descriptor - */ -static int -dvb_table_sat_delivery(dvb_mux_t *dm, uint8_t *ptr, int len, - uint16_t tsid, uint16_t onid, const char *netname) -{ - int freq, symrate; - struct dvb_mux_conf dmc; -#if ENABLE_TRACE - uint16_t orbital_pos; -#endif - - if(len < 11) - return -1; - - memset(&dmc, 0, sizeof(dmc)); - dmc.dmc_fe_params.inversion = INVERSION_AUTO; - - freq = - bcdtoint(ptr[0]) * 1000000 + bcdtoint(ptr[1]) * 10000 + - bcdtoint(ptr[2]) * 100 + bcdtoint(ptr[3]); - dmc.dmc_fe_params.frequency = freq * 10; - tvhtrace("nit", " dvb-s frequency %d", dmc.dmc_fe_params.frequency); - - if(!freq) { - tvhlog(LOG_ERR, "nit", "invalid frequency (%d)", freq); - return -1; - } - -#if ENABLE_TRACE - orbital_pos = bcdtoint(ptr[4]) * 100 + bcdtoint(ptr[5]); -#endif - tvhtrace("nit", " orbital pos %d", orbital_pos); - - symrate = - bcdtoint(ptr[7]) * 100000 + bcdtoint(ptr[8]) * 1000 + - bcdtoint(ptr[9]) * 10 + (ptr[10] >> 4); - dmc.dmc_fe_params.u.qam.symbol_rate = symrate * 100; - - dmc.dmc_fe_params.u.qam.fec_inner = fec_tab[ptr[10] & 0x0f]; - - dmc.dmc_polarisation = (ptr[6] >> 5) & 0x03; - -#if DVB_API_VERSION >= 5 - int modulation = (ptr[6] & 0x03); - - if (modulation == 0x01) - dmc.dmc_fe_modulation = QPSK; - else if (modulation == 0x02) - dmc.dmc_fe_modulation = PSK_8; - else if (modulation == 0x03) - dmc.dmc_fe_modulation = QAM_16; - else - dmc.dmc_fe_modulation = 0; - - if (ptr[6] & 0x04) - dmc.dmc_fe_delsys = SYS_DVBS2; - else - dmc.dmc_fe_delsys = SYS_DVBS; - - switch ((ptr[6] >> 3) & 0x03) { - case 0x00: - dmc.dmc_fe_rolloff = ROLLOFF_35; - break; - case 0x01: - dmc.dmc_fe_rolloff = ROLLOFF_25; - break; - case 0x02: - dmc.dmc_fe_rolloff = ROLLOFF_20; - break; - default: - case 0x03: - dmc.dmc_fe_rolloff = ROLLOFF_AUTO; - break; - } - - if (dmc.dmc_fe_delsys == SYS_DVBS && dmc.dmc_fe_rolloff != ROLLOFF_35) { - tvhlog(LOG_ERR, "nit", "error descriptor"); - return -1; - } - -#endif - -#if TODO_FIX_THIS - dvb_mux_create(dm->dm_dn, &dmc, onid, tsid, netname, - "automatic mux discovery", 1, 1, NULL, dm->dm_conf.dmc_satconf, - dm->dm_dn->dn_autodiscovery, dm); -#endif - - return 0; -} - - -/** - * Terrestrial delivery descriptor - */ -static int -dvb_table_terr_delivery(dvb_mux_t *dm, uint8_t *ptr, int len, - uint16_t tsid, uint16_t onid, const char *netname) -{ - struct dvb_mux_conf dmc; - int freq; - - if(len < 11) - return -1; - - memset(&dmc, 0, sizeof(dmc)); - dmc.dmc_fe_params.inversion = INVERSION_AUTO; - - freq = ((ptr[0] << 24) | (ptr[1] << 16) | (ptr[2] << 8) | ptr[3]) * 10; - - if(!freq) - return -1; - - dmc.dmc_fe_params.frequency = freq; - tvhtrace("nit", " dvb-t frequency %d", dmc.dmc_fe_params.frequency); - dmc.dmc_fe_params.u.ofdm.bandwidth = bandwidth_tab[(ptr[4] & 0xe0) >> 5]; - dmc.dmc_fe_params.u.ofdm.constellation=constellation_tab[(ptr[5] & 0xc0) >> 6]; - dmc.dmc_fe_params.u.ofdm.hierarchy_information=hierarchy_info_tab[(ptr[5] & 0x38) >> 3]; - dmc.dmc_fe_params.u.ofdm.code_rate_HP=code_rate_tab[ptr[5] & 0x3]; - dmc.dmc_fe_params.u.ofdm.code_rate_LP=code_rate_tab[(ptr[6] & 0xe0) >> 5]; - dmc.dmc_fe_params.u.ofdm.guard_interval=guard_interval_tab[(ptr[6] & 0x18) >> 3]; - dmc.dmc_fe_params.u.ofdm.transmission_mode=transmission_mode_tab[(ptr[6] & 0x06) >> 1]; - - dvb_mux_create(dm->dm_dn, &dmc, onid, tsid, netname, - "automatic mux discovery", 1, 1, NULL, NULL, - dm->dm_dn->dn_autodiscovery, dm); - return 0; -} - - -/** - * - */ -static void -dvb_table_local_channel(dvb_mux_t *dm, uint8_t *ptr, int len, - uint16_t tsid, uint16_t onid) -{ - uint16_t sid, chan; - dvb_network_t *dn = dm->dm_dn; - service_t *t; - - LIST_FOREACH(dm, &dn->dn_muxes, dm_network_link) - if(dm->dm_transport_stream_id == tsid && dm->dm_network_id == onid) - break; - - if(dm == NULL) - return; - - while(len >= 4) { - sid = (ptr[0] << 8) | ptr[1]; - chan = ((ptr[2] & 3) << 8) | ptr[3]; - - if(chan != 0) { - t = dvb_service_find(dm, sid, 0, NULL); - if(t != NULL) { - - if(t->s_channel_number != chan) { - t->s_channel_number = chan; - t->s_config_save(t); - service_refresh_channel(t); - } - } - } - ptr += 4; - len -= 4; - } -} - - - -/** - * NIT - Network Information Table - */ -static int -dvb_nit_callback(dvb_mux_t *dm, uint8_t *ptr, int len, - uint8_t tableid, void *opaque) -{ - uint8_t dtag, dlen; - uint16_t llen; - char netname[256]; - uint16_t tsid, onid; - uint16_t network_id = (ptr[0] << 8) | ptr[1]; - netname[0] = '\0'; - - tvhtrace("nit", "tableid 0x%02x", tableid); - tvhlog_hexdump("nit", ptr, len); - - /* Ignore other network */ - if(tableid != 0x40) return -1; - - /* Check NID */ - if(dm->dm_dn->dn_nitoid && - dm->dm_dn->dn_nitoid != network_id) - return -1; - - /* Ignore non-current */ - if((ptr[2] & 1) == 0) - return -1; - - /* Network descriptors */ - llen = ((ptr[5] & 0xf) << 8) | ptr[6]; - ptr += 7; - len -= llen + 7; - if (len < 0) - return -1; - - while(llen > 2) { - dtag = ptr[0]; - dlen = ptr[1]; - - tvhtrace("nit", "dtag %02X dlen %d", dtag, dlen); - - switch(dtag) { - case DVB_DESC_NETWORK_NAME: - if(dvb_get_string(netname, sizeof(netname), ptr+2, dlen, NULL, NULL)) - return -1; - if(strcmp(dm->dm_network_name ?: "", netname)) - dvb_mux_set_networkname(dm, netname); - break; - } - - ptr += dlen + 2; - llen -= dlen + 2; - } - tvhtrace("nit", "network %d/%s", network_id, netname); - if (llen) - return -1; - - /* Transport loop */ - llen = ((ptr[0] & 0xf) << 8) | ptr[1]; - ptr += 2; - len -= 2; - if (llen > len) - return -1; - while(len >= 6) { - tsid = ( ptr[0] << 8) | ptr[1]; - onid = ( ptr[2] << 8) | ptr[3]; - llen = ((ptr[4] & 0xf) << 8) | ptr[5]; - - tvhtrace("nit", " onid %04X tsid %04X", onid, tsid); - - ptr += 6; - len -= llen + 6; - if(len < 0) - return -1; - - while(llen > 2) { - dtag = ptr[0]; - dlen = ptr[1]; - - tvhtrace("nit", " dtag %02X dlen %d", dtag, dlen); - - switch(dtag) { - case DVB_DESC_SAT: - if(dm->dm_dn->dn_fe_type == FE_QPSK) - dvb_table_sat_delivery(dm, ptr+2, dlen, tsid, onid, netname); - break; - case DVB_DESC_CABLE: - if(dm->dm_dn->dn_fe_type == FE_QAM) - dvb_table_cable_delivery(dm, ptr+2, dlen, tsid, onid, netname); - break; - case DVB_DESC_TERR: - if(dm->dm_dn->dn_fe_type == FE_OFDM) - dvb_table_terr_delivery(dm, ptr+2, dlen, tsid, onid, netname); - break; - case DVB_DESC_LOCAL_CHAN: - dvb_table_local_channel(dm, ptr+2, dlen, tsid, onid); - break; - } - - llen -= dlen + 2; - ptr += dlen + 2; - } - if (llen) - return -1; - } - return 0; -} - - -/** - * VCT - ATSC Virtual Channel Table - */ -static int -atsc_vct_callback(dvb_mux_t *dm, uint8_t *ptr, int len, - uint8_t tableid, void *opaque) -{ - dvb_network_t *dn = dm->dm_dn; - service_t *t; - int numch; - char chname[256]; - uint8_t atsc_stype; - uint8_t stype; - uint16_t service_id; - uint16_t tsid, onid; - int dlen, dl; - uint8_t *dptr; - - if(tableid != 0xc8 && tableid != 0xc9) - return -1; // Fail - - ptr += 5; // Skip generic header - len -= 5; - - if(len < 2) - return -1; - - numch = ptr[1]; - ptr += 2; - len -= 2; - - for(; numch > 0 && len >= 32; ptr += 32 + dlen, len -= 32 + dlen, numch--) { - - dl = dlen = ((ptr[30] & 3) << 8) | ptr[31]; - - if(dlen + 32 > len) - return -1; // Corrupt table - - tsid = (ptr[22] << 8) | ptr[23]; - onid = (ptr[24] << 8) | ptr[25]; - - if(tsid != 0) { - /* Search all muxes on adapter */ - LIST_FOREACH(dm, &dn->dn_muxes, dm_network_link) - if(dm->dm_transport_stream_id == tsid && dm->dm_network_id == onid); - break; - } - - if(dm == NULL) - continue; - - service_id = (ptr[24] << 8) | ptr[25]; - if((t = dvb_service_find(dm, service_id, 0, NULL)) == NULL) - continue; - - atsc_stype = ptr[27] & 0x3f; - if(atsc_stype != 0x02) { - /* Not ATSC TV */ - continue; - } - - stype = ST_SDTV; - atsc_utf16_to_utf8(ptr, 7, chname, sizeof(chname)); - - dptr = ptr + 32; - while(dl > 1) { - // int desclen = dptr[1]; - dl -= dptr[1] + 2; - dptr += dptr[1] + 2; - } - - if(t->s_servicetype != stype || - strcmp(t->s_svcname ?: "", chname)) { - - t->s_servicetype = stype; - tvh_str_set(&t->s_svcname, chname); - - t->s_config_save(t); - } - } - return 0; -} - - - - -/** - * PMT - Program Mapping Table - */ -static int -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; - - 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 (dm->dm_dn->dn_disable_pmt_monitor && !active) - dvb_tdt_destroy(dm->dm_current_tdmi->tdmi_adapter, - dm->dm_current_tdmi, tdt); - - return 0; -} - -/* - * Time Offset table handler - */ -static int -dvb_tot_callback(dvb_mux_t *dm, uint8_t *buf, int len, - uint8_t tableid, void *opaque) -{ - uint16_t mjd; - uint8_t hour, min, sec; - int year, mon, day; - struct tm utc; - - if (tableid != 0x73) - return -1; - - /* DVB format MJD, Hour, Min, Sec */ - mjd = (buf[0] << 8) | buf[1]; - hour = bcdtoint(buf[2]); - min = bcdtoint(buf[3]); - sec = bcdtoint(buf[4]); - - /* Convert MJD (using algo from EN 300 468 v1.13.1 Annex C) */ - year = (int)((mjd - 15078.2) / 365.25); - mon = (int)((mjd - 14956.1 - (int)(year * 365.25)) / 30.6001); - day = mjd - 14956 - (int)(year * 365.25) - (int)(mon * 30.6001); - if (mon == 14 || mon == 15) { - year++; - mon -= 12; - } - mon--; - - /* Convert to UTC time_t */ - utc.tm_wday = 0; - utc.tm_yday = 0; - utc.tm_isdst = 0; - utc.tm_year = year; - utc.tm_mon = mon - 1; - utc.tm_mday = day; - utc.tm_hour = hour; - utc.tm_min = min; - utc.tm_sec = sec; - tvhtime_update(&utc); - - return 0; -} - -/** - * Demux for default DVB tables that we want - */ -static void -dvb_table_add_default_dvb(dvb_mux_t *dm) -{ - /* Network Information Table */ - - tdt_add(dm, 0, 0, dvb_nit_callback, NULL, "nit", - TDT_QUICKREQ | TDT_CRC, 0x10); - - /* Service Descriptor Table and Bouqeut Allocation Table */ - - tdt_add(dm, 0, 0, dvb_pidx11_callback, NULL, "pidx11", - TDT_QUICKREQ | TDT_CRC, 0x11); - - /* Time Offset Table */ - - tdt_add(dm, 0, 0, dvb_tot_callback, NULL, "tot", TDT_CRC, 0x14); -} - - -/** - * Demux for default ATSC tables that we want - */ -static void -dvb_table_add_default_atsc(dvb_mux_t *dm) -{ - int tableid; - - if(dm->dm_conf.dmc_fe_params.u.vsb.modulation == VSB_8) { - tableid = 0xc8; // Terrestrial - } else { - tableid = 0xc9; // Cable - } - - tdt_add(dm, tableid, 0xff, atsc_vct_callback, NULL, "vct", - TDT_QUICKREQ | TDT_CRC, 0x1ffb); -} - - - - -/** - * Setup FD + demux for default tables that we want - */ -void -dvb_table_add_default(dvb_mux_t *dm) -{ - /* Program Allocation Table */ - tdt_add(dm, 0x00, 0xff, dvb_pat_callback, NULL, "pat", - TDT_QUICKREQ | TDT_CRC, 0); - - /* Conditional Access Table */ - tdt_add(dm, 0x1, 0xff, dvb_cat_callback, NULL, "cat", - TDT_CRC, 1); - - - switch(dm->dm_dn->dn_fe_type) { - case FE_QPSK: - case FE_OFDM: - case FE_QAM: - dvb_table_add_default_dvb(dm); - break; - - case FE_ATSC: - dvb_table_add_default_atsc(dm); - break; - } -} - - -/** - * Setup FD + demux for a services PMT - */ -void -dvb_table_add_pmt(dvb_mux_t *dm, int pmt_pid) -{ - char pmtname[100]; - - snprintf(pmtname, sizeof(pmtname), "PMT(%d)", pmt_pid); - tdt_add(dm, 0x2, 0xff, dvb_pmt_callback, NULL, pmtname, - TDT_CRC | TDT_QUICKREQ | TDT_TDT, pmt_pid); -} - -void -dvb_table_rem_pmt(dvb_mux_t *dm, int pmt_pid) -{ - 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) - if (tdt->tdt_pid == pmt_pid && tdt->tdt_callback == dvb_pmt_callback) - break; - if (tdt) - dvb_tdt_destroy(tda, tdmi, tdt); -} - - -/** - * - */ -void -dvb_table_flush_all(dvb_mux_t *dm) -{ - 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, tdmi, tdt); -}