Merge remote-tracking branch 'origin/pr/365'

This commit is contained in:
Adam Sutton 2014-04-04 15:02:21 +01:00
commit 7e89bbe3f4
47 changed files with 2700 additions and 2366 deletions

View file

@ -178,6 +178,12 @@ SRCS-$(CONFIG_MPEGTS) += \
src/input/mpegts/dvb_psi.c \
src/input/mpegts/tsdemux.c \
# MPEGTS DVB
SRCS-${CONFIG_MPEGTS_DVB} += \
src/input/mpegts/mpegts_network_dvb.c \
src/input/mpegts/mpegts_mux_dvb.c \
src/input/mpegts/scanfile.c
# MPEGTS EPG
SRCS-$(CONFIG_MPEGTS) += \
src/epggrab/otamux.c\
@ -185,20 +191,16 @@ SRCS-$(CONFIG_MPEGTS) += \
src/epggrab/support/freesat_huffman.c \
src/epggrab/module/opentv.c \
# DVB
# LINUX DVB
SRCS-${CONFIG_LINUXDVB} += \
src/input/mpegts/linuxdvb/linuxdvb.c \
src/input/mpegts/linuxdvb/linuxdvb_adapter.c \
src/input/mpegts/linuxdvb/linuxdvb_frontend.c \
src/input/mpegts/linuxdvb/linuxdvb_network.c \
src/input/mpegts/linuxdvb/linuxdvb_mux.c \
src/input/mpegts/linuxdvb/linuxdvb_service.c \
src/input/mpegts/linuxdvb/linuxdvb_satconf.c \
src/input/mpegts/linuxdvb/linuxdvb_lnb.c \
src/input/mpegts/linuxdvb/linuxdvb_switch.c \
src/input/mpegts/linuxdvb/linuxdvb_rotor.c \
src/input/mpegts/linuxdvb/linuxdvb_en50494.c \
src/input/mpegts/linuxdvb/scanfile.c \
src/input/mpegts/linuxdvb/linuxdvb_en50494.c
# IPTV
SRCS-${CONFIG_IPTV} += \

6
configure vendored
View file

@ -36,6 +36,7 @@ OPTIONS=(
"bundle:no"
"dvbcsa:no"
"kqueue:no"
"mpegts_dvb:auto"
)
#
@ -138,10 +139,11 @@ fi
#
# DVB API
#
check_cc_header 'linux/dvb/version' dvbapi
check_cc_header 'linux/dvb/version' linuxdvbapi
if enabled_or_auto linuxdvb; then
if enabled dvbapi; then
if enabled linuxdvbapi; then
enable linuxdvb
enable mpegts_dvb
elif enabled linuxdvb; then
die "Linux DVB API not found (use --disable-linuxdvb)"
fi

View file

@ -21,11 +21,9 @@
#include "access.h"
#include "htsmsg.h"
#include "api.h"
#include "input/mpegts.h"
#if ENABLE_LINUXDVB
#include "input/mpegts/linuxdvb.h"
#include "input/mpegts/linuxdvb/linuxdvb_private.h"
#include "input/mpegts/linuxdvb/scanfile.h"
#include "input.h"
#if ENABLE_MPEGTS_DVB
#include "input/mpegts/scanfile.h"
#endif
/*
@ -253,9 +251,9 @@ api_mpegts_service_grid
}
}
#if ENABLE_LINUXDVB
#if ENABLE_MPEGTS_DVB
static int
api_linuxdvb_scanfile_list
api_dvb_scanfile_list
( void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp )
{
char buf[512];
@ -323,8 +321,8 @@ api_mpegts_init ( void )
{ "mpegts/mux/class", ACCESS_ANONYMOUS, api_idnode_class, (void*)&mpegts_mux_class },
{ "mpegts/service/grid", ACCESS_ANONYMOUS, api_idnode_grid, api_mpegts_service_grid },
{ "mpegts/service/class", ACCESS_ANONYMOUS, api_idnode_class, (void*)&mpegts_service_class },
#if ENABLE_LINUXDVB
{ "linuxdvb/scanfile/list", ACCESS_ANONYMOUS, api_linuxdvb_scanfile_list, NULL },
#if ENABLE_MPEGTS_DVB
{ "dvb/scanfile/list", ACCESS_ANONYMOUS, api_dvb_scanfile_list, NULL },
#endif
{ NULL },
};

View file

@ -37,7 +37,7 @@
#include <fcntl.h>
#include "tvheadend.h"
#include "input/mpegts.h"
#include "input.h"
#include "tcp.h"
#include "capmt.h"
#include "notify.h"

View file

@ -40,7 +40,7 @@
#include "dtable.h"
#include "subscriptions.h"
#include "service.h"
#include "input/mpegts.h"
#include "input.h"
#include "input/mpegts/tsdemux.h"
#include "tvhcsa.h"

View file

@ -17,7 +17,7 @@
*/
#include "tvhcsa.h"
#include "input/mpegts.h"
#include "input.h"
#include "input/mpegts/tsdemux.h"
#include <stdlib.h>

View file

@ -24,8 +24,7 @@
#include "epg.h"
#include "epggrab.h"
#include "epggrab/private.h"
#include "input/mpegts.h"
#include "input/mpegts/dvb.h"
#include "input.h"
#include "input/mpegts/dvb_charset.h"
/* ************************************************************************

View file

@ -32,7 +32,7 @@
#include "service.h"
#include "htsmsg.h"
#include "settings.h"
#include "input/mpegts.h"
#include "input.h"
static epggrab_channel_tree_t _opentv_channels;

View file

@ -22,7 +22,7 @@
#include "epg.h"
#include "epggrab.h"
#include "epggrab/private.h"
#include "input/mpegts.h"
#include "input.h"
#include "subscriptions.h"
#include <string.h>

View file

@ -609,6 +609,17 @@ idnode_set_add
is->is_array[is->is_count++] = in;
}
int
idnode_set_exists
( idnode_set_t *is, idnode_t * in )
{
int i;
for (i = 0; i < is->is_count; i++)
if (memcmp(is->is_array[i]->in_uuid, in->in_uuid, sizeof(in->in_uuid)) == 0)
return 1;
return 0;
}
void
idnode_set_sort
( idnode_set_t *is, idnode_sort_t *sort )
@ -623,6 +634,17 @@ idnode_set_sort_by_title
qsort(is->is_array, is->is_count, sizeof(idnode_t*), idnode_cmp_title);
}
htsmsg_t *
idnode_set_as_htsmsg
( idnode_set_t *is )
{
htsmsg_t *l = htsmsg_create_list();
int i;
for (i = 0; i < is->is_count; i++)
htsmsg_add_str(l, NULL, idnode_uuid_as_str(is->is_array[i]));
return l;
}
void
idnode_set_free ( idnode_set_t *is )
{

View file

@ -158,8 +158,10 @@ int idnode_filter
#define idnode_set_create() calloc(1, sizeof(idnode_set_t))
void idnode_set_add
( idnode_set_t *is, idnode_t *in, idnode_filter_t *filt );
int idnode_set_exists ( idnode_set_t *is, idnode_t *in );
void idnode_set_sort ( idnode_set_t *is, idnode_sort_t *s );
void idnode_set_sort_by_title ( idnode_set_t *is );
htsmsg_t *idnode_set_as_htsmsg ( idnode_set_t *is );
void idnode_set_free ( idnode_set_t *is );
#endif /* __TVH_IDNODE_H__ */

View file

@ -113,6 +113,9 @@ void tvh_input_stream_destroy ( tvh_input_stream_t *st );
#if ENABLE_MPEGTS
#include "input/mpegts.h"
#if ENABLE_MPEGTS_DVB
#include "input/mpegts/mpegts_dvb.h"
#endif
#if ENABLE_TSFILE
#include "input/mpegts/tsfile.h"
#endif

View file

@ -20,6 +20,10 @@
#ifndef __TVH_MPEGTS_H__
#define __TVH_MPEGTS_H__
#ifndef __TVH_INPUT_H__
#error "Use header file input.h not input/mpegts.h"
#endif
#include "input.h"
#include "service.h"
#include "mpegts/dvb.h"
@ -468,7 +472,7 @@ struct mpegts_input
void (*mi_display_name) (mpegts_input_t*, char *buf, size_t len);
int (*mi_is_free) (mpegts_input_t*);
int (*mi_get_weight) (mpegts_input_t*);
int (*mi_get_priority) (mpegts_input_t*);
int (*mi_get_priority) (mpegts_input_t*, mpegts_mux_t *mm);
int (*mi_get_grace) (mpegts_input_t*, mpegts_mux_t *mm);
int (*mi_start_mux) (mpegts_input_t*,mpegts_mux_instance_t*);
void (*mi_stop_mux) (mpegts_input_t*,mpegts_mux_instance_t*);
@ -644,7 +648,7 @@ void mpegts_input_table_thread_stop( mpegts_input_t *mi );
int mpegts_input_is_free ( mpegts_input_t *mi );
int mpegts_input_get_weight ( mpegts_input_t *mi );
int mpegts_input_get_priority ( mpegts_input_t *mi );
int mpegts_input_get_priority ( mpegts_input_t *mi, mpegts_mux_t *mm );
int mpegts_input_get_grace ( mpegts_input_t *mi, mpegts_mux_t *mm );
void mpegts_input_save ( mpegts_input_t *mi, htsmsg_t *c );
@ -689,8 +693,6 @@ mpegts_service_t *mpegts_service_create0
mpegts_service_t *mpegts_service_find
( mpegts_mux_t *mm, uint16_t sid, uint16_t pmt_pid, int create, int *save );
void mpegts_service_save ( mpegts_service_t *s, htsmsg_t *c );
void mpegts_service_delete ( service_t *s, int delconf );
/*
@ -729,3 +731,4 @@ LIST_HEAD(,mpegts_listener) mpegts_listeners;
*
* vim:sts=2:ts=2:sw=2:et
*****************************************************************************/

View file

@ -190,55 +190,228 @@ void psi_tables_atsc_t ( struct mpegts_mux *mm );
void psi_tables_atsc_c ( struct mpegts_mux *mm );
/*
* Delivery systems and DVB API wrappers
*
* Note: although these are really only useful for linuxDVB, they are
* used in mpegts so that tsfile can be used to debug issues
*/
#if ENABLE_DVBAPI
#if ENABLE_MPEGTS_DVB
#include <linux/dvb/version.h>
#include <linux/dvb/frontend.h>
typedef enum dvb_fe_type {
DVB_TYPE_NONE = 0,
DVB_TYPE_T = 1, /* terrestrial */
DVB_TYPE_C, /* cable */
DVB_TYPE_S, /* satellite */
DVB_TYPE_ATSC, /* terrestrial - north america */
DVB_TYPE_LAST = DVB_TYPE_ATSC
} dvb_fe_type_t;
#define DVB_VER_INT(maj,min) (((maj) << 16) + (min))
typedef enum dvb_fe_delivery_system {
DVB_SYS_NONE = 0,
DVB_SYS_DVBC_ANNEX_A = 100,
DVB_SYS_DVBC_ANNEX_B,
DVB_SYS_DVBC_ANNEX_C,
DVB_SYS_DVBT = 200,
DVB_SYS_DVBT2,
DVB_SYS_DVBS = 300,
DVB_SYS_DVBS2,
DVB_SYS_DVBH = 400,
DVB_SYS_DSS = 500,
DVB_SYS_ISDBT = 600,
DVB_SYS_ISDBS,
DVB_SYS_ISDBC,
DVB_SYS_ATSC = 700,
DVB_SYS_ATSCMH,
DVB_SYS_DTMB = 800,
DVB_SYS_CMMB = 900,
DVB_SYS_DAB = 1000,
DVB_SYS_TURBO = 1100,
} dvb_fe_delivery_system_t;
#define DVB_VER_ATLEAST(maj, min) \
(DVB_VER_INT(DVB_API_VERSION, DVB_API_VERSION_MINOR) >= DVB_VER_INT(maj, min))
typedef enum dvb_fe_spectral_inversion {
DVB_INVERSION_UNDEFINED,
DVB_INVERSION_AUTO,
DVB_INVERSION_OFF,
DVB_INVERSION_ON,
} dvb_fe_spectral_inversion_t;
typedef struct dvb_frontend_parameters dvb_frontend_parameters_t;
typedef enum dvb_fe_code_rate {
DVB_FEC_NONE = 0,
DVB_FEC_AUTO,
DVB_FEC_1_2 = 102,
DVB_FEC_1_3 = 103,
DVB_FEC_1_5 = 105,
DVB_FEC_2_3 = 203,
DVB_FEC_2_5 = 205,
DVB_FEC_2_9 = 209,
DVB_FEC_3_4 = 304,
DVB_FEC_3_5 = 305,
DVB_FEC_4_5 = 405,
DVB_FEC_4_15 = 415,
DVB_FEC_5_6 = 506,
DVB_FEC_5_9 = 509,
DVB_FEC_6_7 = 607,
DVB_FEC_7_8 = 708,
DVB_FEC_7_9 = 709,
DVB_FEC_7_15 = 715,
DVB_FEC_8_9 = 809,
DVB_FEC_8_15 = 815,
DVB_FEC_9_10 = 910,
DVB_FEC_9_20 = 920,
DVB_FEC_11_15 = 1115,
DVB_FEC_11_20 = 1120,
DVB_FEC_11_45 = 1145,
DVB_FEC_13_18 = 1318,
DVB_FEC_13_45 = 1345,
DVB_FEC_14_45 = 1445,
DVB_FEC_23_36 = 2336,
DVB_FEC_25_36 = 2536,
DVB_FEC_26_45 = 2645,
DVB_FEC_28_45 = 2845,
DVB_FEC_29_45 = 2945,
DVB_FEC_31_45 = 3145,
DVB_FEC_32_45 = 3245,
DVB_FEC_77_90 = 7790,
} dvb_fe_code_rate_t;
typedef enum polarisation {
POLARISATION_HORIZONTAL = 0x00,
POLARISATION_VERTICAL = 0x01,
POLARISATION_CIRCULAR_LEFT = 0x02,
POLARISATION_CIRCULAR_RIGHT = 0x03
} polarisation_t;
typedef enum dvb_fe_modulation {
DVB_MOD_NONE = 0,
DVB_MOD_AUTO,
DVB_MOD_QPSK = 1001,
DVB_MOD_QAM_4_NR = 2004,
DVB_MOD_QAM_AUTO = 3000,
DVB_MOD_QAM_16 = 3016,
DVB_MOD_QAM_32 = 3032,
DVB_MOD_QAM_64 = 3064,
DVB_MOD_QAM_128 = 3128,
DVB_MOD_QAM_256 = 3256,
DVB_MOD_VSB_8 = 4008,
DVB_MOD_VSB_16 = 4016,
DVB_MOD_PSK_8 = 5008,
DVB_MOD_DQPSK = 6001,
DVB_MOD_BPSK = 7001,
DVB_MOD_BPSK_S = 8001,
DVB_MOD_APSK_16 = 9016,
DVB_MOD_APSK_32 = 9032,
DVB_MOD_APSK_64 = 9064,
DVB_MOD_APSK_128 = 9128,
DVB_MOD_APSK_256 = 9256,
DVB_MOD_APSK_8_L = 10008,
DVB_MOD_APSK_16_L = 10016,
DVB_MOD_APSK_32_L = 10032,
DVB_MOD_APSK_64_L = 10064,
DVB_MOD_APSK_128_L = 10128,
DVB_MOD_APSK_256_L = 10256,
} dvb_fe_modulation_t;
typedef enum dvb_fe_transmit_mode {
DVB_TRANSMISSION_MODE_NONE = 0,
DVB_TRANSMISSION_MODE_AUTO,
DVB_TRANSMISSION_MODE_1K = 100,
DVB_TRANSMISSION_MODE_2K,
DVB_TRANSMISSION_MODE_4K,
DVB_TRANSMISSION_MODE_8K,
DVB_TRANSMISSION_MODE_16K,
DVB_TRANSMISSION_MODE_32K,
DVB_TRANSMISSION_MODE_C1 = 10001,
DVB_TRANSMISSION_MODE_C3780 = 13780,
} dvb_fe_transmit_mode_t;
typedef enum dvb_fe_bandwidth {
DVB_BANDWIDTH_NONE = 0,
DVB_BANDWIDTH_AUTO,
DVB_BANDWIDTH_1_712_MHZ = 1712,
DVB_BANDWIDTH_5_MHZ = 5000,
DVB_BANDWIDTH_6_MHZ = 6000,
DVB_BANDWIDTH_7_MHZ = 7000,
DVB_BANDWIDTH_8_MHZ = 8000,
DVB_BANDWIDTH_10_MHZ = 10000,
} dvb_fe_bandwidth_t;
typedef enum dvb_fe_guard_interval {
DVB_GUARD_INTERVAL_NONE = 0,
DVB_GUARD_INTERVAL_AUTO,
DVB_GUARD_INTERVAL_1_4 = 1004,
DVB_GUARD_INTERVAL_1_8 = 1008,
DVB_GUARD_INTERVAL_1_16 = 1016,
DVB_GUARD_INTERVAL_1_32 = 1032,
DVB_GUARD_INTERVAL_1_128 = 1128,
DVB_GUARD_INTERVAL_19_128 = 19128,
DVB_GUARD_INTERVAL_19_256 = 19256,
DVB_GUARD_INTERVAL_PN420 = 90420,
DVB_GUARD_INTERVAL_PN595 = 90595,
DVB_GUARD_INTERVAL_PN945 = 90945,
} dvb_fe_guard_interval_t;
typedef enum dvb_fe_hierarchy {
DVB_HIERARCHY_NONE = 0,
DVB_HIERARCHY_AUTO,
DVB_HIERARCHY_1 = 1001,
DVB_HIERARCHY_2 = 1002,
DVB_HIERARCHY_4 = 1004,
} dvb_fe_hierarchy_t;
typedef enum dvb_fe_pilot {
DVB_PILOT_NONE = 0,
DVB_PILOT_AUTO,
DVB_PILOT_ON,
DVB_PILOT_OFF,
} dvb_fe_pilot_t;
typedef enum dvb_fe_rolloff {
DVB_ROLLOFF_NONE = 0,
DVB_ROLLOFF_AUTO,
DVB_ROLLOFF_20 = 200,
DVB_ROLLOFF_25 = 250,
DVB_ROLLOFF_35 = 350,
} dvb_fe_rolloff_t;
typedef enum dvb_polarisation {
DVB_POLARISATION_HORIZONTAL = 0x00,
DVB_POLARISATION_VERTICAL = 0x01,
DVB_POLARISATION_CIRCULAR_LEFT = 0x02,
DVB_POLARISATION_CIRCULAR_RIGHT = 0x03
} dvb_polarisation_t;
typedef struct dvb_qpsk_config {
dvb_polarisation_t polarisation;
int orbital_pos;
char orbital_dir;
uint32_t symbol_rate;
dvb_fe_code_rate_t fec_inner;
} dvb_qpsk_config_t;
typedef struct dvb_qam_config {
uint32_t symbol_rate;
dvb_fe_code_rate_t fec_inner;
} dvb_qam_config_t;
typedef struct dvb_ofdm_config {
dvb_fe_bandwidth_t bandwidth;
dvb_fe_code_rate_t code_rate_HP;
dvb_fe_code_rate_t code_rate_LP;
dvb_fe_transmit_mode_t transmission_mode;
dvb_fe_guard_interval_t guard_interval;
dvb_fe_hierarchy_t hierarchy_information;
} dvb_ofdm_config_t;
typedef struct dvb_mux_conf
{
dvb_frontend_parameters_t dmc_fe_params;
// Additional DVB-S fields
polarisation_t dmc_fe_polarisation;
int dmc_fe_orbital_pos;
char dmc_fe_orbital_dir;
#if DVB_VER_ATLEAST(5,0)
fe_modulation_t dmc_fe_modulation;
fe_delivery_system_t dmc_fe_delsys;
fe_rolloff_t dmc_fe_rolloff;
fe_pilot_t dmc_fe_pilot;
#endif
dvb_fe_type_t dmc_fe_type;
dvb_fe_delivery_system_t dmc_fe_delsys;
dvb_fe_modulation_t dmc_fe_modulation;
uint32_t dmc_fe_freq;
dvb_fe_spectral_inversion_t dmc_fe_inversion;
dvb_fe_rolloff_t dmc_fe_rolloff;
dvb_fe_pilot_t dmc_fe_pilot;
union {
dvb_qpsk_config_t dmc_fe_qpsk;
dvb_qam_config_t dmc_fe_qam;
dvb_ofdm_config_t dmc_fe_ofdm;
} u;
// For scan file configurations
LIST_ENTRY(dvb_mux_conf) dmc_link;
LIST_ENTRY(dvb_mux_conf) dmc_link;
} dvb_mux_conf_t;
const char *dvb_mux_conf_load
( fe_type_t type, dvb_mux_conf_t *dmc, htsmsg_t *m );
void dvb_mux_conf_save
( fe_type_t type, dvb_mux_conf_t *dmc, htsmsg_t *m );
/* conversion routines */
const char *dvb_rolloff2str ( int rolloff );
const char *dvb_delsys2str ( int delsys );
@ -268,13 +441,14 @@ int dvb_str2pilot ( const char *str );
#define dvb_str2feclo dvb_str2fec
#define dvb_str2fechi dvb_str2fec
int dvb_bandwidth ( enum fe_bandwidth bw );
static inline int dvb_bandwidth( dvb_fe_bandwidth_t bw )
{
return bw < 1000 ? 0 : bw * 1000;
}
#if DVB_VER_ATLEAST(5,10)
int dvb_delsys2type ( enum fe_delivery_system ds );
#endif
int dvb_delsys2type ( enum dvb_fe_delivery_system ds );
#endif /* ENABLE_DVBAPI */
#endif /* ENABLE_MPEGTS_DVB */
void dvb_done ( void );

View file

@ -20,7 +20,7 @@
#include "tvheadend.h"
#include "settings.h"
#include "dvb_charset.h"
#include "../mpegts.h"
#include "input.h"
static LIST_HEAD(,dvb_charset) dvb_charset_list;

View file

@ -17,7 +17,7 @@
*/
#include "tvheadend.h"
#include "input/mpegts.h"
#include "input.h"
#include "dvb.h"
#include "tsdemux.h"
#include "parsers.h"
@ -73,27 +73,16 @@ dvb_servicetype_lookup ( int t )
* Descriptors
* *************************************************************************/
#if ENABLE_DVBAPI
#if ENABLE_MPEGTS_DVB
/**
* 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_VER_ATLEAST(5,0)
FEC_3_5,
#else
FEC_NONE,
#endif
FEC_4_5,
#if DVB_VER_ATLEAST(5,0)
FEC_9_10,
#else
FEC_NONE,
#endif
FEC_NONE, FEC_NONE,
FEC_NONE, FEC_NONE, FEC_NONE, FEC_NONE
static const dvb_fe_code_rate_t fec_tab [16] = {
DVB_FEC_AUTO, DVB_FEC_1_2, DVB_FEC_2_3, DVB_FEC_3_4,
DVB_FEC_5_6, DVB_FEC_7_8, DVB_FEC_8_9, DVB_FEC_3_5,
DVB_FEC_4_5, DVB_FEC_9_10, DVB_FEC_NONE, DVB_FEC_NONE,
DVB_FEC_NONE, DVB_FEC_NONE, DVB_FEC_NONE, DVB_FEC_NONE
};
/*
@ -127,58 +116,43 @@ dvb_desc_sat_del
}
memset(&dmc, 0, sizeof(dmc));
#if DVB_VER_ATLEAST(5,0)
dmc.dmc_fe_pilot = PILOT_AUTO;
#endif
dmc.dmc_fe_params.inversion = INVERSION_AUTO;
dmc.dmc_fe_params.frequency = frequency;
dmc.dmc_fe_orbital_pos = bcdtoint(ptr[4]) * 100 + bcdtoint(ptr[5]);
dmc.dmc_fe_orbital_dir = (ptr[6] & 0x80) ? 'E' : 'W';
dmc.dmc_fe_polarisation = (ptr[6] >> 5) & 0x03;
dmc.dmc_fe_pilot = DVB_PILOT_AUTO;
dmc.dmc_fe_inversion = DVB_INVERSION_AUTO;
dmc.dmc_fe_freq = frequency;
dmc.u.dmc_fe_qpsk.orbital_pos = bcdtoint(ptr[4]) * 100 + bcdtoint(ptr[5]);
dmc.u.dmc_fe_qpsk.orbital_dir = (ptr[6] & 0x80) ? 'E' : 'W';
dmc.u.dmc_fe_qpsk.polarisation = (ptr[6] >> 5) & 0x03;
dmc.dmc_fe_params.u.qpsk.symbol_rate = symrate * 100;
dmc.dmc_fe_params.u.qpsk.fec_inner = fec_tab[ptr[10] & 0x0f];
dmc.u.dmc_fe_qpsk.symbol_rate = symrate * 100;
dmc.u.dmc_fe_qpsk.fec_inner = fec_tab[ptr[10] & 0x0f];
#if DVB_VER_ATLEAST(5,0)
static int mtab[4] = {
0, QPSK,
#if DVB_VER_ATLEAST(5,3)
PSK_8,
#else
0,
#endif
QAM_16
DVB_MOD_NONE, DVB_MOD_QPSK, DVB_MOD_PSK_8, DVB_MOD_QAM_16
};
static int rtab[4] = {
ROLLOFF_35, ROLLOFF_25, ROLLOFF_20, ROLLOFF_AUTO
DVB_ROLLOFF_35, DVB_ROLLOFF_25, DVB_ROLLOFF_20, DVB_ROLLOFF_AUTO
};
dmc.dmc_fe_delsys = (ptr[6] & 0x4) ? SYS_DVBS2 : SYS_DVBS;
dmc.dmc_fe_delsys = (ptr[6] & 0x4) ? DVB_SYS_DVBS2 : DVB_SYS_DVBS;
dmc.dmc_fe_modulation = mtab[ptr[6] & 0x3];
dmc.dmc_fe_rolloff = rtab[(ptr[6] >> 3) & 0x3];
if (dmc.dmc_fe_delsys == SYS_DVBS &&
dmc.dmc_fe_rolloff != ROLLOFF_35) {
if (dmc.dmc_fe_delsys == DVB_SYS_DVBS &&
dmc.dmc_fe_rolloff != DVB_ROLLOFF_35) {
tvhwarn("nit", "dvb-s rolloff error");
return NULL;
}
#endif
/* Debug */
const char *pol = dvb_pol2str(dmc.dmc_fe_polarisation);
tvhdebug("nit", " dvb-s%c pos %d%c freq %d %c sym %d fec %s"
#if DVB_VER_ATLEAST(5,0)
" mod %s roff %s"
#endif
,
const char *pol = dvb_pol2str(dmc.u.dmc_fe_qpsk.polarisation);
tvhdebug("nit",
" dvb-s%c pos %d%c freq %d %c sym %d fec %s mod %s roff %s",
(ptr[6] & 0x4) ? '2' : ' ',
dmc.dmc_fe_orbital_pos, dmc.dmc_fe_orbital_dir,
dmc.dmc_fe_params.frequency,
dmc.u.dmc_fe_qpsk.orbital_pos, dmc.u.dmc_fe_qpsk.orbital_dir,
dmc.dmc_fe_freq,
pol ? pol[0] : 'X',
symrate,
dvb_fec2str(dmc.dmc_fe_params.u.qpsk.fec_inner)
#if DVB_VER_ATLEAST(5,0)
, dvb_qam2str(dmc.dmc_fe_modulation),
dvb_fec2str(dmc.u.dmc_fe_qpsk.fec_inner),
dvb_qam2str(dmc.dmc_fe_modulation),
dvb_rolloff2str(dmc.dmc_fe_rolloff)
#endif
);
/* Create */
@ -197,7 +171,8 @@ dvb_desc_cable_del
dvb_mux_conf_t dmc;
static const fe_modulation_t qtab [6] = {
QAM_AUTO, QAM_16, QAM_32, QAM_64, QAM_128, QAM_256
DVB_MOD_QAM_AUTO, DVB_MOD_QAM_16, DVB_MOD_QAM_32, DVB_MOD_QAM_64,
DVB_MOD_QAM_128, DVB_MOD_QAM_256
};
/* Not enough data */
@ -220,25 +195,23 @@ dvb_desc_cable_del
}
memset(&dmc, 0, sizeof(dmc));
#if DVB_VER_ATLEAST(5,0)
dmc.dmc_fe_delsys = SYS_DVBC_ANNEX_AC;
#endif
dmc.dmc_fe_params.inversion = INVERSION_AUTO;
dmc.dmc_fe_params.frequency = frequency * 100;
dmc.dmc_fe_delsys = DVB_SYS_DVBC_ANNEX_A;
dmc.dmc_fe_inversion = DVB_INVERSION_AUTO;
dmc.dmc_fe_freq = frequency * 100;
dmc.dmc_fe_params.u.qam.symbol_rate = symrate * 100;
dmc.u.dmc_fe_qam.symbol_rate = symrate * 100;
if((ptr[6] & 0x0f) >= sizeof(qtab))
dmc.dmc_fe_params.u.qam.modulation = QAM_AUTO;
dmc.dmc_fe_modulation = QAM_AUTO;
else
dmc.dmc_fe_params.u.qam.modulation = qtab[ptr[6] & 0x0f];
dmc.dmc_fe_params.u.qam.fec_inner = fec_tab[ptr[10] & 0x07];
dmc.dmc_fe_modulation = qtab[ptr[6] & 0x0f];
dmc.u.dmc_fe_qam.fec_inner = fec_tab[ptr[10] & 0x07];
/* Debug */
tvhdebug("nit", " dvb-c freq %d sym %d mod %s fec %s",
frequency,
symrate,
dvb_qam2str(dmc.dmc_fe_params.u.qam.modulation),
dvb_fec2str(dmc.dmc_fe_params.u.qam.fec_inner));
dvb_qam2str(dmc.dmc_fe_modulation),
dvb_fec2str(dmc.u.dmc_fe_qam.fec_inner));
/* Create */
return mm->mm_network->mn_create_mux(mm, onid, tsid, &dmc);
@ -253,28 +226,27 @@ dvb_desc_terr_del
const uint8_t *ptr, int len )
{
static const fe_bandwidth_t btab [8] = {
BANDWIDTH_8_MHZ, BANDWIDTH_7_MHZ, BANDWIDTH_6_MHZ, BANDWIDTH_AUTO,
BANDWIDTH_AUTO, BANDWIDTH_AUTO, BANDWIDTH_AUTO, BANDWIDTH_AUTO
};
DVB_BANDWIDTH_8_MHZ, DVB_BANDWIDTH_7_MHZ,
DVB_BANDWIDTH_6_MHZ, DVB_BANDWIDTH_AUTO,
DVB_BANDWIDTH_AUTO, DVB_BANDWIDTH_AUTO,
DVB_BANDWIDTH_AUTO, DVB_BANDWIDTH_AUTO
};
static const fe_modulation_t ctab [4] = {
QPSK, QAM_16, QAM_64, QAM_AUTO
DVB_MOD_QPSK, DVB_MOD_QAM_16, DVB_MOD_QAM_64, DVB_MOD_QAM_AUTO
};
static const fe_guard_interval_t gtab [4] = {
GUARD_INTERVAL_1_32, GUARD_INTERVAL_1_16, GUARD_INTERVAL_1_8, GUARD_INTERVAL_1_4
DVB_GUARD_INTERVAL_1_32, DVB_GUARD_INTERVAL_1_16,
DVB_GUARD_INTERVAL_1_8, DVB_GUARD_INTERVAL_1_4
};
static const fe_transmit_mode_t ttab [4] = {
TRANSMISSION_MODE_2K,
TRANSMISSION_MODE_8K,
#if DVB_VER_ATLEAST(5,1)
TRANSMISSION_MODE_4K,
#else
TRANSMISSION_MODE_AUTO,
#endif
TRANSMISSION_MODE_AUTO
};
DVB_TRANSMISSION_MODE_2K,
DVB_TRANSMISSION_MODE_8K,
DVB_TRANSMISSION_MODE_4K,
DVB_TRANSMISSION_MODE_AUTO
};
static const fe_hierarchy_t htab [8] = {
HIERARCHY_NONE, HIERARCHY_1, HIERARCHY_2, HIERARCHY_4,
HIERARCHY_NONE, HIERARCHY_1, HIERARCHY_2, HIERARCHY_4
DVB_HIERARCHY_NONE, DVB_HIERARCHY_1, DVB_HIERARCHY_2, DVB_HIERARCHY_4,
DVB_HIERARCHY_NONE, DVB_HIERARCHY_1, DVB_HIERARCHY_2, DVB_HIERARCHY_4
};
int frequency;
@ -291,36 +263,34 @@ dvb_desc_terr_del
}
memset(&dmc, 0, sizeof(dmc));
#if DVB_VER_ATLEAST(5,0)
dmc.dmc_fe_delsys = SYS_DVBT;
#endif
dmc.dmc_fe_params.inversion = INVERSION_AUTO;
dmc.dmc_fe_params.frequency = frequency * 10;
dmc.dmc_fe_delsys = DVB_SYS_DVBT;
dmc.dmc_fe_inversion = DVB_INVERSION_AUTO;
dmc.dmc_fe_freq = frequency * 10;
dmc.dmc_fe_params.u.ofdm.bandwidth = btab[(ptr[4] >> 5) & 0x7];
dmc.dmc_fe_params.u.ofdm.constellation = ctab[(ptr[5] >> 6) & 0x3];
dmc.dmc_fe_params.u.ofdm.hierarchy_information = htab[(ptr[5] >> 3) & 0x3];
dmc.dmc_fe_params.u.ofdm.code_rate_HP = fec_tab[(ptr[5] + 1) & 0x7];
dmc.dmc_fe_params.u.ofdm.code_rate_LP = fec_tab[((ptr[6] + 1) >> 5) & 0x7];
dmc.dmc_fe_params.u.ofdm.guard_interval = gtab[(ptr[6] >> 3) & 0x3];
dmc.dmc_fe_params.u.ofdm.transmission_mode = ttab[(ptr[6] >> 1) & 0x3];
dmc.u.dmc_fe_ofdm.bandwidth = btab[(ptr[4] >> 5) & 0x7];
dmc.dmc_fe_modulation = ctab[(ptr[5] >> 6) & 0x3];
dmc.u.dmc_fe_ofdm.hierarchy_information = htab[(ptr[5] >> 3) & 0x3];
dmc.u.dmc_fe_ofdm.code_rate_HP = fec_tab[(ptr[5] + 1) & 0x7];
dmc.u.dmc_fe_ofdm.code_rate_LP = fec_tab[((ptr[6] + 1) >> 5) & 0x7];
dmc.u.dmc_fe_ofdm.guard_interval = gtab[(ptr[6] >> 3) & 0x3];
dmc.u.dmc_fe_ofdm.transmission_mode = ttab[(ptr[6] >> 1) & 0x3];
/* Debug */
tvhdebug("nit", " dvb-t freq %d bw %s cons %s hier %s code_rate %s:%s guard %s trans %s",
frequency,
dvb_bw2str(dmc.dmc_fe_params.u.ofdm.bandwidth),
dvb_qam2str(dmc.dmc_fe_params.u.ofdm.constellation),
dvb_hier2str(dmc.dmc_fe_params.u.ofdm.hierarchy_information),
dvb_fec2str(dmc.dmc_fe_params.u.ofdm.code_rate_HP),
dvb_fec2str(dmc.dmc_fe_params.u.ofdm.code_rate_LP),
dvb_guard2str(dmc.dmc_fe_params.u.ofdm.guard_interval),
dvb_mode2str(dmc.dmc_fe_params.u.ofdm.transmission_mode));
dvb_bw2str(dmc.u.dmc_fe_ofdm.bandwidth),
dvb_qam2str(dmc.dmc_fe_modulation),
dvb_hier2str(dmc.u.dmc_fe_ofdm.hierarchy_information),
dvb_fec2str(dmc.u.dmc_fe_ofdm.code_rate_HP),
dvb_fec2str(dmc.u.dmc_fe_ofdm.code_rate_LP),
dvb_guard2str(dmc.u.dmc_fe_ofdm.guard_interval),
dvb_mode2str(dmc.u.dmc_fe_ofdm.transmission_mode));
/* Create */
return mm->mm_network->mn_create_mux(mm, onid, tsid, &dmc);
}
#endif /* ENABLE_DVBAPI */
#endif /* ENABLE_MPEGTS_DVB */
static int
dvb_desc_service

View file

@ -26,12 +26,10 @@
#include <stdlib.h>
#include <string.h>
#include <linux/dvb/frontend.h>
#include "tvheadend.h"
#include "dvb.h"
#include "dvb_charset_tables.h"
#include "../mpegts.h"
#include "input.h"
static int convert_iso_8859[16] = {
-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, -1, 11, 12, 13
@ -378,442 +376,309 @@ dvb_convert_date(const uint8_t *dvb_buf)
/*
* DVB API helpers
*/
#if ENABLE_DVBAPI
#if ENABLE_MPEGTS_DVB
#define dvb_str2val(p)\
const char *dvb_##p##2str (int p) { return val2str(p, p##tab); }\
int dvb_str2##p (const char *p) { return str2val(p, p##tab); }
const static struct strtab rollofftab[] = {
#if DVB_VER_ATLEAST(5,0)
{ "35", ROLLOFF_35 },
{ "20", ROLLOFF_20 },
{ "25", ROLLOFF_25 },
{ "AUTO", ROLLOFF_AUTO }
#endif
};
dvb_str2val(rolloff);
#define DVB_EOD -10 /* end-of-data */
static const char *dvb_common2str(int p)
{
if (p == 0)
return "NONE";
if (p == 1)
return "AUTO";
return NULL;
}
static int dvb_str2common(const char *p)
{
if (strcmp(p, "NONE") == 0)
return 0;
if (strcmp(p, "AUTO") == 0)
return 1;
return DVB_EOD;
}
static int dvb_verify(int val, int *table)
{
while (*table != DVB_EOD) {
if (val == *table)
return val;
table++;
}
return 0; /* NONE */
}
const char *dvb_rolloff2str(int p)
{
static char __thread buf[16];
const char *res = dvb_common2str(p);
if (res)
return res;
sprintf(buf, "%02i", p / 10);
return buf;
}
int dvb_str2rolloff(const char *p)
{
static int rolloff_table[] = {
DVB_ROLLOFF_20,
DVB_ROLLOFF_25,
DVB_ROLLOFF_35,
DVB_EOD,
};
int res = dvb_str2common(p);
if (res != DVB_EOD)
return res;
res = atoi(p) * 10;
return dvb_verify(atoi(p) * 10, rolloff_table);
}
const static struct strtab delsystab[] = {
#if DVB_VER_ATLEAST(5,0)
{ "UNDEFINED", SYS_UNDEFINED },
{ "DVBC_ANNEX_AC", SYS_DVBC_ANNEX_AC },
{ "DVBC_ANNEX_B", SYS_DVBC_ANNEX_B },
{ "DVBT", SYS_DVBT },
{ "DVBS", SYS_DVBS },
{ "DVBS2", SYS_DVBS2 },
{ "DVBH", SYS_DVBH },
{ "ISDBT", SYS_ISDBT },
{ "ISDBS", SYS_ISDBS },
{ "ISDBC", SYS_ISDBC },
{ "ATSC", SYS_ATSC },
{ "ATSCMH", SYS_ATSCMH },
{ "DMBTH", SYS_DMBTH },
{ "CMMB", SYS_CMMB },
{ "DAB", SYS_DAB },
#endif
#if DVB_VER_ATLEAST(5,1)
{ "DSS", SYS_DSS },
#endif
#if DVB_VER_ATLEAST(5,4)
{ "DVBT2", SYS_DVBT2 },
{ "TURBO", SYS_TURBO }
#endif
{ "NONE", DVB_SYS_NONE },
{ "DVBC_ANNEX_A", DVB_SYS_DVBC_ANNEX_A },
{ "DVBC_ANNEX_B", DVB_SYS_DVBC_ANNEX_B },
{ "DVBC_ANNEX_C", DVB_SYS_DVBC_ANNEX_C },
{ "DVBC_ANNEX_AC",DVB_SYS_DVBC_ANNEX_A }, /* for compatibility */
{ "DVBT", DVB_SYS_DVBT },
{ "DVBT2", DVB_SYS_DVBT2 },
{ "DVBS", DVB_SYS_DVBS },
{ "DVBS2", DVB_SYS_DVBS2 },
{ "DVBH", DVB_SYS_DVBH },
{ "ISDBT", DVB_SYS_ISDBT },
{ "ISDBS", DVB_SYS_ISDBS },
{ "ISDBC", DVB_SYS_ISDBC },
{ "ATSC", DVB_SYS_ATSC },
{ "ATSCMH", DVB_SYS_ATSCMH },
{ "DTMB", DVB_SYS_DTMB },
{ "DMBTH", DVB_SYS_DTMB }, /* for compatibility */
{ "CMMB", DVB_SYS_CMMB },
{ "DAB", DVB_SYS_DAB },
{ "DSS", DVB_SYS_DSS },
{ "TURBO", DVB_SYS_TURBO }
};
dvb_str2val(delsys);
#if DVB_VER_ATLEAST(5,10)
int
dvb_delsys2type ( fe_delivery_system_t delsys )
dvb_delsys2type ( dvb_fe_delivery_system_t delsys )
{
switch (delsys) {
case SYS_DVBC_ANNEX_AC:
case SYS_DVBC_ANNEX_B:
case SYS_ISDBC:
return FE_QAM;
case SYS_DVBT:
case SYS_DVBT2:
case SYS_TURBO:
case SYS_ISDBT:
return FE_OFDM;
case SYS_DVBS:
case SYS_DVBS2:
case SYS_ISDBS:
return FE_QPSK;
case SYS_ATSC:
case SYS_ATSCMH:
return FE_ATSC;
case DVB_SYS_DVBC_ANNEX_A:
case DVB_SYS_DVBC_ANNEX_B:
case DVB_SYS_DVBC_ANNEX_C:
case DVB_SYS_ISDBC:
return DVB_TYPE_C;
case DVB_SYS_DVBT:
case DVB_SYS_DVBT2:
case DVB_SYS_TURBO:
case DVB_SYS_ISDBT:
return DVB_TYPE_T;
case DVB_SYS_DVBS:
case DVB_SYS_DVBS2:
case DVB_SYS_ISDBS:
return DVB_TYPE_S;
case DVB_SYS_ATSC:
case DVB_SYS_ATSCMH:
return DVB_TYPE_ATSC;
default:
return -1;
return DVB_TYPE_NONE;
}
}
#endif
const 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_VER_ATLEAST(5,0)
{ "3/5", FEC_3_5 },
{ "9/10", FEC_9_10 }
#endif
};
dvb_str2val(fec);
const char *dvb_fec2str(int p)
{
static char __thread buf[16];
const char *res = dvb_common2str(p);
if (res)
return res;
sprintf(buf, "%i/%i", p / 100, p % 100);
return buf;
}
int dvb_str2fec(const char *p)
{
static int fec_table[] = {
DVB_FEC_1_2,
DVB_FEC_1_3,
DVB_FEC_1_5,
DVB_FEC_2_3,
DVB_FEC_2_5,
DVB_FEC_2_9,
DVB_FEC_3_4,
DVB_FEC_3_5,
DVB_FEC_4_5,
DVB_FEC_4_15,
DVB_FEC_5_6,
DVB_FEC_5_9,
DVB_FEC_6_7,
DVB_FEC_7_8,
DVB_FEC_7_9,
DVB_FEC_7_15,
DVB_FEC_8_9,
DVB_FEC_8_15,
DVB_FEC_9_10,
DVB_FEC_9_20,
DVB_FEC_11_15,
DVB_FEC_11_20,
DVB_FEC_11_45,
DVB_FEC_13_18,
DVB_FEC_13_45,
DVB_FEC_14_45,
DVB_FEC_23_36,
DVB_FEC_25_36,
DVB_FEC_26_45,
DVB_FEC_28_45,
DVB_FEC_29_45,
DVB_FEC_31_45,
DVB_FEC_32_45,
DVB_FEC_77_90,
DVB_EOD,
};
int res = dvb_str2common(p);
int hi, lo;
if (res != DVB_EOD)
return res;
hi = lo = 0;
sscanf(p, "%i/%i", &hi, &lo);
return dvb_verify(hi * 100 + lo, fec_table);
}
const 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_VER_ATLEAST(5,0)
{ "DQPSK", DQPSK },
#endif
#if DVB_VER_ATLEAST(5,1)
{ "8PSK", PSK_8 },
{ "16APSK", APSK_16 },
{ "32APSK", APSK_32 },
#endif
{ "NONE", DVB_MOD_NONE },
{ "AUTO", DVB_MOD_AUTO },
{ "QPSK", DVB_MOD_QPSK },
{ "QAM4NR", DVB_MOD_QAM_4_NR },
{ "QAM-AUTO", DVB_MOD_QAM_AUTO },
{ "QAM16", DVB_MOD_QAM_16 },
{ "QAM32", DVB_MOD_QAM_32 },
{ "QAM64", DVB_MOD_QAM_64 },
{ "QAM128", DVB_MOD_QAM_128 },
{ "QAM256", DVB_MOD_QAM_256 },
{ "8VSB", DVB_MOD_VSB_8 },
{ "16VSB", DVB_MOD_VSB_16 },
{ "8PSK", DVB_MOD_PSK_8 },
{ "DQPSK", DVB_MOD_DQPSK },
{ "BPSK", DVB_MOD_BPSK },
{ "BPSK-S", DVB_MOD_BPSK_S },
{ "16APSK", DVB_MOD_APSK_16 },
{ "32APSK", DVB_MOD_APSK_32 },
{ "64APSK", DVB_MOD_APSK_64 },
{ "128APSK", DVB_MOD_APSK_128 },
{ "256APSK", DVB_MOD_APSK_256 },
{ "8APSK-L", DVB_MOD_APSK_8_L },
{ "16APSK-L", DVB_MOD_APSK_16_L },
{ "32APSK-L", DVB_MOD_APSK_32_L },
{ "64APSK-L", DVB_MOD_APSK_64_L },
{ "128APSK-L", DVB_MOD_APSK_128_L },
{ "256APSK-L", DVB_MOD_APSK_256_L },
};
dvb_str2val(qam);
const 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
};
dvb_str2val(bw);
const char *dvb_bw2str(int p)
{
static char __thread buf[16];
const char *res = dvb_common2str(p);
if (res)
return res;
if (p % 1000)
sprintf(buf, "%i.%iMHz", p / 1000, p % 1000);
else
sprintf(buf, "%iMHz", p / 1000);
return buf;
}
int dvb_str2bw(const char *p)
{
static int bw_table[] = {
DVB_BANDWIDTH_1_712_MHZ,
DVB_BANDWIDTH_5_MHZ,
DVB_BANDWIDTH_6_MHZ,
DVB_BANDWIDTH_7_MHZ,
DVB_BANDWIDTH_8_MHZ,
DVB_BANDWIDTH_10_MHZ,
DVB_EOD,
};
int len, res = dvb_str2common(p);
int hi, lo;
if (res != DVB_EOD)
return res;
len = strlen(p);
hi = lo = 0;
sscanf(p, "%i.%i", &hi, &lo);
if (len > 3 && strcmp(&p[len-3], "MHz") == 0)
hi = hi * 1000 + lo;
return dvb_verify(hi, bw_table);
}
const static struct strtab modetab[] = {
{ "2k", TRANSMISSION_MODE_2K },
{ "8k", TRANSMISSION_MODE_8K },
{ "AUTO", TRANSMISSION_MODE_AUTO },
#if DVB_VER_ATLEAST(5,1)
{ "4k", TRANSMISSION_MODE_4K },
#endif
#if DVB_VER_ATLEAST(5,3)
{ "1k", TRANSMISSION_MODE_1K },
{ "2k", TRANSMISSION_MODE_16K },
{ "32k", TRANSMISSION_MODE_32K },
#endif
{ "NONE", DVB_TRANSMISSION_MODE_NONE },
{ "AUTO", DVB_TRANSMISSION_MODE_AUTO },
{ "1k", DVB_TRANSMISSION_MODE_1K },
{ "2k", DVB_TRANSMISSION_MODE_2K },
{ "8k", DVB_TRANSMISSION_MODE_8K },
{ "4k", DVB_TRANSMISSION_MODE_4K },
{ "16k", DVB_TRANSMISSION_MODE_16K },
{ "32k", DVB_TRANSMISSION_MODE_32K },
{ "C1", DVB_TRANSMISSION_MODE_C1 },
{ "C3780", DVB_TRANSMISSION_MODE_C3780 },
};
dvb_str2val(mode);
const 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
{ "NONE", DVB_GUARD_INTERVAL_NONE },
{ "AUTO", DVB_GUARD_INTERVAL_AUTO },
{ "1/4", DVB_GUARD_INTERVAL_1_4 },
{ "1/8", DVB_GUARD_INTERVAL_1_8 },
{ "1/32", DVB_GUARD_INTERVAL_1_32 },
{ "1/16", DVB_GUARD_INTERVAL_1_16 },
{ "1/128", DVB_GUARD_INTERVAL_1_128 },
{ "19/128", DVB_GUARD_INTERVAL_19_128 },
{ "19/256", DVB_GUARD_INTERVAL_19_256 },
{ "PN420", DVB_GUARD_INTERVAL_PN420 },
{ "PN595", DVB_GUARD_INTERVAL_PN595 },
{ "PN945", DVB_GUARD_INTERVAL_PN945 },
};
dvb_str2val(guard);
const static struct strtab hiertab[] = {
{ "NONE", HIERARCHY_NONE },
{ "1", HIERARCHY_1 },
{ "2", HIERARCHY_2 },
{ "4", HIERARCHY_4 },
{ "AUTO", HIERARCHY_AUTO }
{ "NONE", DVB_HIERARCHY_NONE },
{ "AUTO", DVB_HIERARCHY_AUTO },
{ "1", DVB_HIERARCHY_1 },
{ "2", DVB_HIERARCHY_2 },
{ "4", DVB_HIERARCHY_4 },
};
dvb_str2val(hier);
const static struct strtab poltab[] = {
{ "V", POLARISATION_VERTICAL },
{ "H", POLARISATION_HORIZONTAL },
{ "L", POLARISATION_CIRCULAR_LEFT },
{ "R", POLARISATION_CIRCULAR_RIGHT },
{ "V", DVB_POLARISATION_VERTICAL },
{ "H", DVB_POLARISATION_HORIZONTAL },
{ "L", DVB_POLARISATION_CIRCULAR_LEFT },
{ "R", DVB_POLARISATION_CIRCULAR_RIGHT },
};
dvb_str2val(pol);
const static struct strtab typetab[] = {
{"DVB-T", FE_OFDM},
{"DVB-C", FE_QAM},
{"DVB-S", FE_QPSK},
{"ATSC", FE_ATSC},
{"DVB-T", DVB_TYPE_T},
{"DVB-C", DVB_TYPE_C},
{"DVB-S", DVB_TYPE_S},
{"ATSC", DVB_TYPE_ATSC},
};
dvb_str2val(type);
const static struct strtab pilottab[] = {
#if DVB_VER_ATLEAST(5,0)
{"AUTO", PILOT_AUTO},
{"ON", PILOT_ON},
{"OFF", PILOT_OFF}
#endif
{"NONE", DVB_PILOT_AUTO},
{"AUTO", DVB_PILOT_AUTO},
{"ON", DVB_PILOT_ON},
{"OFF", DVB_PILOT_OFF}
};
dvb_str2val(pilot);
#undef dvb_str2val
/*
* Process mux conf
*/
static const char *
dvb_mux_conf_load_dvbt ( dvb_mux_conf_t *dmc, htsmsg_t *m )
{
int r;
const char *s;
s = htsmsg_get_str(m, "bandwidth");
if(s == NULL || (r = dvb_str2bw(s)) < 0)
return "Invalid bandwidth";
dmc->dmc_fe_params.u.ofdm.bandwidth = r;
s = htsmsg_get_str(m, "constellation");
if(s == NULL || (r = dvb_str2qam(s)) < 0)
return "Invalid QAM constellation";
dmc->dmc_fe_params.u.ofdm.constellation = r;
s = htsmsg_get_str(m, "transmission_mode");
if(s == NULL || (r = dvb_str2mode(s)) < 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 = dvb_str2guard(s)) < 0)
return "Invalid guard interval";
dmc->dmc_fe_params.u.ofdm.guard_interval = r;
s = htsmsg_get_str(m, "hierarchy");
if(s == NULL || (r = dvb_str2hier(s)) < 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 = dvb_str2fec(s)) < 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 = dvb_str2fec(s)) < 0)
return "Invalid lo-FEC";
dmc->dmc_fe_params.u.ofdm.code_rate_LP = r;
return NULL;
}
static const char *
dvb_mux_conf_load_dvbc ( dvb_mux_conf_t *dmc, htsmsg_t *m )
{
int r;
const char *s;
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 = dvb_str2qam(s)) < 0)
return "Invalid QAM constellation";
dmc->dmc_fe_params.u.qam.modulation = r;
s = htsmsg_get_str(m, "fec");
if(s == NULL || (r = dvb_str2fec(s)) < 0)
return "Invalid FEC";
dmc->dmc_fe_params.u.qam.fec_inner = r;
return NULL;
}
static const char *
dvb_mux_conf_load_dvbs ( dvb_mux_conf_t *dmc, htsmsg_t *m )
{
int r;
const char *s;
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 = dvb_str2fec(s)) < 0)
return "Invalid FEC";
dmc->dmc_fe_params.u.qpsk.fec_inner = r;
s = htsmsg_get_str(m, "polarisation");
if(s == NULL || (r = dvb_str2pol(s)) < 0)
return "Invalid polarisation";
dmc->dmc_fe_polarisation = r;
#if DVB_VER_ATLEAST(5,0)
s = htsmsg_get_str(m, "modulation");
if(s == NULL || (r = dvb_str2qam(s)) < 0) {
r = QPSK;
tvhlog(LOG_INFO, "dvb", "no modulation, using default QPSK");
}
dmc->dmc_fe_modulation = r;
s = htsmsg_get_str(m, "rolloff");
if(s == NULL || (r = dvb_str2rolloff(s)) < 0) {
r = ROLLOFF_35;
tvhlog(LOG_INFO, "dvb", "no rolloff, using default ROLLOFF_35");
}
dmc->dmc_fe_rolloff = r;
// TODO: pilot mode
#endif
return NULL;
}
static const char *
dvb_mux_conf_load_atsc ( dvb_mux_conf_t *dmc, htsmsg_t *m )
{
int r;
const char *s;
s = htsmsg_get_str(m, "constellation");
if(s == NULL || (r = dvb_str2qam(s)) < 0)
return "Invalid VSB constellation";
dmc->dmc_fe_params.u.vsb.modulation = r;
return NULL;
}
const char *
dvb_mux_conf_load ( fe_type_t type, dvb_mux_conf_t *dmc, htsmsg_t *m )
{
#if DVB_VER_ATLEAST(5,0)
int r;
const char *str;
#endif
uint32_t u32;
memset(dmc, 0, sizeof(dvb_mux_conf_t));
dmc->dmc_fe_params.inversion = INVERSION_AUTO;
/* Delivery system */
#if DVB_VER_ATLEAST(5,0)
str = htsmsg_get_str(m, "delsys");
if (!str || (r = dvb_str2delsys(str)) < 0) {
if (type == FE_OFDM) r = SYS_DVBT;
else if (type == FE_QAM) r = SYS_DVBC_ANNEX_AC;
else if (type == FE_QPSK) r = SYS_DVBS;
else if (type == FE_ATSC) r = SYS_ATSC;
else
return "Invalid FE type";
tvhlog(LOG_INFO, "dvb", "no delsys, using default %s", dvb_delsys2str(r));
}
dmc->dmc_fe_delsys = r;
#endif
/* Frequency */
if (htsmsg_get_u32(m, "frequency", &u32))
return "Invalid frequency";
dmc->dmc_fe_params.frequency = u32;
/* Type specific */
if (type == FE_OFDM) return dvb_mux_conf_load_dvbt(dmc, m);
else if (type == FE_QAM) return dvb_mux_conf_load_dvbc(dmc, m);
else if (type == FE_QPSK) return dvb_mux_conf_load_dvbs(dmc, m);
else if (type == FE_ATSC) return dvb_mux_conf_load_atsc(dmc, m);
else
return "Invalid FE type";
}
static void
dvb_mux_conf_save_dvbt ( dvb_mux_conf_t *dmc, htsmsg_t *m )
{
struct dvb_ofdm_parameters *ofdm = &dmc->dmc_fe_params.u.ofdm;
htsmsg_add_str(m, "bandwidth",
dvb_bw2str(ofdm->bandwidth));
htsmsg_add_str(m, "constellation",
dvb_qam2str(ofdm->constellation));
htsmsg_add_str(m, "transmission_mode",
dvb_mode2str(ofdm->transmission_mode));
htsmsg_add_str(m, "guard_interval",
dvb_guard2str(ofdm->guard_interval));
htsmsg_add_str(m, "hierarchy",
dvb_hier2str(ofdm->hierarchy_information));
htsmsg_add_str(m, "fec_hi",
dvb_fec2str(ofdm->code_rate_HP));
htsmsg_add_str(m, "fec_lo",
dvb_fec2str(ofdm->code_rate_LP));
}
static void
dvb_mux_conf_save_dvbc ( dvb_mux_conf_t *dmc, htsmsg_t *m )
{
struct dvb_qam_parameters *qam = &dmc->dmc_fe_params.u.qam;
htsmsg_add_u32(m, "symbol_rate", qam->symbol_rate);
htsmsg_add_str(m, "constellation", dvb_qam2str(qam->modulation));
htsmsg_add_str(m, "fec", dvb_fec2str(qam->fec_inner));
}
static void
dvb_mux_conf_save_dvbs ( dvb_mux_conf_t *dmc, htsmsg_t *m )
{
struct dvb_qpsk_parameters *qpsk = &dmc->dmc_fe_params.u.qpsk;
htsmsg_add_u32(m, "symbol_rate", qpsk->symbol_rate);
htsmsg_add_str(m, "fec", dvb_fec2str(qpsk->fec_inner));
htsmsg_add_str(m, "polarisation", dvb_pol2str(dmc->dmc_fe_polarisation));
#if DVB_VER_ATLEAST(5,0)
htsmsg_add_str(m, "modulation", dvb_qam2str(dmc->dmc_fe_modulation));
htsmsg_add_str(m, "rolloff", dvb_rolloff2str(dmc->dmc_fe_rolloff));
#endif
}
static void
dvb_mux_conf_save_atsc ( dvb_mux_conf_t *dmc, htsmsg_t *m )
{
htsmsg_add_str(m, "constellation",
dvb_qam2str(dmc->dmc_fe_params.u.vsb.modulation));
}
void
dvb_mux_conf_save ( fe_type_t type, dvb_mux_conf_t *dmc, htsmsg_t *m )
{
htsmsg_add_u32(m, "frequency", dmc->dmc_fe_params.frequency);
#if DVB_VER_ATLEAST(5,0)
htsmsg_add_str(m, "delsys", dvb_delsys2str(dmc->dmc_fe_delsys));
#endif
if (type == FE_OFDM) dvb_mux_conf_save_dvbt(dmc, m);
else if (type == FE_QAM) dvb_mux_conf_save_dvbc(dmc, m);
else if (type == FE_QPSK) dvb_mux_conf_save_dvbs(dmc, m);
else if (type == FE_ATSC) dvb_mux_conf_save_atsc(dmc, m);
}
int
dvb_bandwidth ( fe_bandwidth_t bw )
{
switch (bw) {
#if DVB_VER_ATLEAST(5,3)
case BANDWIDTH_10_MHZ:
return 10000000;
case BANDWIDTH_5_MHZ:
return 5000000;
case BANDWIDTH_1_712_MHZ:
return 1712000;
#endif
case BANDWIDTH_8_MHZ:
return 8000000;
case BANDWIDTH_7_MHZ:
return 7000000;
case BANDWIDTH_6_MHZ:
return 6000000;
default:
return 0;
}
}
#endif /* ENABLE_DVBAPI */
#endif /* ENABLE_MPEGTS_DVB */
/**
*

View file

@ -20,8 +20,7 @@
#ifndef __IPTV_PRIVATE_H__
#define __IPTV_PRIVATE_H__
#include "input/mpegts.h"
#include "input/mpegts/iptv.h"
#include "input.h"
#include "htsbuf.h"
#include "url.h"

View file

@ -21,8 +21,6 @@
#include "input.h"
#include "settings.h"
#include "linuxdvb_private.h"
#include "scanfile.h"
#include "../dvb_charset.h"
int linuxdvb_adapter_mask;
@ -30,26 +28,14 @@ void linuxdvb_init ( int adapter_mask )
{
linuxdvb_adapter_mask = adapter_mask;
/* Load scan files */
scanfile_init();
/* Load list of mux charset global overrides */
dvb_charset_init();
/* Initialise en50494 locks */
linuxdvb_en50494_init();
/* Initialise networks */
linuxdvb_network_init();
/* Initialsie devices */
linuxdvb_adapter_init();
}
void linuxdvb_done ( void )
{
linuxdvb_network_done();
linuxdvb_adapter_done();
dvb_charset_done();
scanfile_done();
}

View file

@ -33,6 +33,8 @@
#include <fcntl.h>
#include <openssl/sha.h>
#include <linux/dvb/frontend.h>
#define FE_PATH "%s/frontend%d"
#define DVR_PATH "%s/dvr%d"
#define DMX_PATH "%s/demux%d"
@ -155,6 +157,26 @@ linuxdvb_adapter_create
return la;
}
/*
*
*/
static dvb_fe_type_t
linux_dvb_get_type(int linux_type)
{
switch (linux_type) {
case FE_QPSK:
return DVB_TYPE_S;
case FE_QAM:
return DVB_TYPE_C;
case FE_OFDM:
return DVB_TYPE_T;
case FE_ATSC:
return DVB_TYPE_ATSC;
default:
return DVB_TYPE_NONE;
}
}
/*
* Add adapter by path
*/
@ -171,8 +193,9 @@ linuxdvb_adapter_add ( const char *path )
uint8_t uuidbin[20];
htsmsg_t *conf, *feconf;
int save = 0;
dvb_fe_type_t type;
#if DVB_VER_ATLEAST(5,10)
int fetypes[4] = { 0 };
dvb_fe_type_t fetypes[DVB_TYPE_LAST+1] = { 0 };
struct dtv_property cmd = {
.cmd = DTV_ENUM_DELSYS
};
@ -243,6 +266,11 @@ linuxdvb_adapter_add ( const char *path )
tvhlog(LOG_ERR, "linuxdvb", "unable to query %s", fe_path);
continue;
}
type = linux_dvb_get_type(dfi.type);
if (type == DVB_TYPE_NONE) {
tvhlog(LOG_ERR, "linuxdvb", "unable to determine FE type %s - %i", fe_path, dfi.type);
continue;
}
/* DVR/DMX (bit of a guess) */
snprintf(dmx_path, sizeof(dmx_path), DMX_PATH, path, i);
@ -284,22 +312,23 @@ linuxdvb_adapter_add ( const char *path )
}
/* Create frontend */
linuxdvb_frontend_create(feconf, la, i, fe_path, dmx_path, dvr_path, &dfi);
linuxdvb_frontend_create(feconf, la, i, fe_path, dmx_path, dvr_path, type, dfi.name);
#if DVB_VER_ATLEAST(5,10)
fetypes[dfi.type] = 1;
fetypes[type] = 1;
for (j = 0; j < cmd.u.buffer.len; j++) {
/* Invalid */
if ((dfi.type = dvb_delsys2type(cmd.u.buffer.data[j])) == -1)
if ((type = dvb_delsys2type(cmd.u.buffer.data[j])) == DVB_TYPE_NONE)
continue;
/* Couldn't find */
if (fetypes[dfi.type])
if (fetypes[type])
continue;
/* Create */
linuxdvb_frontend_create(feconf, la, i, fe_path, dmx_path, dvr_path, &dfi);
fetypes[dfi.type] = 1;
linuxdvb_frontend_create(feconf, la, i, fe_path, dmx_path, dvr_path,
type, dfi.name);
fetypes[type] = 1;
}
#endif
pthread_mutex_unlock(&global_lock);

View file

@ -30,6 +30,8 @@
#include <unistd.h>
#include <math.h>
#include <linux/dvb/frontend.h>
/* **************************************************************************
* Static definition
* *************************************************************************/
@ -141,12 +143,12 @@ const idclass_t linuxdvb_en50494_class =
static int
linuxdvb_en50494_tune
( linuxdvb_diseqc_t *ld, linuxdvb_mux_t *lm, linuxdvb_satconf_ele_t *sc, int fd )
( linuxdvb_diseqc_t *ld, dvb_mux_t *lm, linuxdvb_satconf_ele_t *sc, int fd )
{
int ret = 0;
int i;
linuxdvb_en50494_t *le = (linuxdvb_en50494_t*) ld;
linuxdvb_lnb_t *lnb = sc->ls_lnb;
linuxdvb_lnb_t *lnb = sc->lse_lnb;
/* band & polarisation */
uint8_t pol = lnb->lnb_pol(lnb, lm);
@ -177,7 +179,7 @@ linuxdvb_en50494_tune
band, freq, data1, data2);
pthread_mutex_lock(&linuxdvb_en50494_lock);
for (i = 0; i <= sc->ls_parent->ls_diseqc_repeats; i++) {
for (i = 0; i <= sc->lse_parent->ls_diseqc_repeats; i++) {
/* to avoid repeated collision, wait a random time (5-25ms) */
if (i != 0) {
int ms = rand()%20 + 5;

View file

@ -31,6 +31,8 @@
#include <fcntl.h>
#include <assert.h>
#include <linux/dvb/dmx.h>
#include <linux/dvb/frontend.h>
static void
linuxdvb_frontend_monitor ( void *aux );
@ -212,6 +214,26 @@ linuxdvb_frontend_get_weight ( mpegts_input_t *mi )
return weight;
}
static int
linuxdvb_frontend_get_priority ( mpegts_input_t *mi, mpegts_mux_t *mm )
{
linuxdvb_frontend_t *lfe = (linuxdvb_frontend_t*)mi;
int r = mpegts_input_get_priority(mi, mm);
if (lfe->lfe_satconf)
r += linuxdvb_satconf_get_priority(lfe->lfe_satconf, mm);
return r;
}
static int
linuxdvb_frontend_get_grace ( mpegts_input_t *mi, mpegts_mux_t *mm )
{
linuxdvb_frontend_t *lfe = (linuxdvb_frontend_t*)mi;
int r = 5;
if (lfe->lfe_satconf)
r = linuxdvb_satconf_get_grace(lfe->lfe_satconf, mm);
return r;
}
static int
linuxdvb_frontend_is_enabled ( mpegts_input_t *mi )
{
@ -248,12 +270,18 @@ linuxdvb_frontend_stop_mux
/* Ensure it won't happen immediately */
gtimer_arm(&lfe->lfe_monitor_timer, linuxdvb_frontend_monitor, lfe, 2);
if (lfe->lfe_satconf)
linuxdvb_satconf_post_stop_mux(lfe->lfe_satconf);
}
static int
linuxdvb_frontend_start_mux
( mpegts_input_t *mi, mpegts_mux_instance_t *mmi )
{
linuxdvb_frontend_t *lfe = (linuxdvb_frontend_t*)mi;
if (lfe->lfe_satconf)
return linuxdvb_satconf_start_mux(lfe->lfe_satconf, mmi);
return linuxdvb_frontend_tune1((linuxdvb_frontend_t*)mi, mmi, -1);
}
@ -326,19 +354,15 @@ linuxdvb_frontend_network_list ( mpegts_input_t *mi )
{
linuxdvb_frontend_t *lfe = (linuxdvb_frontend_t*)mi;
const idclass_t *idc;
extern const idclass_t linuxdvb_network_dvbt_class;
extern const idclass_t linuxdvb_network_dvbc_class;
extern const idclass_t linuxdvb_network_dvbs_class;
extern const idclass_t linuxdvb_network_atsc_class;
if (lfe->lfe_info.type == FE_OFDM)
idc = &linuxdvb_network_dvbt_class;
else if (lfe->lfe_info.type == FE_QAM)
idc = &linuxdvb_network_dvbc_class;
else if (lfe->lfe_info.type == FE_QPSK)
idc = &linuxdvb_network_dvbs_class;
else if (lfe->lfe_info.type == FE_ATSC)
idc = &linuxdvb_network_atsc_class;
if (lfe->lfe_type == DVB_TYPE_T)
idc = &dvb_network_dvbt_class;
else if (lfe->lfe_type == DVB_TYPE_C)
idc = &dvb_network_dvbc_class;
else if (lfe->lfe_type == DVB_TYPE_S)
idc = &dvb_network_dvbs_class;
else if (lfe->lfe_type == DVB_TYPE_ATSC)
idc = &dvb_network_atsc_class;
else
return NULL;
@ -351,15 +375,15 @@ linuxdvb_frontend_network_list ( mpegts_input_t *mi )
static void
linuxdvb_frontend_default_tables
( linuxdvb_frontend_t *lfe, linuxdvb_mux_t *lm )
( linuxdvb_frontend_t *lfe, dvb_mux_t *lm )
{
mpegts_mux_t *mm = (mpegts_mux_t*)lm;
psi_tables_default(mm);
/* ATSC */
if (lfe->lfe_info.type == FE_ATSC) {
if (lm->lm_tuning.dmc_fe_params.u.vsb.modulation == VSB_8)
if (lfe->lfe_type == DVB_TYPE_ATSC) {
if (lm->lm_tuning.dmc_fe_modulation == DVB_MOD_VSB_8)
psi_tables_atsc_t(mm);
else
psi_tables_atsc_c(mm);
@ -462,7 +486,7 @@ linuxdvb_frontend_monitor ( void *aux )
pthread_mutex_unlock(&lfe->lfe_dvr_lock);
/* Table handlers */
linuxdvb_frontend_default_tables(lfe, (linuxdvb_mux_t*)mm);
linuxdvb_frontend_default_tables(lfe, (dvb_mux_t*)mm);
/* Locked - ensure everything is open */
pthread_mutex_lock(&lfe->mi_delivery_mutex);
@ -666,15 +690,180 @@ linuxdvb_frontend_input_thread ( void *aux )
* Tuning
* *************************************************************************/
typedef struct tvh2linuxdvb {
int t; ///< TVH internal value
int l; ///< LinuxDVB API value
} tvh2linuxdvb_t;
#define TABLE_EOD -1
static int
translate_from_table
(const char *prefix, int src, tvh2linuxdvb_t *tbl, int defval)
{
while (tbl->t >= 0) {
if (tbl->t == src)
return tbl->l;
tbl++;
}
tvhtrace("linuxdvb", "%s - cannot translate %d", prefix, src);
return defval;
}
#define TOSTR(s) #s
#define TR(s, t, d) translate_from_table(TOSTR(s), dmc->dmc_fe_##s , t, d)
#define TRU(s, t, d) translate_from_table(TOSTR(s), dmc->u.dmc_fe_##s , t, d)
int
linuxdvb_frontend_tune0
( linuxdvb_frontend_t *lfe, mpegts_mux_instance_t *mmi, uint32_t freq )
{
static tvh2linuxdvb_t inv_tbl[] = {
{ .t = DVB_INVERSION_AUTO, .l = INVERSION_AUTO },
{ .t = DVB_INVERSION_OFF, .l = INVERSION_OFF },
{ .t = DVB_INVERSION_ON, .l = INVERSION_ON },
{ .t = TABLE_EOD }
};
static tvh2linuxdvb_t bw_tbl[] = {
{ .t = DVB_BANDWIDTH_AUTO, .l = BANDWIDTH_AUTO },
#if DVB_VER_ATLEAST(5,3)
{ .t = DVB_BANDWIDTH_1_712_MHZ, .l = BANDWIDTH_1_712_MHZ },
{ .t = DVB_BANDWIDTH_5_MHZ, .l = BANDWIDTH_5_MHZ },
#endif
{ .t = DVB_BANDWIDTH_6_MHZ, .l = BANDWIDTH_6_MHZ },
{ .t = DVB_BANDWIDTH_7_MHZ, .l = BANDWIDTH_7_MHZ },
{ .t = DVB_BANDWIDTH_8_MHZ, .l = BANDWIDTH_8_MHZ },
#if DVB_VER_ATLEAST(5,3)
{ .t = DVB_BANDWIDTH_10_MHZ, .l = BANDWIDTH_10_MHZ },
#endif
{ .t = TABLE_EOD }
};
static tvh2linuxdvb_t fec_tbl[] = {
{ .t = DVB_FEC_NONE, .l = FEC_NONE },
{ .t = DVB_FEC_AUTO, .l = FEC_AUTO },
{ .t = DVB_FEC_1_2, .l = FEC_1_2 },
{ .t = DVB_FEC_2_3, .l = FEC_2_3 },
{ .t = DVB_FEC_2_5, .l = FEC_2_5 },
{ .t = DVB_FEC_3_4, .l = FEC_3_4 },
#if DVB_VER_ATLEAST(5,0)
{ .t = DVB_FEC_3_5, .l = FEC_3_5 },
#endif
{ .t = DVB_FEC_4_5, .l = FEC_4_5 },
{ .t = DVB_FEC_5_6, .l = FEC_5_6 },
{ .t = DVB_FEC_6_7, .l = FEC_6_7 },
{ .t = DVB_FEC_7_8, .l = FEC_7_8 },
{ .t = DVB_FEC_8_9, .l = FEC_8_9 },
#if DVB_VER_ATLEAST(5,0)
{ .t = DVB_FEC_9_10, .l = FEC_9_10 },
#endif
{ .t = TABLE_EOD }
};
static tvh2linuxdvb_t mod_tbl[] = {
{ .t = DVB_MOD_AUTO, .l = QAM_AUTO },
{ .t = DVB_MOD_QPSK, .l = QPSK },
{ .t = DVB_MOD_QAM_16, .l = QAM_16 },
{ .t = DVB_MOD_QAM_32, .l = QAM_32 },
{ .t = DVB_MOD_QAM_64, .l = QAM_64 },
{ .t = DVB_MOD_QAM_128, .l = QAM_128 },
{ .t = DVB_MOD_QAM_256, .l = QAM_256 },
{ .t = DVB_MOD_QAM_AUTO, .l = QAM_AUTO },
{ .t = DVB_MOD_VSB_8, .l = VSB_8 },
{ .t = DVB_MOD_VSB_16, .l = VSB_16 },
#if DVB_VER_ATLEAST(5,1)
{ .t = DVB_MOD_PSK_8, .l = PSK_8, },
{ .t = DVB_MOD_APSK_16, .l = APSK_16 },
{ .t = DVB_MOD_APSK_32, .l = APSK_32 },
#endif
#if DVB_VER_ATLEAST(5,0)
{ .t = DVB_MOD_DQPSK, .l = DQPSK },
#endif
#if DVB_VER_ATLEAST(5,3)
{ .t = DVB_MOD_QAM_4_NR, .l = QAM_4_NR },
#endif
{ .t = TABLE_EOD }
};
static tvh2linuxdvb_t trans_tbl[] = {
{ .t = DVB_TRANSMISSION_MODE_AUTO, .l = TRANSMISSION_MODE_AUTO },
#if DVB_VER_ATLEAST(5,3)
{ .t = DVB_TRANSMISSION_MODE_1K, .l = TRANSMISSION_MODE_1K },
#endif
{ .t = DVB_TRANSMISSION_MODE_2K, .l = TRANSMISSION_MODE_2K },
#if DVB_VER_ATLEAST(5,1)
{ .t = DVB_TRANSMISSION_MODE_4K, .l = TRANSMISSION_MODE_4K },
#endif
{ .t = DVB_TRANSMISSION_MODE_8K, .l = TRANSMISSION_MODE_8K },
#if DVB_VER_ATLEAST(5,3)
{ .t = DVB_TRANSMISSION_MODE_16K, .l = TRANSMISSION_MODE_16K },
{ .t = DVB_TRANSMISSION_MODE_32K, .l = TRANSMISSION_MODE_32K },
{ .t = DVB_TRANSMISSION_MODE_C1, .l = TRANSMISSION_MODE_C1 },
{ .t = DVB_TRANSMISSION_MODE_C3780, .l = TRANSMISSION_MODE_C3780 },
#endif
{ .t = TABLE_EOD }
};
static tvh2linuxdvb_t guard_tbl[] = {
{ .t = DVB_GUARD_INTERVAL_AUTO, .l = GUARD_INTERVAL_AUTO },
{ .t = DVB_GUARD_INTERVAL_1_4, .l = GUARD_INTERVAL_1_4 },
{ .t = DVB_GUARD_INTERVAL_1_8, .l = GUARD_INTERVAL_1_8 },
{ .t = DVB_GUARD_INTERVAL_1_16, .l = GUARD_INTERVAL_1_16 },
{ .t = DVB_GUARD_INTERVAL_1_32, .l = GUARD_INTERVAL_1_32 },
#if DVB_VER_ATLEAST(5,3)
{ .t = DVB_GUARD_INTERVAL_1_128, .l = GUARD_INTERVAL_1_128 },
{ .t = DVB_GUARD_INTERVAL_19_128, .l = GUARD_INTERVAL_19_128 },
{ .t = DVB_GUARD_INTERVAL_19_256, .l = GUARD_INTERVAL_19_256 },
#endif
{ .t = TABLE_EOD }
};
static tvh2linuxdvb_t h_tbl[] = {
{ .t = DVB_HIERARCHY_NONE, .l = HIERARCHY_NONE },
{ .t = DVB_HIERARCHY_AUTO, .l = HIERARCHY_AUTO },
{ .t = DVB_HIERARCHY_1, .l = HIERARCHY_1 },
{ .t = DVB_HIERARCHY_2, .l = HIERARCHY_2 },
{ .t = DVB_HIERARCHY_4, .l = HIERARCHY_4 },
{ .t = TABLE_EOD }
};
#if DVB_API_VERSION >= 5
static tvh2linuxdvb_t delsys_tbl[] = {
{ .t = DVB_SYS_DVBC_ANNEX_A, .l = SYS_DVBC_ANNEX_A },
{ .t = DVB_SYS_DVBC_ANNEX_B, .l = SYS_DVBC_ANNEX_B },
{ .t = DVB_SYS_DVBC_ANNEX_C, .l = SYS_DVBC_ANNEX_C },
{ .t = DVB_SYS_DVBT, .l = SYS_DVBT },
{ .t = DVB_SYS_DVBT2, .l = SYS_DVBT2 },
{ .t = DVB_SYS_DVBS, .l = SYS_DVBS },
{ .t = DVB_SYS_DVBS2, .l = SYS_DVBS2 },
{ .t = DVB_SYS_DVBH, .l = SYS_DVBH },
{ .t = DVB_SYS_DSS, .l = SYS_DSS },
{ .t = DVB_SYS_ISDBT, .l = SYS_ISDBT },
{ .t = DVB_SYS_ISDBS, .l = SYS_ISDBS },
{ .t = DVB_SYS_ISDBC, .l = SYS_ISDBC },
{ .t = DVB_SYS_ATSC, .l = SYS_ATSC },
{ .t = DVB_SYS_ATSCMH, .l = SYS_ATSCMH },
{ .t = DVB_SYS_DTMB, .l = SYS_DTMB },
{ .t = DVB_SYS_CMMB, .l = SYS_CMMB },
{ .t = DVB_SYS_DAB, .l = SYS_DAB },
{ .t = DVB_SYS_TURBO, .l = SYS_TURBO },
{ .t = TABLE_EOD }
};
static tvh2linuxdvb_t pilot_tbl[] = {
{ .t = DVB_PILOT_AUTO, .l = PILOT_AUTO },
{ .t = DVB_PILOT_ON, .l = PILOT_ON },
{ .t = DVB_PILOT_OFF, .l = PILOT_OFF },
{ .l = TABLE_EOD }
};
static tvh2linuxdvb_t rolloff_tbl[] = {
{ .t = DVB_HIERARCHY_AUTO, .l = ROLLOFF_AUTO },
{ .t = DVB_ROLLOFF_20, .l = ROLLOFF_20 },
{ .t = DVB_ROLLOFF_25, .l = ROLLOFF_25 },
{ .t = DVB_ROLLOFF_35, .l = ROLLOFF_35 },
{ .t = TABLE_EOD },
};
#endif
int r;
struct dvb_frontend_event ev;
char buf1[256];
mpegts_mux_instance_t *cur = LIST_FIRST(&lfe->mi_mux_active);
linuxdvb_mux_t *lm = (linuxdvb_mux_t*)mmi->mmi_mux;
dvb_mux_t *lm = (dvb_mux_t*)mmi->mmi_mux;
dvb_mux_conf_t *dmc;
struct dvb_frontend_parameters p;
// Not sure if this is right place?
/* Currently active */
@ -701,10 +890,53 @@ linuxdvb_frontend_tune0
lfe->lfe_locked = 0;
lfe->lfe_status = 0;
/*
* copy the universal parameters to the Linux kernel structure
*/
dmc = &lm->lm_tuning;
memset(&p, 0, sizeof(p));
p.frequency = dmc->dmc_fe_freq;
p.inversion = TR(inversion, inv_tbl, INVERSION_AUTO);
switch (dmc->dmc_fe_type) {
case DVB_TYPE_T:
#define _OFDM(xyz) p.u.ofdm.xyz
_OFDM(bandwidth) = TRU(ofdm.bandwidth, bw_tbl, BANDWIDTH_AUTO);
_OFDM(code_rate_HP) = TRU(ofdm.code_rate_HP, fec_tbl, FEC_AUTO);
_OFDM(code_rate_LP) = TRU(ofdm.code_rate_LP, fec_tbl, FEC_AUTO);
_OFDM(constellation) = TR(modulation, mod_tbl, QAM_AUTO);
_OFDM(transmission_mode) = TRU(ofdm.transmission_mode, trans_tbl, TRANSMISSION_MODE_AUTO);
_OFDM(guard_interval) = TRU(ofdm.guard_interval, guard_tbl, GUARD_INTERVAL_AUTO);
_OFDM(hierarchy_information)
= TRU(ofdm.hierarchy_information, h_tbl, HIERARCHY_AUTO);
#undef _OFDM
break;
case DVB_TYPE_C:
p.u.qam.symbol_rate = dmc->u.dmc_fe_qam.symbol_rate;
p.u.qam.fec_inner = TRU(qam.fec_inner, fec_tbl, FEC_AUTO);
p.u.qam.modulation = TR(modulation, mod_tbl, QAM_AUTO);
break;
case DVB_TYPE_S:
p.u.qpsk.symbol_rate = dmc->u.dmc_fe_qpsk.symbol_rate;
p.u.qpsk.fec_inner = TRU(qpsk.fec_inner, fec_tbl, FEC_AUTO);
break;
case DVB_TYPE_ATSC:
p.u.vsb.modulation = TR(modulation, mod_tbl, QAM_AUTO);
break;
default:
tvherror("linuxdvb", "%s - unknown FE type %d", buf1, dmc->dmc_fe_type);
return SM_CODE_TUNING_FAILED;
}
if (freq != (uint32_t)-1)
p.frequency = freq;
if (dmc->dmc_fe_type != lfe->lfe_type) {
tvherror("linuxdvb", "%s - failed to tune [type does not match %i != %i]", buf1, dmc->dmc_fe_type, lfe->lfe_type);
return SM_CODE_TUNING_FAILED;
}
/* S2 tuning */
#if DVB_API_VERSION >= 5
dvb_mux_conf_t *dmc = &lm->lm_tuning;
struct dvb_frontend_parameters *p = &dmc->dmc_fe_params;
struct dtv_property cmds[20];
struct dtv_properties cmdseq = { .num = 0, .props = cmds };
@ -720,62 +952,58 @@ linuxdvb_frontend_tune0
return -1;
if (freq == (uint32_t)-1)
freq = p->frequency;
freq = p.frequency;
/* Tune */
#define S2CMD(c, d)\
cmds[cmdseq.num].cmd = c;\
cmds[cmdseq.num++].u.data = d
memset(&cmds, 0, sizeof(cmds));
S2CMD(DTV_DELIVERY_SYSTEM, lm->lm_tuning.dmc_fe_delsys);
S2CMD(DTV_DELIVERY_SYSTEM, TR(delsys, delsys_tbl, SYS_UNDEFINED));
S2CMD(DTV_FREQUENCY, freq);
S2CMD(DTV_INVERSION, p->inversion);
S2CMD(DTV_INVERSION, p.inversion);
/* DVB-T */
if (lfe->lfe_info.type == FE_OFDM) {
S2CMD(DTV_BANDWIDTH_HZ, dvb_bandwidth(p->u.ofdm.bandwidth));
if (lfe->lfe_type == DVB_TYPE_T) {
S2CMD(DTV_BANDWIDTH_HZ, dvb_bandwidth(dmc->u.dmc_fe_ofdm.bandwidth));
#if DVB_VER_ATLEAST(5,1)
S2CMD(DTV_CODE_RATE_HP, p->u.ofdm.code_rate_HP);
S2CMD(DTV_CODE_RATE_LP, p->u.ofdm.code_rate_LP);
S2CMD(DTV_CODE_RATE_HP, p.u.ofdm.code_rate_HP);
S2CMD(DTV_CODE_RATE_LP, p.u.ofdm.code_rate_LP);
#endif
S2CMD(DTV_MODULATION, p->u.ofdm.constellation);
S2CMD(DTV_MODULATION, p.u.ofdm.constellation);
#if DVB_VER_ATLEAST(5,1)
S2CMD(DTV_TRANSMISSION_MODE, p->u.ofdm.transmission_mode);
S2CMD(DTV_GUARD_INTERVAL, p->u.ofdm.guard_interval);
S2CMD(DTV_HIERARCHY, p->u.ofdm.hierarchy_information);
S2CMD(DTV_TRANSMISSION_MODE, p.u.ofdm.transmission_mode);
S2CMD(DTV_GUARD_INTERVAL, p.u.ofdm.guard_interval);
S2CMD(DTV_HIERARCHY, p.u.ofdm.hierarchy_information);
#endif
/* DVB-C */
} else if (lfe->lfe_info.type == FE_QAM) {
S2CMD(DTV_SYMBOL_RATE, p->u.qam.symbol_rate);
S2CMD(DTV_MODULATION, p->u.qam.modulation);
S2CMD(DTV_INNER_FEC, p->u.qam.fec_inner);
} else if (lfe->lfe_type == DVB_TYPE_C) {
S2CMD(DTV_SYMBOL_RATE, p.u.qam.symbol_rate);
S2CMD(DTV_MODULATION, p.u.qam.modulation);
S2CMD(DTV_INNER_FEC, p.u.qam.fec_inner);
/* DVB-S */
} else if (lfe->lfe_info.type == FE_QPSK) {
S2CMD(DTV_SYMBOL_RATE, p->u.qpsk.symbol_rate);
S2CMD(DTV_INNER_FEC, p->u.qpsk.fec_inner);
S2CMD(DTV_PILOT, dmc->dmc_fe_pilot);
S2CMD(DTV_MODULATION, dmc->dmc_fe_modulation);
if (lm->lm_tuning.dmc_fe_delsys == SYS_DVBS) {
S2CMD(DTV_ROLLOFF, ROLLOFF_35);
} else if (lfe->lfe_type == DVB_TYPE_S) {
S2CMD(DTV_SYMBOL_RATE, p.u.qpsk.symbol_rate);
S2CMD(DTV_INNER_FEC, p.u.qpsk.fec_inner);
S2CMD(DTV_PILOT, TR(pilot, pilot_tbl, PILOT_AUTO));
S2CMD(DTV_MODULATION, TR(modulation, mod_tbl, QPSK));
if (lm->lm_tuning.dmc_fe_delsys == DVB_SYS_DVBS) {
S2CMD(DTV_ROLLOFF, ROLLOFF_35);
} else {
S2CMD(DTV_ROLLOFF, dmc->dmc_fe_rolloff);
S2CMD(DTV_ROLLOFF, TR(rolloff, rolloff_tbl, ROLLOFF_AUTO));
}
/* ATSC */
} else {
S2CMD(DTV_MODULATION, p->u.vsb.modulation);
S2CMD(DTV_MODULATION, p.u.vsb.modulation);
}
/* Tune */
S2CMD(DTV_TUNE, 0);
#undef S2CMD
#else
dvb_mux_conf_t dmc = lm->lm_tuning;
struct dvb_frontend_parameters *p = &dmc.dmc_fe_params;
if (freq != (uint32_t)-1)
p->frequency = freq;
#endif
/* discard stale events */
@ -842,16 +1070,16 @@ linuxdvb_frontend_t *
linuxdvb_frontend_create
( htsmsg_t *conf, linuxdvb_adapter_t *la, int number,
const char *fe_path, const char *dmx_path, const char *dvr_path,
struct dvb_frontend_info *dfi )
dvb_fe_type_t type, const char *name )
{
const idclass_t *idc;
const char *str, *uuid = NULL, *scuuid = NULL, *sctype = NULL;
char id[12], name[256];
char id[12], lname[256];
linuxdvb_frontend_t *lfe;
htsmsg_t *scconf = NULL;
/* Internal config ID */
snprintf(id, sizeof(id), "%s #%d", dvb_type2str(dfi->type), number);
snprintf(id, sizeof(id), "%s #%d", dvb_type2str(type), number);
if (conf)
conf = htsmsg_get_map(conf, id);
if (conf)
@ -868,16 +1096,16 @@ linuxdvb_frontend_create
}
/* Class */
if (dfi->type == FE_QPSK)
if (type == DVB_TYPE_S)
idc = &linuxdvb_frontend_dvbs_class;
else if (dfi->type == FE_QAM)
else if (type == DVB_TYPE_C)
idc = &linuxdvb_frontend_dvbc_class;
else if (dfi->type == FE_OFDM)
else if (type == DVB_TYPE_T)
idc = &linuxdvb_frontend_dvbt_class;
else if (dfi->type == FE_ATSC)
else if (type == DVB_TYPE_ATSC)
idc = &linuxdvb_frontend_atsc_class;
else {
tvherror("linuxdvb", "unknown FE type %d", dfi->type);
tvherror("linuxdvb", "unknown FE type %d", type);
return NULL;
}
@ -887,18 +1115,22 @@ linuxdvb_frontend_create
// in mpegts_input_create()). So we must set early.
lfe = calloc(1, sizeof(linuxdvb_frontend_t));
lfe->lfe_number = number;
memcpy(&lfe->lfe_info, dfi, sizeof(struct dvb_frontend_info));
lfe->lfe_type = type;
strncpy(lfe->lfe_name, name, sizeof(lfe->lfe_name));
lfe->lfe_name[sizeof(lfe->lfe_name)-1] = '\0';
lfe = (linuxdvb_frontend_t*)mpegts_input_create0((mpegts_input_t*)lfe, idc, uuid, conf);
if (!lfe) return NULL;
/* Callbacks */
lfe->mi_is_free = linuxdvb_frontend_is_free;
lfe->mi_get_weight = linuxdvb_frontend_get_weight;
lfe->mi_is_free = linuxdvb_frontend_is_free;
lfe->mi_get_weight = linuxdvb_frontend_get_weight;
lfe->mi_get_priority = linuxdvb_frontend_get_priority;
lfe->mi_get_grace = linuxdvb_frontend_get_grace;
/* Default name */
if (!lfe->mi_name) {
snprintf(name, sizeof(name), "%s : %s", dfi->name, id);
lfe->mi_name = strdup(name);
snprintf(lname, sizeof(lname), "%s : %s", name, id);
lfe->mi_name = strdup(lname);
}
/* Set paths */
@ -933,7 +1165,7 @@ linuxdvb_frontend_create
}
/* Create satconf */
if (dfi->type == FE_QPSK && !lfe->lfe_satconf)
if (lfe->lfe_type == DVB_TYPE_S && !lfe->lfe_satconf)
lfe->lfe_satconf = linuxdvb_satconf_create(lfe, sctype, scuuid, scconf);
return lfe;
@ -947,7 +1179,7 @@ linuxdvb_frontend_save ( linuxdvb_frontend_t *lfe, htsmsg_t *fe )
/* Save frontend */
mpegts_input_save((mpegts_input_t*)lfe, m);
htsmsg_add_str(m, "type", dvb_type2str(lfe->lfe_info.type));
htsmsg_add_str(m, "type", dvb_type2str(lfe->lfe_type));
if (lfe->lfe_satconf) {
htsmsg_t *s = htsmsg_create_map();
linuxdvb_satconf_save(lfe->lfe_satconf, s);
@ -956,7 +1188,7 @@ linuxdvb_frontend_save ( linuxdvb_frontend_t *lfe, htsmsg_t *fe )
}
/* Add to list */
snprintf(id, sizeof(id), "%s #%d", dvb_type2str(lfe->lfe_info.type), lfe->lfe_number);
snprintf(id, sizeof(id), "%s #%d", dvb_type2str(lfe->lfe_type), lfe->lfe_number);
htsmsg_add_msg(fe, id, m);
}

View file

@ -72,10 +72,10 @@ const idclass_t linuxdvb_lnb_class =
static uint32_t
linuxdvb_lnb_standard_freq
( linuxdvb_lnb_t *l, linuxdvb_mux_t *lm )
( linuxdvb_lnb_t *l, dvb_mux_t *lm )
{
linuxdvb_lnb_conf_t *lnb = (linuxdvb_lnb_conf_t*)l;
int32_t f = (int32_t)lm->lm_tuning.dmc_fe_params.frequency;
int32_t f = (int32_t)lm->lm_tuning.dmc_fe_freq;
if (lnb->lnb_switch && f > lnb->lnb_switch)
f -= lnb->lnb_high;
else
@ -85,25 +85,25 @@ linuxdvb_lnb_standard_freq
static int
linuxdvb_lnb_standard_band
( linuxdvb_lnb_t *l, linuxdvb_mux_t *lm )
( linuxdvb_lnb_t *l, dvb_mux_t *lm )
{
linuxdvb_lnb_conf_t *lnb = (linuxdvb_lnb_conf_t*)l;
uint32_t f = lm->lm_tuning.dmc_fe_params.frequency;
uint32_t f = lm->lm_tuning.dmc_fe_freq;
return (lnb->lnb_switch && f > lnb->lnb_switch);
}
static int
linuxdvb_lnb_standard_pol
( linuxdvb_lnb_t *l, linuxdvb_mux_t *lm )
( linuxdvb_lnb_t *l, dvb_mux_t *lm )
{
dvb_mux_conf_t *dmc = &lm->lm_tuning;
return dmc->dmc_fe_polarisation == POLARISATION_HORIZONTAL ||
dmc->dmc_fe_polarisation == POLARISATION_CIRCULAR_LEFT;
return dmc->u.dmc_fe_qpsk.polarisation == DVB_POLARISATION_HORIZONTAL ||
dmc->u.dmc_fe_qpsk.polarisation == DVB_POLARISATION_CIRCULAR_LEFT;
}
static int
linuxdvb_lnb_standard_tune
( linuxdvb_diseqc_t *ld, linuxdvb_mux_t *lm, linuxdvb_satconf_ele_t *ls, int fd )
( linuxdvb_diseqc_t *ld, dvb_mux_t *lm, linuxdvb_satconf_ele_t *ls, int fd )
{
int pol = linuxdvb_lnb_standard_pol((linuxdvb_lnb_t*)ld, lm);
return linuxdvb_diseqc_set_volt(fd, pol);
@ -115,13 +115,13 @@ linuxdvb_lnb_standard_tune
static uint32_t
linuxdvb_lnb_bandstack_freq
( linuxdvb_lnb_t *l, linuxdvb_mux_t *lm )
( linuxdvb_lnb_t *l, dvb_mux_t *lm )
{
linuxdvb_lnb_conf_t *lnb = (linuxdvb_lnb_conf_t*)l;
int32_t f = (int32_t)lm->lm_tuning.dmc_fe_params.frequency;
int32_t f = (int32_t)lm->lm_tuning.dmc_fe_freq;
dvb_mux_conf_t *dmc = &lm->lm_tuning;
int pol = dmc->dmc_fe_polarisation == POLARISATION_HORIZONTAL ||
dmc->dmc_fe_polarisation == POLARISATION_CIRCULAR_LEFT;
int pol = dmc->u.dmc_fe_qpsk.polarisation == DVB_POLARISATION_HORIZONTAL ||
dmc->u.dmc_fe_qpsk.polarisation == DVB_POLARISATION_CIRCULAR_LEFT;
if (pol)
f -= lnb->lnb_high;
else
@ -131,24 +131,24 @@ linuxdvb_lnb_bandstack_freq
static int
linuxdvb_lnb_bandstack_band
( linuxdvb_lnb_t *l, linuxdvb_mux_t *lm )
( linuxdvb_lnb_t *l, dvb_mux_t *lm )
{
dvb_mux_conf_t *dmc = &lm->lm_tuning;
int pol = dmc->dmc_fe_polarisation == POLARISATION_HORIZONTAL ||
dmc->dmc_fe_polarisation == POLARISATION_CIRCULAR_LEFT;
int pol = dmc->u.dmc_fe_qpsk.polarisation == DVB_POLARISATION_HORIZONTAL ||
dmc->u.dmc_fe_qpsk.polarisation == DVB_POLARISATION_CIRCULAR_LEFT;
return pol;
}
static int
linuxdvb_lnb_bandstack_pol
( linuxdvb_lnb_t *l, linuxdvb_mux_t *lm )
( linuxdvb_lnb_t *l, dvb_mux_t *lm )
{
return 0;
}
static int
linuxdvb_lnb_bandstack_tune
( linuxdvb_diseqc_t *ld, linuxdvb_mux_t *lm, linuxdvb_satconf_ele_t *ls, int fd )
( linuxdvb_diseqc_t *ld, dvb_mux_t *lm, linuxdvb_satconf_ele_t *ls, int fd )
{
int pol = linuxdvb_lnb_bandstack_pol((linuxdvb_lnb_t*)ld, lm);
return linuxdvb_diseqc_set_volt(fd, pol);

View file

@ -1,695 +0,0 @@
/*
* Tvheadend - Linux DVB Multiplex
*
* Copyright (C) 2013 Adam Sutton
*
* 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 <http://www.gnu.org/licenses/>.
*/
#include "tvheadend.h"
#include "input.h"
#include "linuxdvb_private.h"
#include "queue.h"
#include "settings.h"
#include <sys/types.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <stdlib.h>
#include <dirent.h>
#include <fcntl.h>
#include <math.h>
/* **************************************************************************
* Class definition
* *************************************************************************/
static void
linuxdvb_mux_delete ( mpegts_mux_t *mm, int delconf );
extern const idclass_t mpegts_mux_class;
/*
* Generic
*/
/* Macro to defien mux class str get/set */
#define linuxdvb_mux_class_X(c, f, p, l, ...)\
static const void * \
linuxdvb_mux_##c##_class_##l##_get (void *o)\
{\
static const char *s;\
linuxdvb_mux_t *lm = o;\
s = dvb_##l##2str(lm->lm_tuning.dmc_fe_params.u.f.p);\
return &s;\
}\
static int \
linuxdvb_mux_##c##_class_##l##_set (void *o, const void *v)\
{\
linuxdvb_mux_t *lm = o;\
lm->lm_tuning.dmc_fe_params.u.f.p = dvb_str2##l ((const char*)v);\
return 1;\
}\
static htsmsg_t *\
linuxdvb_mux_##c##_class_##l##_enum (void *o)\
{\
static const int t[] = { __VA_ARGS__ };\
int i;\
htsmsg_t *m = htsmsg_create_list();\
for (i = 0; i < ARRAY_SIZE(t); i++)\
htsmsg_add_str(m, NULL, dvb_##l##2str(t[i]));\
return m;\
}
#define MUX_PROP_STR(_id, _name, t, l, d)\
.type = PT_STR,\
.id = _id,\
.name = _name,\
.get = linuxdvb_mux_##t##_class_##l##_get,\
.set = linuxdvb_mux_##t##_class_##l##_set,\
.list = linuxdvb_mux_##t##_class_##l##_enum,\
.def.s = d
static const void *
linuxdvb_mux_class_delsys_get (void *o)
{
static const char *s;
#if DVB_VER_ATLEAST(5,0)
linuxdvb_mux_t *lm = o;
s = dvb_delsys2str(lm->lm_tuning.dmc_fe_delsys);
#else
s = NULL;
#endif
return &s;
}
static int
linuxdvb_mux_class_delsys_set (void *o, const void *v)
{
#if DVB_VER_ATLEAST(5,0)
const char *s = v;
int delsys = dvb_str2delsys(s);
linuxdvb_mux_t *lm = o;
if (delsys != lm->lm_tuning.dmc_fe_delsys) {
lm->lm_tuning.dmc_fe_delsys = dvb_str2delsys(s);
return 1;
}
#endif
return 0;
}
const idclass_t linuxdvb_mux_class =
{
.ic_super = &mpegts_mux_class,
.ic_class = "linuxdvb_mux",
.ic_caption = "Linux DVB Multiplex",
.ic_properties = (const property_t[]){
{}
}
};
/*
* DVB-T
*/
linuxdvb_mux_class_X(dvbt, ofdm, bandwidth, bw,
BANDWIDTH_AUTO
, BANDWIDTH_8_MHZ, BANDWIDTH_7_MHZ, BANDWIDTH_6_MHZ
#if DVB_VER_ATLEAST(5,4)
, BANDWIDTH_5_MHZ
, BANDWIDTH_10_MHZ
, BANDWIDTH_1_712_MHZ
#endif
);
linuxdvb_mux_class_X(dvbt, ofdm, constellation, qam,
QAM_AUTO, QPSK, QAM_16, QAM_64, QAM_256
);
linuxdvb_mux_class_X(dvbt, ofdm, transmission_mode, mode,
TRANSMISSION_MODE_AUTO,
TRANSMISSION_MODE_2K, TRANSMISSION_MODE_8K
#if DVB_VER_ATLEAST(5,4)
, TRANSMISSION_MODE_1K, TRANSMISSION_MODE_16K
, TRANSMISSION_MODE_32K
#endif
);
linuxdvb_mux_class_X(dvbt, ofdm, guard_interval, guard,
GUARD_INTERVAL_AUTO, GUARD_INTERVAL_1_4,
GUARD_INTERVAL_1_8, GUARD_INTERVAL_1_16,
GUARD_INTERVAL_1_32
#if DVB_VER_ATLEAST(5,4)
, GUARD_INTERVAL_1_128, GUARD_INTERVAL_19_128
, GUARD_INTERVAL_19_256
#endif
);
linuxdvb_mux_class_X(dvbt, ofdm, hierarchy_information, hier,
HIERARCHY_AUTO, HIERARCHY_NONE,
HIERARCHY_1, HIERARCHY_2, HIERARCHY_4
);
linuxdvb_mux_class_X(dvbt, ofdm, code_rate_HP, fechi,
FEC_AUTO,
FEC_1_2, FEC_2_3, FEC_3_4, FEC_4_5, FEC_5_6, FEC_7_8
#if DVB_VER_ATLEAST(5,4)
, FEC_3_5
#endif
);
linuxdvb_mux_class_X(dvbt, ofdm, code_rate_LP, feclo,
FEC_AUTO,
FEC_1_2, FEC_2_3, FEC_3_4, FEC_4_5, FEC_5_6, FEC_7_8
#if DVB_VER_ATLEAST(5,4)
, FEC_3_5
#endif
);
#define linuxdvb_mux_dvbt_class_delsys_get linuxdvb_mux_class_delsys_get
#define linuxdvb_mux_dvbt_class_delsys_set linuxdvb_mux_class_delsys_set
static htsmsg_t *
linuxdvb_mux_dvbt_class_delsys_enum (void *o)
{
htsmsg_t *list = htsmsg_create_list();
#if DVB_VER_ATLEAST(5,0)
htsmsg_add_str(list, NULL, dvb_delsys2str(SYS_DVBT));
#endif
#if DVB_VER_ATLEAST(5,4)
htsmsg_add_str(list, NULL, dvb_delsys2str(SYS_DVBT2));
htsmsg_add_str(list, NULL, dvb_delsys2str(SYS_TURBO));
#endif
return list;
}
const idclass_t linuxdvb_mux_dvbt_class =
{
.ic_super = &linuxdvb_mux_class,
.ic_class = "linuxdvb_mux_dvbt",
.ic_caption = "Linux DVB-T Multiplex",
.ic_properties = (const property_t[]){
{
MUX_PROP_STR("delsys", "Delivery System", dvbt, delsys, "DVBT"),
},
{
.type = PT_U32,
.id = "frequency",
.name = "Frequency (Hz)",
.opts = PO_WRONCE,
.off = offsetof(linuxdvb_mux_t, lm_tuning.dmc_fe_params.frequency),
},
{
MUX_PROP_STR("bandwidth", "Bandwidth", dvbt, bw, "AUTO")
},
{
MUX_PROP_STR("constellation", "Constellation", dvbt, qam, "AUTO")
},
{
MUX_PROP_STR("transmission_mode", "Transmission Mode", dvbt, mode, "AUTO")
},
{
MUX_PROP_STR("guard_interval", "Guard Interval", dvbt, guard, "AUTO")
},
{
MUX_PROP_STR("hierarchy", "Hierarchy", dvbt, hier, "AUTO"),
},
{
MUX_PROP_STR("fec_hi", "FEC High", dvbt, fechi, "AUTO"),
},
{
MUX_PROP_STR("fec_lo", "FEC Low", dvbt, feclo, "AUTO"),
},
{}
}
};
/*
* DVB-C
*/
linuxdvb_mux_class_X(dvbc, qam, modulation, qam,
QAM_AUTO, QAM_16, QAM_32, QAM_64, QAM_128, QAM_256
);
linuxdvb_mux_class_X(dvbc, qam, fec_inner, fec,
FEC_AUTO, FEC_NONE,
FEC_1_2, FEC_2_3, FEC_3_4, FEC_4_5, FEC_5_6, FEC_8_9
#if DVB_VER_ATLEAST(5,4)
, FEC_9_10
#endif
);
#define linuxdvb_mux_dvbc_class_delsys_get linuxdvb_mux_class_delsys_get
#define linuxdvb_mux_dvbc_class_delsys_set linuxdvb_mux_class_delsys_set
static htsmsg_t *
linuxdvb_mux_dvbc_class_delsys_enum (void *o)
{
htsmsg_t *list = htsmsg_create_list();
#if DVB_VER_ATLEAST(5,0)
htsmsg_add_str(list, NULL, dvb_delsys2str(SYS_DVBC_ANNEX_AC));
htsmsg_add_str(list, NULL, dvb_delsys2str(SYS_DVBC_ANNEX_B));
#endif
return list;
}
const idclass_t linuxdvb_mux_dvbc_class =
{
.ic_super = &linuxdvb_mux_class,
.ic_class = "linuxdvb_mux_dvbc",
.ic_caption = "Linux DVB-C Multiplex",
.ic_properties = (const property_t[]){
{
MUX_PROP_STR("delsys", "Delivery System", dvbc, delsys, "DVBC_ANNEX_AC"),
},
{
.type = PT_U32,
.id = "frequency",
.name = "Frequency (Hz)",
.opts = PO_WRONCE,
.off = offsetof(linuxdvb_mux_t, lm_tuning.dmc_fe_params.frequency),
},
{
.type = PT_U32,
.id = "symbolrate",
.name = "Symbol Rate (Sym/s)",
.opts = PO_WRONCE,
.off = offsetof(linuxdvb_mux_t, lm_tuning.dmc_fe_params.u.qam.symbol_rate),
},
{
MUX_PROP_STR("constellation", "Constellation", dvbc, qam, "AUTO")
},
{
MUX_PROP_STR("fec", "FEC", dvbc, fec, "AUTO")
},
{}
}
};
linuxdvb_mux_class_X(dvbs, qpsk, fec_inner, fec,
FEC_AUTO, FEC_NONE,
FEC_1_2, FEC_2_3, FEC_3_4, FEC_4_5, FEC_5_6, FEC_7_8,
FEC_8_9
#if DVB_VER_ATLEAST(5,4)
, FEC_3_5, FEC_9_10
#endif
);
static const void *
linuxdvb_mux_dvbs_class_polarity_get (void *o)
{
static const char *s;
linuxdvb_mux_t *lm = o;
s = dvb_pol2str(lm->lm_tuning.dmc_fe_polarisation);
return &s;
}
static int
linuxdvb_mux_dvbs_class_polarity_set (void *o, const void *s)
{
linuxdvb_mux_t *lm = o;
lm->lm_tuning.dmc_fe_polarisation = dvb_str2pol((const char*)s);
return 1;
}
static htsmsg_t *
linuxdvb_mux_dvbs_class_polarity_enum (void *o)
{
htsmsg_t *list = htsmsg_create_list();
htsmsg_add_str(list, NULL, dvb_pol2str(POLARISATION_VERTICAL));
htsmsg_add_str(list, NULL, dvb_pol2str(POLARISATION_HORIZONTAL));
htsmsg_add_str(list, NULL, dvb_pol2str(POLARISATION_CIRCULAR_LEFT));
htsmsg_add_str(list, NULL, dvb_pol2str(POLARISATION_CIRCULAR_RIGHT));
return list;
}
static const void *
linuxdvb_mux_dvbs_class_modulation_get ( void *o )
{
static const char *s;
#if DVB_VER_ATLEAST(5,0)
linuxdvb_mux_t *lm = o;
s = dvb_qam2str(lm->lm_tuning.dmc_fe_modulation);
#endif
return &s;
}
static int
linuxdvb_mux_dvbs_class_modulation_set (void *o, const void *s)
{
#if DVB_VER_ATLEAST(5,0)
int mod = dvb_str2qam(s);
linuxdvb_mux_t *lm = o;
if (mod != lm->lm_tuning.dmc_fe_modulation) {
lm->lm_tuning.dmc_fe_modulation = mod;
return 1;
}
#endif
return 0;
}
static htsmsg_t *
linuxdvb_mux_dvbs_class_modulation_list ( void *o )
{
htsmsg_t *list = htsmsg_create_list();
htsmsg_add_str(list, NULL, dvb_qam2str(QAM_AUTO));
htsmsg_add_str(list, NULL, dvb_qam2str(QPSK));
htsmsg_add_str(list, NULL, dvb_qam2str(QAM_16));
#if DVB_VER_ATLEAST(5,4)
htsmsg_add_str(list, NULL, dvb_qam2str(PSK_8));
htsmsg_add_str(list, NULL, dvb_qam2str(APSK_16));
htsmsg_add_str(list, NULL, dvb_qam2str(APSK_32));
#endif
return list;
}
#if DVB_VER_ATLEAST(5,0)
static const void *
linuxdvb_mux_dvbs_class_rolloff_get ( void *o )
{
static const char *s;
linuxdvb_mux_t *lm = o;
s = dvb_rolloff2str(lm->lm_tuning.dmc_fe_rolloff);
return &s;
}
static int
linuxdvb_mux_dvbs_class_rolloff_set ( void *o, const void *s )
{
linuxdvb_mux_t *lm = o;
lm->lm_tuning.dmc_fe_rolloff = dvb_str2rolloff(s);
return 1;
}
static htsmsg_t *
linuxdvb_mux_dvbs_class_rolloff_list ( void *o )
{
htsmsg_t *list = htsmsg_create_list();
htsmsg_add_str(list, NULL, dvb_rolloff2str(ROLLOFF_35));
// Note: this is a bit naff, as the below values are only relevant
// to S2 muxes, but currently have no way to model that
htsmsg_add_str(list, NULL, dvb_rolloff2str(ROLLOFF_20));
htsmsg_add_str(list, NULL, dvb_rolloff2str(ROLLOFF_25));
htsmsg_add_str(list, NULL, dvb_rolloff2str(ROLLOFF_AUTO));
return list;
}
static const void *
linuxdvb_mux_dvbs_class_pilot_get ( void *o )
{
static const char *s;
linuxdvb_mux_t *lm = o;
s = dvb_pilot2str(lm->lm_tuning.dmc_fe_pilot);
return &s;
}
static int
linuxdvb_mux_dvbs_class_pilot_set ( void *o, const void *s )
{
linuxdvb_mux_t *lm = o;
lm->lm_tuning.dmc_fe_pilot = dvb_str2pilot(s);
return 1;
}
static htsmsg_t *
linuxdvb_mux_dvbs_class_pilot_list ( void *o )
{
htsmsg_t *list = htsmsg_create_list();
htsmsg_add_str(list, NULL, dvb_pilot2str(PILOT_AUTO));
htsmsg_add_str(list, NULL, dvb_pilot2str(PILOT_ON));
htsmsg_add_str(list, NULL, dvb_pilot2str(PILOT_OFF));
return list;
}
#endif
#define linuxdvb_mux_dvbs_class_delsys_get linuxdvb_mux_class_delsys_get
#define linuxdvb_mux_dvbs_class_delsys_set linuxdvb_mux_class_delsys_set
static htsmsg_t *
linuxdvb_mux_dvbs_class_delsys_enum (void *o)
{
htsmsg_t *list = htsmsg_create_list();
#if DVB_VER_ATLEAST(5,0)
htsmsg_add_str(list, NULL, dvb_delsys2str(SYS_DVBS));
htsmsg_add_str(list, NULL, dvb_delsys2str(SYS_DVBS2));
#endif
return list;
}
static const void *
linuxdvb_mux_dvbs_class_orbital_get ( void *o )
{
static char buf[256], *s = buf;
linuxdvb_mux_t *lm = o;
snprintf(buf, sizeof(buf), "%0.1f%c",
lm->lm_tuning.dmc_fe_orbital_pos / 10.0,
lm->lm_tuning.dmc_fe_orbital_dir);
return &s;
}
static int
linuxdvb_mux_dvbs_class_orbital_set ( void *o, const void *s )
{
int pos, save = 0;
char dir;
char *tmp = tvh_strdupa(s);
linuxdvb_mux_t *lm = o;
dir = tmp[strlen(tmp)-1];
tmp[strlen(tmp)-1] = '\0';
pos = (int)floorf(atof(tmp) * 10.0);
if (pos != lm->lm_tuning.dmc_fe_orbital_pos ||
dir != lm->lm_tuning.dmc_fe_orbital_dir) {
lm->lm_tuning.dmc_fe_orbital_pos = pos;
lm->lm_tuning.dmc_fe_orbital_dir = dir;
save = 1;
}
return save;
}
const idclass_t linuxdvb_mux_dvbs_class =
{
.ic_super = &linuxdvb_mux_class,
.ic_class = "linuxdvb_mux_dvbs",
.ic_caption = "Linux DVB-S Multiplex",
.ic_properties = (const property_t[]){
{
MUX_PROP_STR("delsys", "Delivery System", dvbs, delsys, "DVBS"),
},
{
.type = PT_U32,
.id = "frequency",
.name = "Frequency (kHz)",
.opts = PO_WRONCE,
.off = offsetof(linuxdvb_mux_t, lm_tuning.dmc_fe_params.frequency),
},
{
.type = PT_U32,
.id = "symbolrate",
.name = "Symbol Rate (Sym/s)",
.opts = PO_WRONCE,
.off = offsetof(linuxdvb_mux_t, lm_tuning.dmc_fe_params.u.qpsk.symbol_rate),
},
{
MUX_PROP_STR("polarisation", "Polarisation", dvbs, polarity, NULL)
},
{
.type = PT_STR,
.id = "modulation",
.name = "Modulation",
.set = linuxdvb_mux_dvbs_class_modulation_set,
.get = linuxdvb_mux_dvbs_class_modulation_get,
.list = linuxdvb_mux_dvbs_class_modulation_list,
.def.s = "AUTO",
},
{
MUX_PROP_STR("fec", "FEC", dvbs, fec, "AUTO")
},
#if DVB_VER_ATLEAST(5,0)
{
.type = PT_STR,
.id = "rolloff",
.name = "Rolloff",
.set = linuxdvb_mux_dvbs_class_rolloff_set,
.get = linuxdvb_mux_dvbs_class_rolloff_get,
.list = linuxdvb_mux_dvbs_class_rolloff_list,
.def.s = "AUTO"
},
{
.type = PT_STR,
.id = "pilot",
.name = "Pilot",
.opts = PO_ADVANCED,
.set = linuxdvb_mux_dvbs_class_pilot_set,
.get = linuxdvb_mux_dvbs_class_pilot_get,
.list = linuxdvb_mux_dvbs_class_pilot_list,
},
#endif
{
.type = PT_STR,
.id = "orbital",
.name = "Orbital Pos.",
.set = linuxdvb_mux_dvbs_class_orbital_set,
.get = linuxdvb_mux_dvbs_class_orbital_get,
.opts = PO_ADVANCED | PO_RDONLY
},
{}
}
};
#define linuxdvb_mux_atsc_class_delsys_get linuxdvb_mux_class_delsys_get
#define linuxdvb_mux_atsc_class_delsys_set linuxdvb_mux_class_delsys_set
static htsmsg_t *
linuxdvb_mux_atsc_class_delsys_enum (void *o)
{
htsmsg_t *list = htsmsg_create_list();
#if DVB_VER_ATLEAST(5,0)
htsmsg_add_str(list, NULL, dvb_delsys2str(SYS_ATSC));
htsmsg_add_str(list, NULL, dvb_delsys2str(SYS_ATSCMH));
#endif
return list;
}
linuxdvb_mux_class_X(atsc, vsb, modulation, qam,
QAM_AUTO, QAM_256, VSB_8);
const idclass_t linuxdvb_mux_atsc_class =
{
.ic_super = &linuxdvb_mux_class,
.ic_class = "linuxdvb_mux_atsc",
.ic_caption = "Linux ATSC Multiplex",
.ic_properties = (const property_t[]){
{
MUX_PROP_STR("delsys", "Delivery System", atsc, delsys, "ATSC"),
},
{
.type = PT_U32,
.id = "frequency",
.name = "Frequency (kHz)",
.opts = PO_WRONCE,
.off = offsetof(linuxdvb_mux_t, lm_tuning.dmc_fe_params.frequency),
},
{
MUX_PROP_STR("modulation", "Modulation", atsc, qam, "AUTO")
},
{}
}
};
/* **************************************************************************
* Class methods
* *************************************************************************/
static void
linuxdvb_mux_config_save ( mpegts_mux_t *mm )
{
htsmsg_t *c = htsmsg_create_map();
mpegts_mux_save(mm, c);
hts_settings_save(c, "input/linuxdvb/networks/%s/muxes/%s/config",
idnode_uuid_as_str(&mm->mm_network->mn_id),
idnode_uuid_as_str(&mm->mm_id));
htsmsg_destroy(c);
}
static void
linuxdvb_mux_display_name ( mpegts_mux_t *mm, char *buf, size_t len )
{
linuxdvb_mux_t *lm = (linuxdvb_mux_t*)mm;
linuxdvb_network_t *ln = (linuxdvb_network_t*)mm->mm_network;
uint32_t freq = lm->lm_tuning.dmc_fe_params.frequency;
char pol[2] = { 0 };
if (ln->ln_type == FE_QPSK) {
const char *s = dvb_pol2str(lm->lm_tuning.dmc_fe_polarisation);
if (s) pol[0] = *s;
freq /= 1000;
} else {
freq /= 1000;
}
snprintf(buf, len, "%d%s", freq, pol);
}
static void
linuxdvb_mux_create_instances ( mpegts_mux_t *mm )
{
mpegts_network_link_t *mnl;
LIST_FOREACH(mnl, &mm->mm_network->mn_inputs, mnl_mn_link) {
mpegts_input_t *mi = mnl->mnl_input;
if (mi->mi_is_enabled(mi))
mi->mi_create_mux_instance(mi, mm);
}
}
static void
linuxdvb_mux_delete ( mpegts_mux_t *mm, int delconf )
{
/* Remove config */
if (delconf)
hts_settings_remove("input/linuxdvb/networks/%s/muxes/%s",
idnode_uuid_as_str(&mm->mm_network->mn_id),
idnode_uuid_as_str(&mm->mm_id));
/* Delete the mux */
mpegts_mux_delete(mm, delconf);
}
/* **************************************************************************
* Creation/Config
* *************************************************************************/
linuxdvb_mux_t *
linuxdvb_mux_create0
( linuxdvb_network_t *ln,
uint16_t onid, uint16_t tsid, const dvb_mux_conf_t *dmc,
const char *uuid, htsmsg_t *conf )
{
const idclass_t *idc;
mpegts_mux_t *mm;
linuxdvb_mux_t *lm;
htsmsg_t *c, *e;
htsmsg_field_t *f;
/* Class */
if (ln->ln_type == FE_QPSK)
idc = &linuxdvb_mux_dvbs_class;
else if (ln->ln_type == FE_QAM)
idc = &linuxdvb_mux_dvbc_class;
else if (ln->ln_type == FE_OFDM)
idc = &linuxdvb_mux_dvbt_class;
else if (ln->ln_type == FE_ATSC)
idc = &linuxdvb_mux_atsc_class;
else {
tvherror("linuxdvb", "unknown FE type %d", ln->ln_type);
return NULL;
}
/* Create */
if (!(mm = mpegts_mux_create0(calloc(1, sizeof(linuxdvb_mux_t)), idc, uuid,
(mpegts_network_t*)ln, onid, tsid, conf)))
return NULL;
lm = (linuxdvb_mux_t*)mm;
/* Tuning */
if (dmc)
memcpy(&lm->lm_tuning, dmc, sizeof(dvb_mux_conf_t));
/* Callbacks */
lm->mm_delete = linuxdvb_mux_delete;
lm->mm_display_name = linuxdvb_mux_display_name;
lm->mm_config_save = linuxdvb_mux_config_save;
lm->mm_create_instances = linuxdvb_mux_create_instances;
/* Defaults */
lm->lm_tuning.dmc_fe_params.inversion = INVERSION_AUTO;
#if DVB_VER_ATLEAST(5,0)
lm->lm_tuning.dmc_fe_pilot = PILOT_AUTO;
#endif
/* No config */
if (!conf) return lm;
/* Services */
c = hts_settings_load_r(1, "input/linuxdvb/networks/%s/muxes/%s/services",
idnode_uuid_as_str(&ln->mn_id),
idnode_uuid_as_str(&mm->mm_id));
if (c) {
HTSMSG_FOREACH(f, c) {
if (!(e = htsmsg_get_map_by_field(f))) continue;
(void)linuxdvb_service_create0(lm, 0, 0, f->hmf_name, e);
}
htsmsg_destroy(c);
}
return lm;
}

View file

@ -1,424 +0,0 @@
/*
* Tvheadend - Linux DVB Network
*
* Copyright (C) 2013 Adam Sutton
*
* 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 <http://www.gnu.org/licenses/>.
*/
#include "tvheadend.h"
#include "input.h"
#include "linuxdvb_private.h"
#include "queue.h"
#include "settings.h"
#include "scanfile.h"
#include <sys/types.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <stdlib.h>
#include <dirent.h>
#include <fcntl.h>
static mpegts_mux_t *
linuxdvb_network_find_mux
( linuxdvb_network_t *ln, dvb_mux_conf_t *dmc );
/* ****************************************************************************
* Class definition
* ***************************************************************************/
extern const idclass_t mpegts_network_class;
static void
linuxdvb_network_class_delete ( idnode_t *in )
{
mpegts_network_t *mn = (mpegts_network_t*)in;
/* remove config */
hts_settings_remove("input/linuxdvb/networks/%s",
idnode_uuid_as_str(in));
/* Parent delete */
mpegts_network_delete(mn, 1);
}
static const void *
linuxdvb_network_class_scanfile_get ( void *o )
{
static const char *s = NULL;
return &s;
}
static int
linuxdvb_network_class_scanfile_set ( void *o, const void *s )
{
dvb_mux_conf_t *dmc;
scanfile_network_t *sfn;
mpegts_mux_t *mm;
/* Find */
if (!s)
return 0;
if (!(sfn = scanfile_find(s)))
return 0;
/* Create */
LIST_FOREACH(dmc, &sfn->sfn_muxes, dmc_link) {
if (!(mm = linuxdvb_network_find_mux(o, dmc))) {
mm = (mpegts_mux_t*)linuxdvb_mux_create0(o,
MPEGTS_ONID_NONE,
MPEGTS_TSID_NONE,
dmc, NULL, NULL);
if (mm)
mm->mm_config_save(mm);
}
}
return 0;
}
static htsmsg_t *
linuxdvb_network_class_scanfile_list ( const char *type )
{
htsmsg_t *e, *m = htsmsg_create_map();
htsmsg_add_str(m, "type", "api");
htsmsg_add_str(m, "uri", "linuxdvb/scanfile/list");
e = htsmsg_create_map();
htsmsg_add_str(e, "type", type);
htsmsg_add_msg(m, "params", e);
return m;
}
static htsmsg_t *
linuxdvb_network_dvbt_class_scanfile_list ( void *o )
{
return linuxdvb_network_class_scanfile_list("dvbt");
}
static htsmsg_t *
linuxdvb_network_dvbc_class_scanfile_list ( void *o )
{
return linuxdvb_network_class_scanfile_list("dvbc");
}
static htsmsg_t *
linuxdvb_network_dvbs_class_scanfile_list ( void *o )
{
return linuxdvb_network_class_scanfile_list("dvbs");
}
static htsmsg_t *
linuxdvb_network_atsc_class_scanfile_list ( void *o )
{
return linuxdvb_network_class_scanfile_list("atsc");
}
const idclass_t linuxdvb_network_class =
{
.ic_super = &mpegts_network_class,
.ic_class = "linuxdvb_network",
.ic_caption = "LinuxDVB Network",
.ic_delete = linuxdvb_network_class_delete,
.ic_properties = (const property_t[]){
{}
}
};
const idclass_t linuxdvb_network_dvbt_class =
{
.ic_super = &linuxdvb_network_class,
.ic_class = "linuxdvb_network_dvbt",
.ic_caption = "DVB-T Network",
.ic_properties = (const property_t[]) {
{
.type = PT_STR,
.id = "scanfile",
.name = "Pre-defined Muxes",
.set = linuxdvb_network_class_scanfile_set,
.get = linuxdvb_network_class_scanfile_get,
.list = linuxdvb_network_dvbt_class_scanfile_list,
.opts = PO_NOSAVE,
},
{}
}
};
const idclass_t linuxdvb_network_dvbc_class =
{
.ic_super = &linuxdvb_network_class,
.ic_class = "linuxdvb_network_dvbc",
.ic_caption = "DVB-C Network",
.ic_properties = (const property_t[]) {
{
.type = PT_STR,
.id = "scanfile",
.name = "Pre-defined Muxes",
.set = linuxdvb_network_class_scanfile_set,
.get = linuxdvb_network_class_scanfile_get,
.list = linuxdvb_network_dvbc_class_scanfile_list,
.opts = PO_NOSAVE,
},
{}
}
};
const idclass_t linuxdvb_network_dvbs_class =
{
.ic_super = &linuxdvb_network_class,
.ic_class = "linuxdvb_network_dvbs",
.ic_caption = "DVB-S Network",
.ic_properties = (const property_t[]) {
{
.type = PT_STR,
.id = "scanfile",
.name = "Pre-defined Muxes",
.set = linuxdvb_network_class_scanfile_set,
.get = linuxdvb_network_class_scanfile_get,
.list = linuxdvb_network_dvbs_class_scanfile_list,
.opts = PO_NOSAVE,
},
{}
}
};
const idclass_t linuxdvb_network_atsc_class =
{
.ic_super = &linuxdvb_network_class,
.ic_class = "linuxdvb_network_atsc",
.ic_caption = "ATSC Network",
.ic_properties = (const property_t[]) {
{
.type = PT_STR,
.id = "scanfile",
.name = "Pre-defined Muxes",
.set = linuxdvb_network_class_scanfile_set,
.get = linuxdvb_network_class_scanfile_get,
.list = linuxdvb_network_atsc_class_scanfile_list,
.opts = PO_NOSAVE,
},
{}
}
};
/* ****************************************************************************
* Class methods
* ***************************************************************************/
static mpegts_mux_t *
linuxdvb_network_find_mux
( linuxdvb_network_t *ln, dvb_mux_conf_t *dmc )
{
mpegts_mux_t *mm;
LIST_FOREACH(mm, &ln->mn_muxes, mm_network_link) {
linuxdvb_mux_t *lm = (linuxdvb_mux_t*)mm;
if (abs(lm->lm_tuning.dmc_fe_params.frequency
- dmc->dmc_fe_params.frequency) > LINUXDVB_FREQ_TOL) continue;
if (lm->lm_tuning.dmc_fe_polarisation != dmc->dmc_fe_polarisation) continue;
break;
}
return mm;
}
static void
linuxdvb_network_config_save ( mpegts_network_t *mn )
{
htsmsg_t *c = htsmsg_create_map();
idnode_save(&mn->mn_id, c);
htsmsg_add_str(c, "class", mn->mn_id.in_class->ic_class);
hts_settings_save(c, "input/linuxdvb/networks/%s/config",
idnode_uuid_as_str(&mn->mn_id));
htsmsg_destroy(c);
}
static mpegts_mux_t *
linuxdvb_network_create_mux
( mpegts_mux_t *mm, uint16_t onid, uint16_t tsid, dvb_mux_conf_t *dmc )
{
int save = 0;
linuxdvb_network_t *ln = (linuxdvb_network_t*)mm->mm_network;
mm = linuxdvb_network_find_mux(ln, dmc);
if (!mm && ln->mn_autodiscovery) {
mm = (mpegts_mux_t*)linuxdvb_mux_create0(ln, onid, tsid, dmc, NULL, NULL);
save = 1;
} else if (mm) {
linuxdvb_mux_t *lm = (linuxdvb_mux_t*)mm;
dmc->dmc_fe_params.frequency = lm->lm_tuning.dmc_fe_params.frequency;
// Note: keep original freq, else it can bounce around if diff transponders
// report it slightly differently.
// TODO: Note: should we also leave AUTO settings as is?
if (memcmp(&lm->lm_tuning, dmc, sizeof(lm->lm_tuning))) {
memcpy(&lm->lm_tuning, dmc, sizeof(lm->lm_tuning));
save = 1;
}
}
if (save)
mm->mm_config_save(mm);
return mm;
}
static mpegts_service_t *
linuxdvb_network_create_service
( mpegts_mux_t *mm, uint16_t sid, uint16_t pmt_pid )
{
return linuxdvb_service_create0((linuxdvb_mux_t*)mm, sid,
pmt_pid, NULL, NULL);
}
static const idclass_t *
linuxdvb_network_mux_class
( mpegts_network_t *mn )
{
extern const idclass_t linuxdvb_mux_dvbt_class;
extern const idclass_t linuxdvb_mux_dvbc_class;
extern const idclass_t linuxdvb_mux_dvbs_class;
extern const idclass_t linuxdvb_mux_atsc_class;
if (idnode_is_instance(&mn->mn_id, &linuxdvb_network_dvbt_class))
return &linuxdvb_mux_dvbt_class;
if (idnode_is_instance(&mn->mn_id, &linuxdvb_network_dvbc_class))
return &linuxdvb_mux_dvbc_class;
if (idnode_is_instance(&mn->mn_id, &linuxdvb_network_dvbs_class))
return &linuxdvb_mux_dvbs_class;
if (idnode_is_instance(&mn->mn_id, &linuxdvb_network_atsc_class))
return &linuxdvb_mux_atsc_class;
return NULL;
}
static mpegts_mux_t *
linuxdvb_network_mux_create2
( mpegts_network_t *mn, htsmsg_t *conf )
{
linuxdvb_network_t *ln = (linuxdvb_network_t*)mn;
return (mpegts_mux_t*)
linuxdvb_mux_create0(ln, MPEGTS_ONID_NONE, MPEGTS_TSID_NONE,
NULL, NULL, conf);
}
/* ****************************************************************************
* Creation/Config
* ***************************************************************************/
linuxdvb_network_t *
linuxdvb_network_create0
( const char *uuid, const idclass_t *idc, htsmsg_t *conf )
{
linuxdvb_network_t *ln;
htsmsg_t *c, *e;
htsmsg_field_t *f;
ln = calloc(1, sizeof(linuxdvb_network_t));
if (idc == &linuxdvb_network_dvbt_class)
ln->ln_type = FE_OFDM;
else if (idc == &linuxdvb_network_dvbc_class)
ln->ln_type = FE_QAM;
else if (idc == &linuxdvb_network_dvbs_class)
ln->ln_type = FE_QPSK;
else
ln->ln_type = FE_ATSC;
/* Create */
if (!(ln = (linuxdvb_network_t*)mpegts_network_create0((void*)ln,
idc, uuid, NULL, conf)))
return NULL;
/* Callbacks */
ln->mn_create_mux = linuxdvb_network_create_mux;
ln->mn_create_service = linuxdvb_network_create_service;
ln->mn_config_save = linuxdvb_network_config_save;
ln->mn_mux_class = linuxdvb_network_mux_class;
ln->mn_mux_create2 = linuxdvb_network_mux_create2;
/* No config */
if (!conf)
return ln;
/* Load muxes */
if ((c = hts_settings_load_r(1, "input/linuxdvb/networks/%s/muxes", uuid))) {
HTSMSG_FOREACH(f, c) {
if (!(e = htsmsg_get_map_by_field(f))) continue;
if (!(e = htsmsg_get_map(e, "config"))) continue;
(void)linuxdvb_mux_create1(ln, f->hmf_name, e);
}
htsmsg_destroy(c);
}
return ln;
}
static mpegts_network_t *
linuxdvb_network_builder
( const idclass_t *idc, htsmsg_t *conf )
{
return (mpegts_network_t*)linuxdvb_network_create0(NULL, idc, conf);
}
static const idclass_t* linuxdvb_network_classes[] = {
&linuxdvb_network_dvbt_class,
&linuxdvb_network_dvbc_class,
&linuxdvb_network_dvbs_class,
&linuxdvb_network_atsc_class,
};
void linuxdvb_network_init ( void )
{
htsmsg_t *c, *e;
htsmsg_field_t *f;
const char *s;
int i;
/* Register class builders */
for (i = 0; i < ARRAY_SIZE(linuxdvb_network_classes); i++)
mpegts_network_register_builder(linuxdvb_network_classes[i],
linuxdvb_network_builder);
/* Load settings */
if (!(c = hts_settings_load_r(1, "input/linuxdvb/networks")))
return;
HTSMSG_FOREACH(f, c) {
if (!(e = htsmsg_get_map_by_field(f))) continue;
if (!(e = htsmsg_get_map(e, "config"))) continue;
if (!(s = htsmsg_get_str(e, "class"))) continue;
for (i = 0; i < ARRAY_SIZE(linuxdvb_network_classes); i++) {
if(!strcmp(linuxdvb_network_classes[i]->ic_class, s)) {
(void)linuxdvb_network_create0(f->hmf_name, linuxdvb_network_classes[i], e);
break;
}
}
}
htsmsg_destroy(c);
}
void linuxdvb_network_done ( void )
{
int i;
pthread_mutex_lock(&global_lock);
/* Unregister class builders */
for (i = 0; i < ARRAY_SIZE(linuxdvb_network_classes); i++) {
mpegts_network_unregister_builder(linuxdvb_network_classes[i]);
mpegts_network_class_delete(linuxdvb_network_classes[i], 0);
}
pthread_mutex_unlock(&global_lock);
}
/* ****************************************************************************
* Search
* ***************************************************************************/
linuxdvb_network_t*
linuxdvb_network_find_by_uuid(const char *uuid)
{
idnode_t *in = idnode_find(uuid, &linuxdvb_network_class);
return (linuxdvb_network_t*)in;
}
/******************************************************************************
* Editor Configuration
*
* vim:sts=2:ts=2:sw=2:et
*****************************************************************************/

View file

@ -20,7 +20,14 @@
#ifndef __TVH_LINUXDVB_PRIVATE_H__
#define __TVH_LINUXDVB_PRIVATE_H__
#include "input/mpegts.h"
#include "input.h"
#include <linux/dvb/version.h>
#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))
/* Max allowed frequency variation for something to be considered the same */
#define LINUXDVB_FREQ_TOL 2000
@ -33,7 +40,6 @@ typedef struct linuxdvb_satconf_ele linuxdvb_satconf_ele_t;
typedef struct linuxdvb_diseqc linuxdvb_diseqc_t;
typedef struct linuxdvb_lnb linuxdvb_lnb_t;
typedef struct linuxdvb_network linuxdvb_network_t;
typedef struct linuxdvb_mux linuxdvb_mux_t;
typedef struct linuxdvb_en50494 linuxdvb_en50494_t;
typedef LIST_HEAD(,linuxdvb_hardware) linuxdvb_hardware_list_t;
@ -75,7 +81,8 @@ struct linuxdvb_frontend
* Frontend info
*/
int lfe_number;
struct dvb_frontend_info lfe_info;
dvb_fe_type_t lfe_type;
char lfe_name[128];
char *lfe_fe_path;
char *lfe_dmx_path;
char *lfe_dvr_path;
@ -93,7 +100,7 @@ struct linuxdvb_frontend
* Tuning
*/
int lfe_locked;
fe_status_t lfe_status;
int lfe_status;
time_t lfe_monitor;
gtimer_t lfe_monitor_timer;
@ -139,31 +146,36 @@ struct linuxdvb_satconf
};
/*
* Internal wrapper for a satconf entry
*
* Note: this is a bit cumbersome, it comes from how I first did the satconf
* and was subsequently bullied (by amet) into changing it (probably
* for the better, just don't tell him, no danger he'll read this!)
*
* maybe one day I'll do it again properly
* Elementary satconf entry
*/
struct linuxdvb_satconf_ele
{
mpegts_input_t; // This acts as proxy for the frontend
idnode_t lse_id;
/*
* Parent
*/
linuxdvb_satconf_t *ls_parent;
TAILQ_ENTRY(linuxdvb_satconf_ele) ls_link;
linuxdvb_satconf_t *lse_parent;
TAILQ_ENTRY(linuxdvb_satconf_ele) lse_link;
/*
* Config
*/
int lse_enabled;
int lse_priority;
char *lse_name;
/*
* Assigned networks to this SAT configuration
*/
idnode_set_t *lse_networks;
/*
* Diseqc kit
*/
linuxdvb_lnb_t *ls_lnb;
linuxdvb_diseqc_t *ls_switch;
linuxdvb_diseqc_t *ls_rotor;
linuxdvb_diseqc_t *ls_en50494;
linuxdvb_lnb_t *lse_lnb;
linuxdvb_diseqc_t *lse_switch;
linuxdvb_diseqc_t *lse_rotor;
linuxdvb_diseqc_t *lse_en50494;
};
struct linuxdvb_diseqc
@ -171,17 +183,17 @@ struct linuxdvb_diseqc
idnode_t ld_id;
const char *ld_type;
linuxdvb_satconf_ele_t *ld_satconf;
int (*ld_grace) (linuxdvb_diseqc_t *ld, linuxdvb_mux_t *lm);
int (*ld_tune) (linuxdvb_diseqc_t *ld, linuxdvb_mux_t *lm,
int (*ld_grace) (linuxdvb_diseqc_t *ld, dvb_mux_t *lm);
int (*ld_tune) (linuxdvb_diseqc_t *ld, dvb_mux_t *lm,
linuxdvb_satconf_ele_t *ls, int fd);
};
struct linuxdvb_lnb
{
linuxdvb_diseqc_t;
uint32_t (*lnb_freq)(linuxdvb_lnb_t*, linuxdvb_mux_t*);
int (*lnb_band)(linuxdvb_lnb_t*, linuxdvb_mux_t*);
int (*lnb_pol) (linuxdvb_lnb_t*, linuxdvb_mux_t*);
uint32_t (*lnb_freq)(linuxdvb_lnb_t*, dvb_mux_t*);
int (*lnb_band)(linuxdvb_lnb_t*, dvb_mux_t*);
int (*lnb_pol) (linuxdvb_lnb_t*, dvb_mux_t*);
};
struct linuxdvb_en50494
@ -218,7 +230,7 @@ linuxdvb_frontend_t *
linuxdvb_frontend_create
( htsmsg_t *conf, linuxdvb_adapter_t *la, int number,
const char *fe_path, const char *dmx_path, const char *dvr_path,
struct dvb_frontend_info *dfi );
dvb_fe_type_t type, const char *name );
void linuxdvb_frontend_save ( linuxdvb_frontend_t *lfe, htsmsg_t *m );
@ -232,52 +244,6 @@ int linuxdvb_frontend_tune0
int linuxdvb_frontend_tune1
( linuxdvb_frontend_t *lfe, mpegts_mux_instance_t *mmi, uint32_t freq );
/*
* Network
*/
struct linuxdvb_network
{
mpegts_network_t;
/*
* Network type
*/
fe_type_t ln_type;
};
void linuxdvb_network_init ( void );
void linuxdvb_network_done ( void );
linuxdvb_network_t *linuxdvb_network_find_by_uuid(const char *uuid);
linuxdvb_network_t *linuxdvb_network_create0
( const char *uuid, const idclass_t *idc, htsmsg_t *conf );
struct linuxdvb_mux
{
mpegts_mux_t;
/*
* Tuning information
*/
dvb_mux_conf_t lm_tuning;
};
linuxdvb_mux_t *linuxdvb_mux_create0
(linuxdvb_network_t *ln, uint16_t onid, uint16_t tsid,
const dvb_mux_conf_t *dmc, const char *uuid, htsmsg_t *conf);
#define linuxdvb_mux_create1(n, u, c)\
linuxdvb_mux_create0(n, MPEGTS_ONID_NONE, MPEGTS_TSID_NONE,\
NULL, u, c)
/*
* Service
*/
mpegts_service_t *linuxdvb_service_create0
(linuxdvb_mux_t *lm, uint16_t sid, uint16_t pmt_pid,
const char *uuid, htsmsg_t *conf);
/*
* Diseqc gear
*/
@ -338,4 +304,15 @@ linuxdvb_satconf_t *linuxdvb_satconf_create
void linuxdvb_satconf_delete ( linuxdvb_satconf_t *ls, int delconf );
int linuxdvb_satconf_get_priority
( linuxdvb_satconf_t *ls, mpegts_mux_t *mm );
int linuxdvb_satconf_get_grace
( linuxdvb_satconf_t *ls, mpegts_mux_t *mm );
void linuxdvb_satconf_post_stop_mux( linuxdvb_satconf_t *ls );
int linuxdvb_satconf_start_mux
( linuxdvb_satconf_t *ls, mpegts_mux_instance_t *mmi );
#endif /* __TVH_LINUXDVB_PRIVATE_H__ */

View file

@ -28,6 +28,7 @@
#include <fcntl.h>
#include <assert.h>
#include <math.h>
#include <linux/dvb/frontend.h>
/* **************************************************************************
* Class definition
@ -131,10 +132,10 @@ const idclass_t linuxdvb_rotor_usals_class =
/* GotoX */
static int
linuxdvb_rotor_gotox_tune
( linuxdvb_rotor_t *lr, linuxdvb_mux_t *lm, linuxdvb_satconf_ele_t *ls, int fd )
( linuxdvb_rotor_t *lr, dvb_mux_t *lm, linuxdvb_satconf_ele_t *ls, int fd )
{
int i;
for (i = 0; i <= ls->ls_parent->ls_diseqc_repeats; i++) {
for (i = 0; i <= ls->lse_parent->ls_diseqc_repeats; i++) {
if (linuxdvb_diseqc_send(fd, 0xE0, 0x31, 0x6B, 1, (int)lr->lr_position)) {
tvherror("diseqc", "failed to set GOTOX pos %d", lr->lr_position);
return -1;
@ -149,7 +150,7 @@ linuxdvb_rotor_gotox_tune
/* USALS */
static int
linuxdvb_rotor_usals_tune
( linuxdvb_rotor_t *lr, linuxdvb_mux_t *lm, linuxdvb_satconf_ele_t *ls, int fd )
( linuxdvb_rotor_t *lr, dvb_mux_t *lm, linuxdvb_satconf_ele_t *ls, int fd )
{
/*
* Code originally written in PR #238 by Jason Millard jsm174
@ -202,7 +203,7 @@ linuxdvb_rotor_usals_tune
fabs(pos), (pos > 0.0) ? 'E' : 'W',
motor_angle, (motor_angle > 0.0) ? "counter-" : "");
for (i = 0; i <= ls->ls_parent->ls_diseqc_repeats; i++) {
for (i = 0; i <= ls->lse_parent->ls_diseqc_repeats; i++) {
if (linuxdvb_diseqc_send(fd, 0xE0, 0x31, 0x6E, 2, angle_1, angle_2)) {
tvherror("diseqc", "failed to send USALS command");
return -1;
@ -218,7 +219,7 @@ linuxdvb_rotor_usals_tune
static int
linuxdvb_rotor_tune
( linuxdvb_diseqc_t *ld, linuxdvb_mux_t *lm, linuxdvb_satconf_ele_t *ls, int fd )
( linuxdvb_diseqc_t *ld, dvb_mux_t *lm, linuxdvb_satconf_ele_t *ls, int fd )
{
linuxdvb_rotor_t *lr = (linuxdvb_rotor_t*)ld;
@ -239,7 +240,7 @@ linuxdvb_rotor_tune
static int
linuxdvb_rotor_grace
( linuxdvb_diseqc_t *ld, linuxdvb_mux_t *lm )
( linuxdvb_diseqc_t *ld, dvb_mux_t *lm )
{
return 120; // TODO: calculate approx period
}

File diff suppressed because it is too large Load diff

View file

@ -1,57 +0,0 @@
/*
* Tvheadend - Linux DVB Service
*
* Copyright (C) 2013 Adam Sutton
*
* 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 <http://www.gnu.org/licenses/>.
*/
#include "tvheadend.h"
#include "input.h"
#include "linuxdvb_private.h"
#include "queue.h"
#include "settings.h"
#include <sys/types.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <stdlib.h>
#include <dirent.h>
#include <fcntl.h>
static void
linuxdvb_service_config_save ( service_t *t )
{
htsmsg_t *c = htsmsg_create_map();
mpegts_service_t *s = (mpegts_service_t*)t;
mpegts_service_save(s, c);
hts_settings_save(c, "input/linuxdvb/networks/%s/muxes/%s/services/%s",
idnode_uuid_as_str(&s->s_dvb_mux->mm_network->mn_id),
idnode_uuid_as_str(&s->s_dvb_mux->mm_id),
idnode_uuid_as_str(&s->s_id));
htsmsg_destroy(c);
}
mpegts_service_t *
linuxdvb_service_create0
( linuxdvb_mux_t *mm, uint16_t sid, uint16_t pmt_pid,
const char *uuid, htsmsg_t *conf )
{
extern const idclass_t mpegts_service_class;
mpegts_service_t *s
= mpegts_service_create1(uuid, (mpegts_mux_t*)mm, sid, pmt_pid, conf);
if (s)
s->s_config_save = linuxdvb_service_config_save;
return s;
}

View file

@ -28,6 +28,7 @@
#include <fcntl.h>
#include <assert.h>
#include <linux/dvb/dmx.h>
#include <linux/dvb/frontend.h>
/* **************************************************************************
* Class definition
@ -112,15 +113,15 @@ const idclass_t linuxdvb_switch_class =
static int
linuxdvb_switch_tune
( linuxdvb_diseqc_t *ld, linuxdvb_mux_t *lm, linuxdvb_satconf_ele_t *sc, int fd )
( linuxdvb_diseqc_t *ld, dvb_mux_t *lm, linuxdvb_satconf_ele_t *sc, int fd )
{
int i, com, r1 = 0, r2 = 0;
int pol, band;
linuxdvb_switch_t *ls = (linuxdvb_switch_t*)ld;
/* LNB settings */
pol = (sc->ls_lnb) ? sc->ls_lnb->lnb_pol (sc->ls_lnb, lm) & 0x1 : 0;
band = (sc->ls_lnb) ? sc->ls_lnb->lnb_band(sc->ls_lnb, lm) & 0x1 : 0;
pol = (sc->lse_lnb) ? sc->lse_lnb->lnb_pol (sc->lse_lnb, lm) & 0x1 : 0;
band = (sc->lse_lnb) ? sc->lse_lnb->lnb_band(sc->lse_lnb, lm) & 0x1 : 0;
/* Set the voltage */
if (linuxdvb_diseqc_set_volt(fd, pol))
@ -130,7 +131,7 @@ linuxdvb_switch_tune
com = 0xF0 | (ls->ls_committed << 2) | (pol << 1) | band;
/* Single committed (before repeats) */
if (sc->ls_parent->ls_diseqc_repeats > 0) {
if (sc->lse_parent->ls_diseqc_repeats > 0) {
r2 = 1;
if (linuxdvb_diseqc_send(fd, 0xE0, 0x10, 0x38, 1, com))
return -1;
@ -138,7 +139,7 @@ linuxdvb_switch_tune
}
/* Repeats */
for (i = 0; i <= sc->ls_parent->ls_diseqc_repeats; i++) {
for (i = 0; i <= sc->lse_parent->ls_diseqc_repeats; i++) {
/* Uncommitted */
if (linuxdvb_diseqc_send(fd, 0xE0 | r1, 0x10, 0x39, 1,

View file

@ -0,0 +1,74 @@
/*
* Tvheadend - MPEGTS DVB support routines and defines
* Copyright (C) 2013 Adam Sutton
* Copyright (C) 2014 Jaroslav Kysela
*
* 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 <http://www.gnu.org/licenses/>.
*/
#ifndef __TVH_MPEGTS_DVB_H__
#define __TVH_MPEGTS_DVB_H__
/*
* Network
*/
typedef struct dvb_network
{
mpegts_network_t;
/*
* Network type
*/
dvb_fe_type_t ln_type;
} dvb_network_t;
extern const idclass_t dvb_network_dvbt_class;
extern const idclass_t dvb_network_dvbc_class;
extern const idclass_t dvb_network_dvbs_class;
extern const idclass_t dvb_network_atsc_class;
void dvb_network_init ( void );
void dvb_network_done ( void );
dvb_network_t *dvb_network_find_by_uuid(const char *uuid);
dvb_network_t *dvb_network_create0
( const char *uuid, const idclass_t *idc, htsmsg_t *conf );
/*
*
*/
typedef struct dvb_mux
{
mpegts_mux_t;
/*
* Tuning information
*/
dvb_mux_conf_t lm_tuning;
} dvb_mux_t;
extern const idclass_t dvb_mux_dvbt_class;
extern const idclass_t dvb_mux_dvbc_class;
extern const idclass_t dvb_mux_dvbs_class;
extern const idclass_t dvb_mux_atsc_class;
dvb_mux_t *dvb_mux_create0
(dvb_network_t *ln, uint16_t onid, uint16_t tsid,
const dvb_mux_conf_t *dmc, const char *uuid, htsmsg_t *conf);
#define dvb_mux_create1(n, u, c)\
dvb_mux_create0(n, MPEGTS_ONID_NONE, MPEGTS_TSID_NONE, NULL, u, c)
#endif /* __TVH_MPEGTS_DVB_H__ */

View file

@ -16,7 +16,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "input/mpegts.h"
#include "input.h"
#include "tsdemux.h"
#include "packet.h"
#include "streaming.h"
@ -197,7 +197,7 @@ mpegts_input_get_weight ( mpegts_input_t *mi )
}
int
mpegts_input_get_priority ( mpegts_input_t *mi )
mpegts_input_get_priority ( mpegts_input_t *mi, mpegts_mux_t *mm )
{
return mi->mi_priority;
}
@ -839,7 +839,7 @@ mpegts_input_set_networks ( mpegts_input_t *mi, htsmsg_t *msg )
htsmsg_field_t *f;
mpegts_network_t *mn;
mpegts_network_link_t *mnl, *nxt;
/* Mark for deletion */
LIST_FOREACH(mnl, &mi->mi_networks, mnl_mi_link)
mnl->mnl_mark = 1;

View file

@ -19,7 +19,7 @@
#include "idnode.h"
#include "queue.h"
#include "input/mpegts.h"
#include "input.h"
#include "subscriptions.h"
#include "dvb_charset.h"

View file

@ -0,0 +1,698 @@
/*
* Tvheadend - Linux DVB Multiplex
*
* Copyright (C) 2013 Adam Sutton
*
* 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 <http://www.gnu.org/licenses/>.
*/
#include "tvheadend.h"
#include "input.h"
#include "mpegts_dvb.h"
#include "queue.h"
#include "settings.h"
#include <sys/types.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <stdlib.h>
#include <dirent.h>
#include <fcntl.h>
#include <math.h>
/* **************************************************************************
* Class definition
* *************************************************************************/
static void
dvb_mux_delete ( mpegts_mux_t *mm, int delconf );
extern const idclass_t mpegts_mux_class;
/*
* Generic
*/
/* Macro to define mux class str get/set */
#define dvb_mux_class_R(c, f, l, ...)\
static const void * \
dvb_mux_##c##_class_##l##_get (void *o)\
{\
static const char *s;\
dvb_mux_t *lm = o;\
s = dvb_##l##2str(lm->lm_tuning.dmc_fe_##f);\
return &s;\
}\
static int \
dvb_mux_##c##_class_##l##_set (void *o, const void *v)\
{\
dvb_mux_t *lm = o;\
lm->lm_tuning.dmc_fe_##f = dvb_str2##l ((const char*)v);\
return 1;\
}\
static htsmsg_t *\
dvb_mux_##c##_class_##l##_enum (void *o)\
{\
static const int t[] = { __VA_ARGS__ };\
int i;\
htsmsg_t *m = htsmsg_create_list();\
for (i = 0; i < ARRAY_SIZE(t); i++)\
htsmsg_add_str(m, NULL, dvb_##l##2str(t[i]));\
return m;\
}
#define dvb_mux_class_X(c, f, p, l, ...)\
static const void * \
dvb_mux_##c##_class_##l##_get (void *o)\
{\
static const char *s;\
dvb_mux_t *lm = o;\
s = dvb_##l##2str(lm->lm_tuning.u.dmc_fe_##f.p);\
return &s;\
}\
static int \
dvb_mux_##c##_class_##l##_set (void *o, const void *v)\
{\
dvb_mux_t *lm = o;\
lm->lm_tuning.u.dmc_fe_##f.p = dvb_str2##l ((const char*)v);\
return 1;\
}\
static htsmsg_t *\
dvb_mux_##c##_class_##l##_enum (void *o)\
{\
static const int t[] = { __VA_ARGS__ };\
int i;\
htsmsg_t *m = htsmsg_create_list();\
for (i = 0; i < ARRAY_SIZE(t); i++)\
htsmsg_add_str(m, NULL, dvb_##l##2str(t[i]));\
return m;\
}
#define MUX_PROP_STR(_id, _name, t, l, d)\
.type = PT_STR,\
.id = _id,\
.name = _name,\
.get = dvb_mux_##t##_class_##l##_get,\
.set = dvb_mux_##t##_class_##l##_set,\
.list = dvb_mux_##t##_class_##l##_enum,\
.def.s = d
static const void *
dvb_mux_class_delsys_get (void *o)
{
static const char *s;
dvb_mux_t *lm = o;
s = dvb_delsys2str(lm->lm_tuning.dmc_fe_delsys);
return &s;
}
static int
dvb_mux_class_delsys_set (void *o, const void *v)
{
const char *s = v;
int delsys = dvb_str2delsys(s);
dvb_mux_t *lm = o;
if (delsys != lm->lm_tuning.dmc_fe_delsys) {
lm->lm_tuning.dmc_fe_delsys = dvb_str2delsys(s);
return 1;
}
return 0;
}
const idclass_t dvb_mux_class =
{
.ic_super = &mpegts_mux_class,
.ic_class = "dvb_mux",
.ic_caption = "Linux DVB Multiplex",
.ic_properties = (const property_t[]){
{}
}
};
/*
* DVB-T
*/
dvb_mux_class_X(dvbt, ofdm, bandwidth, bw,
DVB_BANDWIDTH_AUTO, DVB_BANDWIDTH_10_MHZ,
DVB_BANDWIDTH_8_MHZ, DVB_BANDWIDTH_7_MHZ,
DVB_BANDWIDTH_6_MHZ, DVB_BANDWIDTH_5_MHZ,
DVB_BANDWIDTH_1_712_MHZ);
dvb_mux_class_R(dvbt, modulation, qam,
DVB_MOD_QAM_AUTO, DVB_MOD_QPSK, DVB_MOD_QAM_16,
DVB_MOD_QAM_64, DVB_MOD_QAM_256);
dvb_mux_class_X(dvbt, ofdm, transmission_mode, mode,
DVB_TRANSMISSION_MODE_AUTO, DVB_TRANSMISSION_MODE_32K,
DVB_TRANSMISSION_MODE_16K, DVB_TRANSMISSION_MODE_8K,
DVB_TRANSMISSION_MODE_2K, DVB_TRANSMISSION_MODE_1K);
dvb_mux_class_X(dvbt, ofdm, guard_interval, guard,
DVB_GUARD_INTERVAL_AUTO, DVB_GUARD_INTERVAL_1_32,
DVB_GUARD_INTERVAL_1_16, DVB_GUARD_INTERVAL_1_8,
DVB_GUARD_INTERVAL_1_4, DVB_GUARD_INTERVAL_1_128,
DVB_GUARD_INTERVAL_19_128, DVB_GUARD_INTERVAL_19_256);
dvb_mux_class_X(dvbt, ofdm, hierarchy_information, hier,
DVB_HIERARCHY_AUTO, DVB_HIERARCHY_NONE,
DVB_HIERARCHY_1, DVB_HIERARCHY_2, DVB_HIERARCHY_4);
dvb_mux_class_X(dvbt, ofdm, code_rate_HP, fechi,
DVB_FEC_AUTO, DVB_FEC_1_2, DVB_FEC_2_3, DVB_FEC_3_4,
DVB_FEC_3_5, DVB_FEC_4_5, DVB_FEC_5_6, DVB_FEC_7_8);
dvb_mux_class_X(dvbt, ofdm, code_rate_LP, feclo,
DVB_FEC_AUTO, DVB_FEC_1_2, DVB_FEC_2_3, DVB_FEC_3_4,
DVB_FEC_3_5, DVB_FEC_4_5, DVB_FEC_5_6, DVB_FEC_7_8);
#define dvb_mux_dvbt_class_delsys_get dvb_mux_class_delsys_get
#define dvb_mux_dvbt_class_delsys_set dvb_mux_class_delsys_set
static htsmsg_t *
dvb_mux_dvbt_class_delsys_enum (void *o)
{
htsmsg_t *list = htsmsg_create_list();
htsmsg_add_str(list, NULL, dvb_delsys2str(DVB_SYS_DVBT));
htsmsg_add_str(list, NULL, dvb_delsys2str(DVB_SYS_DVBT2));
htsmsg_add_str(list, NULL, dvb_delsys2str(DVB_SYS_TURBO));
return list;
}
const idclass_t dvb_mux_dvbt_class =
{
.ic_super = &dvb_mux_class,
.ic_class = "dvb_mux_dvbt",
.ic_caption = "Linux DVB-T Multiplex",
.ic_properties = (const property_t[]){
{
MUX_PROP_STR("delsys", "Delivery System", dvbt, delsys, "DVBT"),
},
{
.type = PT_U32,
.id = "frequency",
.name = "Frequency (Hz)",
.opts = PO_WRONCE,
.off = offsetof(dvb_mux_t, lm_tuning.dmc_fe_freq),
},
{
MUX_PROP_STR("bandwidth", "Bandwidth", dvbt, bw, "AUTO")
},
{
MUX_PROP_STR("constellation", "Constellation", dvbt, qam, "AUTO")
},
{
MUX_PROP_STR("transmission_mode", "Transmission Mode", dvbt, mode, "AUTO")
},
{
MUX_PROP_STR("guard_interval", "Guard Interval", dvbt, guard, "AUTO")
},
{
MUX_PROP_STR("hierarchy", "Hierarchy", dvbt, hier, "AUTO"),
},
{
MUX_PROP_STR("fec_hi", "FEC High", dvbt, fechi, "AUTO"),
},
{
MUX_PROP_STR("fec_lo", "FEC Low", dvbt, feclo, "AUTO"),
},
{}
}
};
/*
* DVB-C
*/
dvb_mux_class_R(dvbc, modulation, qam,
DVB_MOD_QAM_AUTO, DVB_MOD_QAM_16, DVB_MOD_QAM_32,
DVB_MOD_QAM_64, DVB_MOD_QAM_128, DVB_MOD_QAM_256);
dvb_mux_class_X(dvbc, qam, fec_inner, fec,
DVB_FEC_AUTO, DVB_FEC_NONE,
DVB_FEC_1_2, DVB_FEC_2_3, DVB_FEC_3_4, DVB_FEC_4_5,
DVB_FEC_5_6, DVB_FEC_8_9, DVB_FEC_9_10);
#define dvb_mux_dvbc_class_delsys_get dvb_mux_class_delsys_get
#define dvb_mux_dvbc_class_delsys_set dvb_mux_class_delsys_set
static htsmsg_t *
dvb_mux_dvbc_class_delsys_enum (void *o)
{
htsmsg_t *list = htsmsg_create_list();
htsmsg_add_str(list, NULL, dvb_delsys2str(DVB_SYS_DVBC_ANNEX_A));
htsmsg_add_str(list, NULL, dvb_delsys2str(DVB_SYS_DVBC_ANNEX_B));
htsmsg_add_str(list, NULL, dvb_delsys2str(DVB_SYS_DVBC_ANNEX_C));
return list;
}
const idclass_t dvb_mux_dvbc_class =
{
.ic_super = &dvb_mux_class,
.ic_class = "dvb_mux_dvbc",
.ic_caption = "Linux DVB-C Multiplex",
.ic_properties = (const property_t[]){
{
MUX_PROP_STR("delsys", "Delivery System", dvbc, delsys, "DVBC_ANNEX_AC"),
},
{
.type = PT_U32,
.id = "frequency",
.name = "Frequency (Hz)",
.opts = PO_WRONCE,
.off = offsetof(dvb_mux_t, lm_tuning.dmc_fe_freq),
},
{
.type = PT_U32,
.id = "symbolrate",
.name = "Symbol Rate (Sym/s)",
.opts = PO_WRONCE,
.off = offsetof(dvb_mux_t, lm_tuning.u.dmc_fe_qam.symbol_rate),
},
{
MUX_PROP_STR("constellation", "Constellation", dvbc, qam, "AUTO")
},
{
MUX_PROP_STR("fec", "FEC", dvbc, fec, "AUTO")
},
{}
}
};
dvb_mux_class_X(dvbs, qpsk, fec_inner, fec,
DVB_FEC_AUTO, DVB_FEC_NONE,
DVB_FEC_1_2, DVB_FEC_2_3, DVB_FEC_3_4, DVB_FEC_3_5,
DVB_FEC_4_5, DVB_FEC_5_6, DVB_FEC_7_8, DVB_FEC_8_9,
DVB_FEC_9_10);
static const void *
dvb_mux_dvbs_class_polarity_get (void *o)
{
static const char *s;
dvb_mux_t *lm = o;
s = dvb_pol2str(lm->lm_tuning.u.dmc_fe_qpsk.polarisation);
return &s;
}
static int
dvb_mux_dvbs_class_polarity_set (void *o, const void *s)
{
dvb_mux_t *lm = o;
lm->lm_tuning.u.dmc_fe_qpsk.polarisation = dvb_str2pol((const char*)s);
return 1;
}
static htsmsg_t *
dvb_mux_dvbs_class_polarity_enum (void *o)
{
htsmsg_t *list = htsmsg_create_list();
htsmsg_add_str(list, NULL, dvb_pol2str(DVB_POLARISATION_VERTICAL));
htsmsg_add_str(list, NULL, dvb_pol2str(DVB_POLARISATION_HORIZONTAL));
htsmsg_add_str(list, NULL, dvb_pol2str(DVB_POLARISATION_CIRCULAR_LEFT));
htsmsg_add_str(list, NULL, dvb_pol2str(DVB_POLARISATION_CIRCULAR_RIGHT));
return list;
}
static const void *
dvb_mux_dvbs_class_modulation_get ( void *o )
{
static const char *s;
dvb_mux_t *lm = o;
s = dvb_qam2str(lm->lm_tuning.dmc_fe_modulation);
return &s;
}
static int
dvb_mux_dvbs_class_modulation_set (void *o, const void *s)
{
int mod = dvb_str2qam(s);
dvb_mux_t *lm = o;
if (mod != lm->lm_tuning.dmc_fe_modulation) {
lm->lm_tuning.dmc_fe_modulation = mod;
return 1;
}
return 0;
}
static htsmsg_t *
dvb_mux_dvbs_class_modulation_list ( void *o )
{
htsmsg_t *list = htsmsg_create_list();
htsmsg_add_str(list, NULL, dvb_qam2str(DVB_MOD_AUTO));
htsmsg_add_str(list, NULL, dvb_qam2str(DVB_MOD_QPSK));
htsmsg_add_str(list, NULL, dvb_qam2str(DVB_MOD_QAM_16));
htsmsg_add_str(list, NULL, dvb_qam2str(DVB_MOD_PSK_8));
htsmsg_add_str(list, NULL, dvb_qam2str(DVB_MOD_APSK_16));
htsmsg_add_str(list, NULL, dvb_qam2str(DVB_MOD_APSK_32));
return list;
}
static const void *
dvb_mux_dvbs_class_rolloff_get ( void *o )
{
static const char *s;
dvb_mux_t *lm = o;
s = dvb_rolloff2str(lm->lm_tuning.dmc_fe_rolloff);
return &s;
}
static int
dvb_mux_dvbs_class_rolloff_set ( void *o, const void *s )
{
dvb_mux_t *lm = o;
lm->lm_tuning.dmc_fe_rolloff = dvb_str2rolloff(s);
return 1;
}
static htsmsg_t *
dvb_mux_dvbs_class_rolloff_list ( void *o )
{
htsmsg_t *list = htsmsg_create_list();
htsmsg_add_str(list, NULL, dvb_rolloff2str(DVB_ROLLOFF_35));
// Note: this is a bit naff, as the below values are only relevant
// to S2 muxes, but currently have no way to model that
htsmsg_add_str(list, NULL, dvb_rolloff2str(DVB_ROLLOFF_20));
htsmsg_add_str(list, NULL, dvb_rolloff2str(DVB_ROLLOFF_25));
htsmsg_add_str(list, NULL, dvb_rolloff2str(DVB_ROLLOFF_AUTO));
return list;
}
static const void *
dvb_mux_dvbs_class_pilot_get ( void *o )
{
static const char *s;
dvb_mux_t *lm = o;
s = dvb_pilot2str(lm->lm_tuning.dmc_fe_pilot);
return &s;
}
static int
dvb_mux_dvbs_class_pilot_set ( void *o, const void *s )
{
dvb_mux_t *lm = o;
lm->lm_tuning.dmc_fe_pilot = dvb_str2pilot(s);
return 1;
}
static htsmsg_t *
dvb_mux_dvbs_class_pilot_list ( void *o )
{
htsmsg_t *list = htsmsg_create_list();
htsmsg_add_str(list, NULL, dvb_pilot2str(DVB_PILOT_AUTO));
htsmsg_add_str(list, NULL, dvb_pilot2str(DVB_PILOT_ON));
htsmsg_add_str(list, NULL, dvb_pilot2str(DVB_PILOT_OFF));
return list;
}
#define dvb_mux_dvbs_class_delsys_get dvb_mux_class_delsys_get
#define dvb_mux_dvbs_class_delsys_set dvb_mux_class_delsys_set
static htsmsg_t *
dvb_mux_dvbs_class_delsys_enum (void *o)
{
htsmsg_t *list = htsmsg_create_list();
htsmsg_add_str(list, NULL, dvb_delsys2str(DVB_SYS_DVBS));
htsmsg_add_str(list, NULL, dvb_delsys2str(DVB_SYS_DVBS2));
return list;
}
static const void *
dvb_mux_dvbs_class_orbital_get ( void *o )
{
static char buf[256], *s = buf;
dvb_mux_t *lm = o;
snprintf(buf, sizeof(buf), "%0.1f%c",
lm->lm_tuning.u.dmc_fe_qpsk.orbital_pos / 10.0,
lm->lm_tuning.u.dmc_fe_qpsk.orbital_dir);
return &s;
}
static int
dvb_mux_dvbs_class_orbital_set ( void *o, const void *s )
{
int pos, save = 0;
char dir;
char *tmp = tvh_strdupa(s);
dvb_mux_t *lm = o;
dir = tmp[strlen(tmp)-1];
tmp[strlen(tmp)-1] = '\0';
pos = (int)floorf(atof(tmp) * 10.0);
if (pos != lm->lm_tuning.u.dmc_fe_qpsk.orbital_pos ||
dir != lm->lm_tuning.u.dmc_fe_qpsk.orbital_dir) {
lm->lm_tuning.u.dmc_fe_qpsk.orbital_pos = pos;
lm->lm_tuning.u.dmc_fe_qpsk.orbital_dir = dir;
save = 1;
}
return save;
}
const idclass_t dvb_mux_dvbs_class =
{
.ic_super = &dvb_mux_class,
.ic_class = "dvb_mux_dvbs",
.ic_caption = "Linux DVB-S Multiplex",
.ic_properties = (const property_t[]){
{
MUX_PROP_STR("delsys", "Delivery System", dvbs, delsys, "DVBS"),
},
{
.type = PT_U32,
.id = "frequency",
.name = "Frequency (kHz)",
.opts = PO_WRONCE,
.off = offsetof(dvb_mux_t, lm_tuning.dmc_fe_freq),
},
{
.type = PT_U32,
.id = "symbolrate",
.name = "Symbol Rate (Sym/s)",
.opts = PO_WRONCE,
.off = offsetof(dvb_mux_t, lm_tuning.u.dmc_fe_qpsk.symbol_rate),
},
{
MUX_PROP_STR("polarisation", "Polarisation", dvbs, polarity, NULL)
},
{
.type = PT_STR,
.id = "modulation",
.name = "Modulation",
.set = dvb_mux_dvbs_class_modulation_set,
.get = dvb_mux_dvbs_class_modulation_get,
.list = dvb_mux_dvbs_class_modulation_list,
.def.s = "AUTO",
},
{
MUX_PROP_STR("fec", "FEC", dvbs, fec, "AUTO")
},
{
.type = PT_STR,
.id = "rolloff",
.name = "Rolloff",
.set = dvb_mux_dvbs_class_rolloff_set,
.get = dvb_mux_dvbs_class_rolloff_get,
.list = dvb_mux_dvbs_class_rolloff_list,
.def.s = "AUTO"
},
{
.type = PT_STR,
.id = "pilot",
.name = "Pilot",
.opts = PO_ADVANCED,
.set = dvb_mux_dvbs_class_pilot_set,
.get = dvb_mux_dvbs_class_pilot_get,
.list = dvb_mux_dvbs_class_pilot_list,
},
{
.type = PT_STR,
.id = "orbital",
.name = "Orbital Pos.",
.set = dvb_mux_dvbs_class_orbital_set,
.get = dvb_mux_dvbs_class_orbital_get,
.opts = PO_ADVANCED | PO_RDONLY
},
{}
}
};
#define dvb_mux_atsc_class_delsys_get dvb_mux_class_delsys_get
#define dvb_mux_atsc_class_delsys_set dvb_mux_class_delsys_set
static htsmsg_t *
dvb_mux_atsc_class_delsys_enum (void *o)
{
htsmsg_t *list = htsmsg_create_list();
htsmsg_add_str(list, NULL, dvb_delsys2str(DVB_SYS_ATSC));
htsmsg_add_str(list, NULL, dvb_delsys2str(DVB_SYS_ATSCMH));
return list;
}
dvb_mux_class_R(atsc, modulation, qam,
DVB_MOD_QAM_AUTO, DVB_MOD_QAM_256, DVB_MOD_VSB_8);
const idclass_t dvb_mux_atsc_class =
{
.ic_super = &dvb_mux_class,
.ic_class = "dvb_mux_atsc",
.ic_caption = "Linux ATSC Multiplex",
.ic_properties = (const property_t[]){
{
MUX_PROP_STR("delsys", "Delivery System", atsc, delsys, "ATSC"),
},
{
.type = PT_U32,
.id = "frequency",
.name = "Frequency (kHz)",
.opts = PO_WRONCE,
.off = offsetof(dvb_mux_t, lm_tuning.dmc_fe_freq),
},
{
MUX_PROP_STR("modulation", "Modulation", atsc, qam, "AUTO")
},
{}
}
};
/* **************************************************************************
* Class methods
* *************************************************************************/
static void
dvb_mux_config_save ( mpegts_mux_t *mm )
{
htsmsg_t *c = htsmsg_create_map();
mpegts_mux_save(mm, c);
hts_settings_save(c, "input/dvb/networks/%s/muxes/%s/config",
idnode_uuid_as_str(&mm->mm_network->mn_id),
idnode_uuid_as_str(&mm->mm_id));
htsmsg_destroy(c);
}
static void
dvb_mux_display_name ( mpegts_mux_t *mm, char *buf, size_t len )
{
dvb_mux_t *lm = (dvb_mux_t*)mm;
dvb_network_t *ln = (dvb_network_t*)mm->mm_network;
uint32_t freq = lm->lm_tuning.dmc_fe_freq;
char pol[2] = { 0 };
if (ln->ln_type == DVB_TYPE_S) {
const char *s = dvb_pol2str(lm->lm_tuning.u.dmc_fe_qpsk.polarisation);
if (s) pol[0] = *s;
freq /= 1000;
} else {
freq /= 1000;
}
snprintf(buf, len, "%d%s", freq, pol);
}
static void
dvb_mux_create_instances ( mpegts_mux_t *mm )
{
mpegts_network_link_t *mnl;
LIST_FOREACH(mnl, &mm->mm_network->mn_inputs, mnl_mn_link) {
mpegts_input_t *mi = mnl->mnl_input;
if (mi->mi_is_enabled(mi))
mi->mi_create_mux_instance(mi, mm);
}
}
static void
dvb_mux_delete ( mpegts_mux_t *mm, int delconf )
{
/* Remove config */
if (delconf)
hts_settings_remove("input/dvb/networks/%s/muxes/%s",
idnode_uuid_as_str(&mm->mm_network->mn_id),
idnode_uuid_as_str(&mm->mm_id));
/* Delete the mux */
mpegts_mux_delete(mm, delconf);
}
/* **************************************************************************
* Creation/Config
* *************************************************************************/
dvb_mux_t *
dvb_mux_create0
( dvb_network_t *ln,
uint16_t onid, uint16_t tsid, const dvb_mux_conf_t *dmc,
const char *uuid, htsmsg_t *conf )
{
const idclass_t *idc;
mpegts_mux_t *mm;
dvb_mux_t *lm;
htsmsg_t *c, *e;
htsmsg_field_t *f;
mpegts_service_t *ts;
int move = 0;
/* Class */
if (ln->ln_type == DVB_TYPE_S)
idc = &dvb_mux_dvbs_class;
else if (ln->ln_type == DVB_TYPE_C)
idc = &dvb_mux_dvbc_class;
else if (ln->ln_type == DVB_TYPE_T)
idc = &dvb_mux_dvbt_class;
else if (ln->ln_type == DVB_TYPE_ATSC)
idc = &dvb_mux_atsc_class;
else {
tvherror("dvb", "unknown FE type %d", ln->ln_type);
return NULL;
}
/* Create */
if (!(mm = mpegts_mux_create0(calloc(1, sizeof(dvb_mux_t)), idc, uuid,
(mpegts_network_t*)ln, onid, tsid, conf)))
return NULL;
lm = (dvb_mux_t*)mm;
lm->lm_tuning.dmc_fe_type = ln->ln_type;
/* Tuning */
if (dmc) {
assert(dmc->dmc_fe_type == lm->lm_tuning.dmc_fe_type);
memcpy(&lm->lm_tuning, dmc, sizeof(dvb_mux_conf_t));
}
/* Callbacks */
lm->mm_delete = dvb_mux_delete;
lm->mm_display_name = dvb_mux_display_name;
lm->mm_config_save = dvb_mux_config_save;
lm->mm_create_instances = dvb_mux_create_instances;
/* Defaults */
if (dmc == NULL) {
lm->lm_tuning.dmc_fe_inversion = DVB_INVERSION_AUTO;
lm->lm_tuning.dmc_fe_pilot = DVB_PILOT_AUTO;
}
/* No config */
if (!conf) return lm;
/* Services */
c = hts_settings_load_r(1, "input/dvb/networks/%s/muxes/%s/services",
idnode_uuid_as_str(&ln->mn_id),
idnode_uuid_as_str(&mm->mm_id));
if (!c) {
move = 1;
c = hts_settings_load_r(1, "input/linuxdvb/networks/%s/muxes/%s/services",
idnode_uuid_as_str(&ln->mn_id),
idnode_uuid_as_str(&mm->mm_id));
}
if (c) {
HTSMSG_FOREACH(f, c) {
if (!(e = htsmsg_get_map_by_field(f))) continue;
ts = mpegts_service_create1(f->hmf_name, (mpegts_mux_t *)lm, 0, 0, e);
if (ts && move)
ts->s_config_save((service_t *)ts);
}
htsmsg_destroy(c);
if (move)
hts_settings_remove("input/linuxdvb/networks/%s/muxes/%s/services",
idnode_uuid_as_str(&ln->mn_id),
idnode_uuid_as_str(&mm->mm_id));
}
return lm;
}

View file

@ -16,7 +16,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "input/mpegts.h"
#include "input.h"
#include "subscriptions.h"
#include "dvb_charset.h"

View file

@ -0,0 +1,451 @@
/*
* Tvheadend - Linux DVB Network
*
* Copyright (C) 2013 Adam Sutton
*
* 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 <http://www.gnu.org/licenses/>.
*/
#include "tvheadend.h"
#include "input.h"
#include "queue.h"
#include "settings.h"
#include "mpegts_dvb.h"
#include "linuxdvb/linuxdvb_private.h"
#include "dvb_charset.h"
#include "scanfile.h"
#include <sys/types.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <stdlib.h>
#include <dirent.h>
#include <fcntl.h>
static mpegts_mux_t *
dvb_network_find_mux
( dvb_network_t *ln, dvb_mux_conf_t *dmc );
/* ****************************************************************************
* Class definition
* ***************************************************************************/
extern const idclass_t mpegts_network_class;
static void
dvb_network_class_delete ( idnode_t *in )
{
mpegts_network_t *mn = (mpegts_network_t*)in;
/* remove config */
hts_settings_remove("input/dvb/networks/%s",
idnode_uuid_as_str(in));
/* Parent delete */
mpegts_network_delete(mn, 1);
}
static const void *
dvb_network_class_scanfile_get ( void *o )
{
static const char *s = NULL;
return &s;
}
static int
dvb_network_class_scanfile_set ( void *o, const void *s )
{
dvb_mux_conf_t *dmc;
scanfile_network_t *sfn;
mpegts_mux_t *mm;
/* Find */
if (!s)
return 0;
if (!(sfn = scanfile_find(s)))
return 0;
/* Create */
LIST_FOREACH(dmc, &sfn->sfn_muxes, dmc_link) {
if (!(mm = dvb_network_find_mux(o, dmc))) {
mm = (mpegts_mux_t*)dvb_mux_create0(o,
MPEGTS_ONID_NONE,
MPEGTS_TSID_NONE,
dmc, NULL, NULL);
if (mm)
mm->mm_config_save(mm);
}
}
return 0;
}
static htsmsg_t *
dvb_network_class_scanfile_list ( const char *type )
{
htsmsg_t *e, *m = htsmsg_create_map();
htsmsg_add_str(m, "type", "api");
htsmsg_add_str(m, "uri", "dvb/scanfile/list");
e = htsmsg_create_map();
htsmsg_add_str(e, "type", type);
htsmsg_add_msg(m, "params", e);
return m;
}
static htsmsg_t *
dvb_network_dvbt_class_scanfile_list ( void *o )
{
return dvb_network_class_scanfile_list("dvbt");
}
static htsmsg_t *
dvb_network_dvbc_class_scanfile_list ( void *o )
{
return dvb_network_class_scanfile_list("dvbc");
}
static htsmsg_t *
dvb_network_dvbs_class_scanfile_list ( void *o )
{
return dvb_network_class_scanfile_list("dvbs");
}
static htsmsg_t *
dvb_network_atsc_class_scanfile_list ( void *o )
{
return dvb_network_class_scanfile_list("atsc");
}
const idclass_t dvb_network_class =
{
.ic_super = &mpegts_network_class,
.ic_class = "dvb_network",
.ic_caption = "LinuxDVB Network",
.ic_delete = dvb_network_class_delete,
.ic_properties = (const property_t[]){
{}
}
};
const idclass_t dvb_network_dvbt_class =
{
.ic_super = &dvb_network_class,
.ic_class = "dvb_network_dvbt",
.ic_caption = "DVB-T Network",
.ic_properties = (const property_t[]) {
{
.type = PT_STR,
.id = "scanfile",
.name = "Pre-defined Muxes",
.set = dvb_network_class_scanfile_set,
.get = dvb_network_class_scanfile_get,
.list = dvb_network_dvbt_class_scanfile_list,
.opts = PO_NOSAVE,
},
{}
}
};
const idclass_t dvb_network_dvbc_class =
{
.ic_super = &dvb_network_class,
.ic_class = "dvb_network_dvbc",
.ic_caption = "DVB-C Network",
.ic_properties = (const property_t[]) {
{
.type = PT_STR,
.id = "scanfile",
.name = "Pre-defined Muxes",
.set = dvb_network_class_scanfile_set,
.get = dvb_network_class_scanfile_get,
.list = dvb_network_dvbc_class_scanfile_list,
.opts = PO_NOSAVE,
},
{}
}
};
const idclass_t dvb_network_dvbs_class =
{
.ic_super = &dvb_network_class,
.ic_class = "dvb_network_dvbs",
.ic_caption = "DVB-S Network",
.ic_properties = (const property_t[]) {
{
.type = PT_STR,
.id = "scanfile",
.name = "Pre-defined Muxes",
.set = dvb_network_class_scanfile_set,
.get = dvb_network_class_scanfile_get,
.list = dvb_network_dvbs_class_scanfile_list,
.opts = PO_NOSAVE,
},
{}
}
};
const idclass_t dvb_network_atsc_class =
{
.ic_super = &dvb_network_class,
.ic_class = "dvb_network_atsc",
.ic_caption = "ATSC Network",
.ic_properties = (const property_t[]) {
{
.type = PT_STR,
.id = "scanfile",
.name = "Pre-defined Muxes",
.set = dvb_network_class_scanfile_set,
.get = dvb_network_class_scanfile_get,
.list = dvb_network_atsc_class_scanfile_list,
.opts = PO_NOSAVE,
},
{}
}
};
/* ****************************************************************************
* Class methods
* ***************************************************************************/
static mpegts_mux_t *
dvb_network_find_mux
( dvb_network_t *ln, dvb_mux_conf_t *dmc )
{
mpegts_mux_t *mm;
LIST_FOREACH(mm, &ln->mn_muxes, mm_network_link) {
dvb_mux_t *lm = (dvb_mux_t*)mm;
if (abs(lm->lm_tuning.dmc_fe_freq
- dmc->dmc_fe_freq) > LINUXDVB_FREQ_TOL) continue;
if (lm->lm_tuning.u.dmc_fe_qpsk.polarisation != dmc->u.dmc_fe_qpsk.polarisation) continue;
break;
}
return mm;
}
static void
dvb_network_config_save ( mpegts_network_t *mn )
{
htsmsg_t *c = htsmsg_create_map();
idnode_save(&mn->mn_id, c);
htsmsg_add_str(c, "class", mn->mn_id.in_class->ic_class);
hts_settings_save(c, "input/dvb/networks/%s/config",
idnode_uuid_as_str(&mn->mn_id));
htsmsg_destroy(c);
}
static mpegts_mux_t *
dvb_network_create_mux
( mpegts_mux_t *mm, uint16_t onid, uint16_t tsid, dvb_mux_conf_t *dmc )
{
int save = 0;
dvb_network_t *ln = (dvb_network_t*)mm->mm_network;
mm = dvb_network_find_mux(ln, dmc);
if (!mm && ln->mn_autodiscovery) {
mm = (mpegts_mux_t*)dvb_mux_create0(ln, onid, tsid, dmc, NULL, NULL);
save = 1;
} else if (mm) {
dvb_mux_t *lm = (dvb_mux_t*)mm;
dmc->dmc_fe_freq = lm->lm_tuning.dmc_fe_freq;
// Note: keep original freq, else it can bounce around if diff transponders
// report it slightly differently.
// TODO: Note: should we also leave AUTO settings as is?
if (memcmp(&lm->lm_tuning, dmc, sizeof(lm->lm_tuning))) {
memcpy(&lm->lm_tuning, dmc, sizeof(lm->lm_tuning));
save = 1;
}
}
if (save)
mm->mm_config_save(mm);
return mm;
}
static mpegts_service_t *
dvb_network_create_service
( mpegts_mux_t *mm, uint16_t sid, uint16_t pmt_pid )
{
return mpegts_service_create1(NULL, mm, sid, pmt_pid, NULL);
}
static const idclass_t *
dvb_network_mux_class
( mpegts_network_t *mn )
{
if (idnode_is_instance(&mn->mn_id, &dvb_network_dvbt_class))
return &dvb_mux_dvbt_class;
if (idnode_is_instance(&mn->mn_id, &dvb_network_dvbc_class))
return &dvb_mux_dvbc_class;
if (idnode_is_instance(&mn->mn_id, &dvb_network_dvbs_class))
return &dvb_mux_dvbs_class;
if (idnode_is_instance(&mn->mn_id, &dvb_network_atsc_class))
return &dvb_mux_atsc_class;
return NULL;
}
static mpegts_mux_t *
dvb_network_mux_create2
( mpegts_network_t *mn, htsmsg_t *conf )
{
dvb_network_t *ln = (dvb_network_t*)mn;
return (mpegts_mux_t*)
dvb_mux_create0(ln, MPEGTS_ONID_NONE, MPEGTS_TSID_NONE,
NULL, NULL, conf);
}
/* ****************************************************************************
* Creation/Config
* ***************************************************************************/
dvb_network_t *
dvb_network_create0
( const char *uuid, const idclass_t *idc, htsmsg_t *conf )
{
dvb_network_t *ln;
htsmsg_t *c, *e;
htsmsg_field_t *f;
mpegts_mux_t *mm;
int move = 0;
ln = calloc(1, sizeof(dvb_network_t));
if (idc == &dvb_network_dvbt_class)
ln->ln_type = DVB_TYPE_T;
else if (idc == &dvb_network_dvbc_class)
ln->ln_type = DVB_TYPE_C;
else if (idc == &dvb_network_dvbs_class)
ln->ln_type = DVB_TYPE_S;
else
ln->ln_type = DVB_TYPE_ATSC;
/* Create */
if (!(ln = (dvb_network_t*)mpegts_network_create0((void*)ln,
idc, uuid, NULL, conf)))
return NULL;
/* Callbacks */
ln->mn_create_mux = dvb_network_create_mux;
ln->mn_create_service = dvb_network_create_service;
ln->mn_config_save = dvb_network_config_save;
ln->mn_mux_class = dvb_network_mux_class;
ln->mn_mux_create2 = dvb_network_mux_create2;
/* No config */
if (!conf)
return ln;
/* Load muxes */
c = hts_settings_load_r(1, "input/dvb/networks/%s/muxes", uuid);
if (!c) {
c = hts_settings_load_r(1, "input/linuxdvb/networks/%s/muxes", uuid);
move = 1;
}
if (c) {
HTSMSG_FOREACH(f, c) {
if (!(e = htsmsg_get_map_by_field(f))) continue;
if (!(e = htsmsg_get_map(e, "config"))) continue;
mm = (mpegts_mux_t *)dvb_mux_create1(ln, f->hmf_name, e);
if (mm && move)
mm->mm_config_save(mm);
}
htsmsg_destroy(c);
if (move)
hts_settings_remove("input/linuxdvb/networks/%s/muxes", uuid);
}
return ln;
}
static mpegts_network_t *
dvb_network_builder
( const idclass_t *idc, htsmsg_t *conf )
{
return (mpegts_network_t*)dvb_network_create0(NULL, idc, conf);
}
static const idclass_t* dvb_network_classes[] = {
&dvb_network_dvbt_class,
&dvb_network_dvbc_class,
&dvb_network_dvbs_class,
&dvb_network_atsc_class,
};
void dvb_network_init ( void )
{
htsmsg_t *c, *e;
htsmsg_field_t *f;
const char *s;
dvb_network_t *ln;
int i, move = 0;
/* Load scan files */
scanfile_init();
/* Load list of mux charset global overrides */
dvb_charset_init();
/* Register class builders */
for (i = 0; i < ARRAY_SIZE(dvb_network_classes); i++)
mpegts_network_register_builder(dvb_network_classes[i],
dvb_network_builder);
/* Load settings */
if (!(c = hts_settings_load_r(1, "input/dvb/networks"))) {
if (!(c = hts_settings_load_r(1, "input/linuxdvb/networks"))) {
printf("RETURN!!\n");
return;
}
move = 1;
}
HTSMSG_FOREACH(f, c) {
if (!(e = htsmsg_get_map_by_field(f))) continue;
if (!(e = htsmsg_get_map(e, "config"))) continue;
if (!(s = htsmsg_get_str(e, "class"))) continue;
for (i = 0; i < ARRAY_SIZE(dvb_network_classes); i++) {
if(!strcmp(dvb_network_classes[i]->ic_class, s + (move ? 5 : 0))) {
ln = dvb_network_create0(f->hmf_name, dvb_network_classes[i], e);
if (ln && move)
ln->mn_config_save((mpegts_network_t *)ln);
break;
}
}
}
htsmsg_destroy(c);
if (move)
hts_settings_remove("input/linuxdvb/networks");
}
void dvb_network_done ( void )
{
int i;
pthread_mutex_lock(&global_lock);
/* Unregister class builders */
for (i = 0; i < ARRAY_SIZE(dvb_network_classes); i++) {
mpegts_network_unregister_builder(dvb_network_classes[i]);
mpegts_network_class_delete(dvb_network_classes[i], 0);
}
pthread_mutex_unlock(&global_lock);
dvb_charset_done();
scanfile_done();
}
/* ****************************************************************************
* Search
* ***************************************************************************/
dvb_network_t*
dvb_network_find_by_uuid(const char *uuid)
{
idnode_t *in = idnode_find(uuid, &dvb_network_class);
return (dvb_network_t*)in;
}
/******************************************************************************
* Editor Configuration
*
* vim:sts=2:ts=2:sw=2:et
*****************************************************************************/

View file

@ -20,7 +20,7 @@
#include <assert.h>
#include "service.h"
#include "input/mpegts.h"
#include "input.h"
#include "settings.h"
#include "dvb_charset.h"
@ -148,8 +148,16 @@ mpegts_service_is_enabled(service_t *t)
* Save
*/
static void
mpegts_service_config_save(service_t *t)
mpegts_service_config_save ( service_t *t )
{
htsmsg_t *c = htsmsg_create_map();
mpegts_service_t *s = (mpegts_service_t*)t;
service_save(t, c);
hts_settings_save(c, "input/dvb/networks/%s/muxes/%s/services/%s",
idnode_uuid_as_str(&s->s_dvb_mux->mm_network->mn_id),
idnode_uuid_as_str(&s->s_dvb_mux->mm_id),
idnode_uuid_as_str(&s->s_id));
htsmsg_destroy(c);
}
/*
@ -181,7 +189,7 @@ mpegts_service_enlist(service_t *t, struct service_instance_list *sil)
p = -1;
} else {
w = mmi->mmi_input->mi_get_weight(mmi->mmi_input);
p = mmi->mmi_input->mi_get_priority(mmi->mmi_input);
p = mmi->mmi_input->mi_get_priority(mmi->mmi_input, mmi->mmi_mux);
}
service_instance_add(sil, t, mmi->mmi_input->mi_instance, p, w);
@ -348,7 +356,7 @@ mpegts_service_delete ( service_t *t, int delconf )
/* Remove config */
if (delconf)
hts_settings_remove("input/linuxdvb/networks/%s/muxes/%s/services/%s",
hts_settings_remove("input/dvb/networks/%s/muxes/%s/services/%s",
idnode_uuid_as_str(&mm->mm_network->mn_id),
idnode_uuid_as_str(&mm->mm_id),
idnode_uuid_as_str(&t->s_id));
@ -451,15 +459,6 @@ mpegts_service_find
return s;
}
/*
* Save
*/
void
mpegts_service_save ( mpegts_service_t *s, htsmsg_t *c )
{
service_save((service_t*)s, c);
}
/******************************************************************************
* Editor Configuration
*

View file

@ -17,7 +17,7 @@
*/
#include "tvheadend.h"
#include "input/mpegts.h"
#include "input.h"
#include <assert.h>

View file

@ -17,7 +17,7 @@
*/
#include "tvheadend.h"
#include "../dvb.h"
#include "dvb.h"
#include "filebundle.h"
#include "config.h"
#include "scanfile.h"
@ -112,14 +112,12 @@ scanfile_load_atsc ( dvb_mux_conf_t *mux, const char *line )
{
char qam[20];
int r;
dvb_frontend_parameters_t *p = &mux->dmc_fe_params;
r = sscanf(line, "%u %s", &p->frequency, qam);
r = sscanf(line, "%u %s", &mux->dmc_fe_freq, qam);
if (r != 2) return 1;
#if DVB_VER_ATLEAST(5,0)
mux->dmc_fe_delsys = SYS_ATSC;
#endif
if ((p->u.vsb.modulation = dvb_str2qam(qam)) == -1) return 1;
mux->dmc_fe_type = DVB_TYPE_ATSC;
mux->dmc_fe_delsys = DVB_SYS_ATSC;
if ((mux->dmc_fe_modulation = dvb_str2qam(qam)) == -1) return 1;
return 0;
}
@ -130,31 +128,28 @@ scanfile_load_dvbt ( dvb_mux_conf_t *mux, const char *line )
char bw[20], fec[20], fec2[20], qam[20], mode[20], guard[20], hier[20];
int r;
uint32_t i;
dvb_frontend_parameters_t *p = &mux->dmc_fe_params;
if (*line == '2') {
r = sscanf(line+1, "%u %u %u %10s %10s %10s %10s %10s %10s %10s",
&i, &i, &p->frequency, bw, fec, fec2, qam, mode, guard, hier);
&i, &i, &mux->dmc_fe_freq, bw, fec, fec2, qam,
mode, guard, hier);
if(r != 10) return 1;
#if DVB_VER_ATLEAST(5,4)
mux->dmc_fe_delsys = SYS_DVBT2;
#endif
mux->dmc_fe_delsys = DVB_SYS_DVBT2;
} else {
r = sscanf(line, "%u %10s %10s %10s %10s %10s %10s %10s",
&p->frequency, bw, fec, fec2, qam, mode, guard, hier);
&mux->dmc_fe_freq, bw, fec, fec2, qam, mode, guard, hier);
if(r != 8) return 1;
#if DVB_VER_ATLEAST(5,0)
mux->dmc_fe_delsys = SYS_DVBT;
#endif
mux->dmc_fe_delsys = DVB_SYS_DVBT;
}
if ((p->u.ofdm.bandwidth = dvb_str2bw(bw)) == -1) return 1;
if ((p->u.ofdm.constellation = dvb_str2qam(qam)) == -1) return 1;
if ((p->u.ofdm.code_rate_HP = dvb_str2fec(fec)) == -1) return 1;
if ((p->u.ofdm.code_rate_LP = dvb_str2fec(fec2)) == -1) return 1;
if ((p->u.ofdm.transmission_mode = dvb_str2mode(mode)) == -1) return 1;
if ((p->u.ofdm.guard_interval = dvb_str2guard(guard)) == -1) return 1;
if ((p->u.ofdm.hierarchy_information = dvb_str2hier(hier)) == -1) return 1;
mux->dmc_fe_type = DVB_TYPE_T;
if ((mux->u.dmc_fe_ofdm.bandwidth = dvb_str2bw(bw)) == -1) return 1;
if ((mux->dmc_fe_modulation = dvb_str2qam(qam)) == -1) return 1;
if ((mux->u.dmc_fe_ofdm.code_rate_HP = dvb_str2fec(fec)) == -1) return 1;
if ((mux->u.dmc_fe_ofdm.code_rate_LP = dvb_str2fec(fec2)) == -1) return 1;
if ((mux->u.dmc_fe_ofdm.transmission_mode = dvb_str2mode(mode)) == -1) return 1;
if ((mux->u.dmc_fe_ofdm.guard_interval = dvb_str2guard(guard)) == -1) return 1;
if ((mux->u.dmc_fe_ofdm.hierarchy_information = dvb_str2hier(hier)) == -1) return 1;
return 0;
}
@ -164,7 +159,6 @@ scanfile_load_dvbs ( dvb_mux_conf_t *mux, const char *line )
{
char pol[20], fec[20], qam[20], rolloff[20];
int r, v2 = 0;
dvb_frontend_parameters_t *p = &mux->dmc_fe_params;
if (*line == '2') {
v2 = 2;
@ -172,25 +166,23 @@ scanfile_load_dvbs ( dvb_mux_conf_t *mux, const char *line )
}
r = sscanf(line, "%u %s %u %s %s %s",
&p->frequency, pol, &p->u.qpsk.symbol_rate,
&mux->dmc_fe_freq, pol, &mux->u.dmc_fe_qpsk.symbol_rate,
fec, rolloff, qam);
if (r < (4+v2)) return 1;
if ((mux->dmc_fe_polarisation = dvb_str2pol(pol)) == -1) return 1;
if ((p->u.qpsk.fec_inner = dvb_str2fec(fec)) == -1) return 1;
#if DVB_VER_ATLEAST(5,0)
mux->dmc_fe_type = DVB_TYPE_S;
if ((mux->u.dmc_fe_qpsk.polarisation = dvb_str2pol(pol)) == -1) return 1;
if ((mux->u.dmc_fe_qpsk.fec_inner = dvb_str2fec(fec)) == -1) return 1;
if (v2) {
mux->dmc_fe_delsys = SYS_DVBS2;
mux->dmc_fe_delsys = DVB_SYS_DVBS2;
if ((mux->dmc_fe_rolloff = dvb_str2rolloff(rolloff)) == -1) return 1;
if ((mux->dmc_fe_modulation = dvb_str2qam(qam)) == -1) return 1;
} else {
mux->dmc_fe_delsys = SYS_DVBS;
mux->dmc_fe_rolloff = ROLLOFF_35;
mux->dmc_fe_modulation = QPSK;
mux->dmc_fe_delsys = DVB_SYS_DVBS;
mux->dmc_fe_rolloff = DVB_ROLLOFF_35;
mux->dmc_fe_modulation = DVB_MOD_QPSK;
}
#else
if (v2) return 1;
#endif
return 0;
}
@ -200,17 +192,15 @@ scanfile_load_dvbc ( dvb_mux_conf_t *mux, const char *line )
{
char fec[20], qam[20];
int r;
dvb_frontend_parameters_t *p = &mux->dmc_fe_params;
r = sscanf(line, "%u %u %s %s",
&p->frequency, &p->u.qam.symbol_rate, fec, qam);
&mux->dmc_fe_freq, &mux->u.dmc_fe_qam.symbol_rate, fec, qam);
if(r != 4) return 1;
#if DVB_VER_ATLEAST(5,0)
mux->dmc_fe_delsys = SYS_DVBC_ANNEX_AC;
#endif
if ((p->u.qam.fec_inner = dvb_str2fec(fec)) == -1) return 1;
if ((p->u.qam.modulation = dvb_str2qam(qam)) == -1) return 1;
mux->dmc_fe_type = DVB_TYPE_C;
mux->dmc_fe_delsys = DVB_SYS_DVBC_ANNEX_A;
if ((mux->u.dmc_fe_qam.fec_inner = dvb_str2fec(fec)) == -1) return 1;
if ((mux->dmc_fe_modulation = dvb_str2qam(qam)) == -1) return 1;
return 0;
}

View file

@ -16,8 +16,8 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __LINUXDVB_SCANFILES_H__
#define __LINUXDVB_SCANFILES_H__
#ifndef __DVB_SCANFILES_H__
#define __DVB_SCANFILES_H__
typedef struct scanfile_network {
const char *sfn_id;
@ -44,4 +44,4 @@ void scanfile_done ( void );
scanfile_network_t *scanfile_find ( const char *id );
#endif /* __LINUXDVB_SCANFILES_H__ */
#endif /* __DVB_SCANFILES_H__ */

View file

@ -36,7 +36,7 @@
#include "subscriptions.h"
#include "parsers.h"
#include "streaming.h"
#include "input/mpegts.h"
#include "input.h"
#include "parsers/parser_teletext.h"
#include "tsdemux.h"

View file

@ -20,7 +20,7 @@
#ifndef __TVH_TSFILE_PRIVATE_H__
#define __TVH_TSFILE_PRIVATE_H__
#include "input/mpegts.h"
#include "input.h"
/*
* Globals

View file

@ -762,6 +762,9 @@ main(int argc, char **argv)
tsfile_add_file(opt_tsfile.str[i]);
}
#endif
#if ENABLE_MPEGTS_DVB
dvb_network_init();
#endif
#if ENABLE_IPTV
iptv_init();
#endif
@ -834,6 +837,9 @@ main(int argc, char **argv)
tvhftrace("main", webui_done);
tvhftrace("main", http_client_done);
tvhftrace("main", fsmonitor_done);
#if ENABLE_MPEGTS_DVB
tvhftrace("main", dvb_network_done);
#endif
#if ENABLE_IPTV
tvhftrace("main", iptv_done);
#endif

View file

@ -35,7 +35,7 @@
#include "packet.h"
#include "streaming.h"
#include "service.h"
#include "input/mpegts.h"
#include "input.h"
#include "parser_teletext.h"
/**

View file

@ -43,7 +43,7 @@
#include "htsp_server.h"
#include "lang_codes.h"
#include "descrambler.h"
#include "input/mpegts.h"
#include "input.h"
static void service_data_timeout(void *aux);
static void service_class_save(struct idnode *self);

View file

@ -39,9 +39,7 @@
#include "htsmsg.h"
#include "notify.h"
#include "atomic.h"
#if ENABLE_MPEGTS
#include "input/mpegts.h"
#endif
#include "input.h"
struct th_subscription_list subscriptions;
struct th_subscription_list subscriptions_remove;

View file

@ -724,7 +724,7 @@ http_stream_service(http_connection_t *hc, service_t *service, int weight)
* TODO: can't currently force this to be on a particular input
*/
#if ENABLE_MPEGTS
#include "src/input/mpegts.h"
#include "input.h"
static int
http_stream_mux(http_connection_t *hc, mpegts_mux_t *mm, int weight)
{