Compare commits
No commits in common. "master" and "testing" have entirely different histories.
30
.doozer.json
|
@ -12,12 +12,16 @@
|
|||
"zlib1g-dev",
|
||||
"wget",
|
||||
"bzip2",
|
||||
"libcurl4-gnutls-dev",
|
||||
"git-core",
|
||||
"liburiparser-dev"
|
||||
"liburiparser-dev",
|
||||
"libavformat-dev",
|
||||
"libswscale-dev",
|
||||
"libavcodec-dev"
|
||||
],
|
||||
|
||||
"buildcmd": [
|
||||
"./configure --disable-dvbscan --enable-libffmpeg_static --enable-hdhomerun_static",
|
||||
"./configure --disable-dvbscan",
|
||||
"make -j ${PARALLEL}"
|
||||
]
|
||||
},
|
||||
|
@ -33,13 +37,16 @@
|
|||
"zlib1g-dev",
|
||||
"wget",
|
||||
"bzip2",
|
||||
"libcurl4-gnutls-dev",
|
||||
"git-core",
|
||||
"liburiparser-dev",
|
||||
"libx264-dev"
|
||||
"libavformat-dev",
|
||||
"libswscale-dev",
|
||||
"libavcodec-dev"
|
||||
],
|
||||
|
||||
"buildcmd": [
|
||||
"./configure --disable-dvbscan --enable-libffmpeg_static --disable-libffmpeg_static_x264 --enable-hdhomerun_static",
|
||||
"./configure --disable-dvbscan",
|
||||
"make -j ${PARALLEL}"
|
||||
]
|
||||
},
|
||||
|
@ -55,12 +62,16 @@
|
|||
"zlib1g-dev",
|
||||
"wget",
|
||||
"bzip2",
|
||||
"libcurl4-gnutls-dev",
|
||||
"git-core",
|
||||
"liburiparser-dev"
|
||||
"liburiparser-dev",
|
||||
"libavformat-dev",
|
||||
"libswscale-dev",
|
||||
"libavcodec-dev"
|
||||
],
|
||||
|
||||
"buildcmd": [
|
||||
"./configure --disable-dvbscan --enable-libffmpeg_static --enable-hdhomerun_static",
|
||||
"./configure --disable-dvbscan",
|
||||
"make -j ${PARALLEL}"
|
||||
]
|
||||
},
|
||||
|
@ -76,13 +87,16 @@
|
|||
"zlib1g-dev",
|
||||
"wget",
|
||||
"bzip2",
|
||||
"libcurl4-gnutls-dev",
|
||||
"git-core",
|
||||
"liburiparser-dev",
|
||||
"libx264-dev"
|
||||
"libavformat-dev",
|
||||
"libswscale-dev",
|
||||
"libavcodec-dev"
|
||||
],
|
||||
|
||||
"buildcmd": [
|
||||
"./configure --disable-dvbscan --enable-libffmpeg_static --disable-libffmpeg_static_x264 --enable-hdhomerun_static",
|
||||
"./configure --disable-dvbscan",
|
||||
"make -j ${PARALLEL}"
|
||||
]
|
||||
}
|
||||
|
|
15
.gitignore
vendored
|
@ -5,11 +5,8 @@ src/version.c
|
|||
|
||||
data/dvb-scan
|
||||
|
||||
libav_static
|
||||
|
||||
.cproject
|
||||
.project
|
||||
nbproject
|
||||
.settings
|
||||
|
||||
*.pyc
|
||||
|
@ -22,15 +19,3 @@ debian/tvheadend
|
|||
debian/tvheadend-dbg
|
||||
debian/tvheadend*substvars
|
||||
debian/tvheadend*.debhelper*
|
||||
|
||||
rpm/tvheadend.spec
|
||||
rpm/test.patch
|
||||
|
||||
#############
|
||||
###Windows###
|
||||
#############
|
||||
|
||||
#windows image file cache
|
||||
Thumbs.db
|
||||
#Folder config file
|
||||
Desktop.ini
|
||||
|
|
135
Makefile
|
@ -27,27 +27,21 @@ PROG := $(BUILDDIR)/tvheadend
|
|||
# Common compiler flags
|
||||
#
|
||||
|
||||
CFLAGS += -g -O2 -Wunused-result
|
||||
CFLAGS += -g -O2
|
||||
CFLAGS += -Wall -Werror -Wwrite-strings -Wno-deprecated-declarations
|
||||
CFLAGS += -Wmissing-prototypes
|
||||
CFLAGS += -fms-extensions -funsigned-char -fno-strict-aliasing
|
||||
CFLAGS += -D_FILE_OFFSET_BITS=64
|
||||
CFLAGS += -I${BUILDDIR} -I${ROOTDIR}/src -I${ROOTDIR}
|
||||
ifeq ($(CONFIG_ANDROID),yes)
|
||||
LDFLAGS += -ldl -lm
|
||||
else
|
||||
LDFLAGS += -ldl -lpthread -lm
|
||||
endif
|
||||
ifeq ($(CONFIG_LIBICONV),yes)
|
||||
LDFLAGS += -liconv
|
||||
endif
|
||||
ifeq ($(PLATFORM), darwin)
|
||||
LDFLAGS += -framework CoreServices
|
||||
else
|
||||
ifeq ($(CONFIG_ANDROID),no)
|
||||
LDFLAGS += -lrt
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(COMPILER), clang)
|
||||
CFLAGS += -Wno-microsoft -Qunused-arguments -Wno-unused-function
|
||||
|
@ -55,20 +49,6 @@ CFLAGS += -Wno-unused-value -Wno-tautological-constant-out-of-range-compare
|
|||
CFLAGS += -Wno-parentheses-equality -Wno-incompatible-pointer-types
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_LIBFFMPEG_STATIC),yes)
|
||||
CFLAGS += -I${ROOTDIR}/libav_static/build/ffmpeg/include
|
||||
LDFLAGS += -L${ROOTDIR}/libav_static/build/ffmpeg/lib -Wl,-Bstatic \
|
||||
-lavresample -lswresample -lswscale \
|
||||
-lavutil -lavformat -lavcodec -lavutil \
|
||||
-lvorbisenc -lvorbis -logg -lx264 -lvpx \
|
||||
-Wl,-Bdynamic -ldl
|
||||
endif
|
||||
ifeq ($(CONFIG_HDHOMERUN_STATIC),yes)
|
||||
CFLAGS += -I${ROOTDIR}/libhdhomerun_static
|
||||
LDFLAGS += -L${ROOTDIR}/libhdhomerun_static/libhdhomerun \
|
||||
-Wl,-Bstatic -lhdhomerun -Wl,-Bdynamic
|
||||
endif
|
||||
|
||||
vpath %.c $(ROOTDIR)
|
||||
vpath %.h $(ROOTDIR)
|
||||
|
||||
|
@ -109,6 +89,7 @@ SRCS = src/version.c \
|
|||
src/utils.c \
|
||||
src/wrappers.c \
|
||||
src/access.c \
|
||||
src/dtable.c \
|
||||
src/tcp.c \
|
||||
src/udp.c \
|
||||
src/url.c \
|
||||
|
@ -136,7 +117,7 @@ SRCS = src/version.c \
|
|||
src/trap.c \
|
||||
src/avg.c \
|
||||
src/htsstr.c \
|
||||
src/tvhpoll.c \
|
||||
src/tvhpoll.c \
|
||||
src/huffman.c \
|
||||
src/filebundle.c \
|
||||
src/config.c \
|
||||
|
@ -151,20 +132,11 @@ SRCS = src/version.c \
|
|||
src/fsmonitor.c \
|
||||
src/cron.c \
|
||||
src/esfilter.c \
|
||||
src/intlconv.c \
|
||||
src/profile.c \
|
||||
src/bouquet.c \
|
||||
src/lock.c
|
||||
src/intlconv.c
|
||||
|
||||
SRCS-${CONFIG_UPNP} += \
|
||||
src/upnp.c
|
||||
|
||||
# SATIP Server
|
||||
SRCS-${CONFIG_SATIP_SERVER} += \
|
||||
src/satip/server.c \
|
||||
src/satip/rtsp.c \
|
||||
src/satip/rtp.c
|
||||
|
||||
SRCS += \
|
||||
src/api.c \
|
||||
src/api/api_status.c \
|
||||
|
@ -177,12 +149,7 @@ SRCS += \
|
|||
src/api/api_epggrab.c \
|
||||
src/api/api_imagecache.c \
|
||||
src/api/api_esfilter.c \
|
||||
src/api/api_intlconv.c \
|
||||
src/api/api_access.c \
|
||||
src/api/api_dvr.c \
|
||||
src/api/api_caclient.c \
|
||||
src/api/api_profile.c \
|
||||
src/api/api_bouquet.c
|
||||
src/api/api_intlconv.c
|
||||
|
||||
SRCS += \
|
||||
src/parsers/parsers.c \
|
||||
|
@ -203,8 +170,6 @@ SRCS += src/plumbing/tsfix.c \
|
|||
SRCS += src/dvr/dvr_db.c \
|
||||
src/dvr/dvr_rec.c \
|
||||
src/dvr/dvr_autorec.c \
|
||||
src/dvr/dvr_timerec.c \
|
||||
src/dvr/dvr_config.c \
|
||||
src/dvr/dvr_cutpoints.c \
|
||||
|
||||
SRCS += src/webui/webui.c \
|
||||
|
@ -225,15 +190,11 @@ SRCS += src/muxer.c \
|
|||
# Optional code
|
||||
#
|
||||
|
||||
# MPEGTS core, order by usage (psi lib, tsdemux)
|
||||
# MPEGTS core
|
||||
SRCS-$(CONFIG_MPEGTS) += \
|
||||
src/descrambler/descrambler.c \
|
||||
src/descrambler/caclient.c \
|
||||
src/input/mpegts.c \
|
||||
src/input/mpegts/mpegts_pid.c \
|
||||
src/input/mpegts/mpegts_input.c \
|
||||
src/input/mpegts/tsdemux.c \
|
||||
src/input/mpegts/dvb_psi_lib.c \
|
||||
src/input/mpegts/mpegts_network.c \
|
||||
src/input/mpegts/mpegts_mux.c \
|
||||
src/input/mpegts/mpegts_service.c \
|
||||
|
@ -241,9 +202,9 @@ SRCS-$(CONFIG_MPEGTS) += \
|
|||
src/input/mpegts/dvb_support.c \
|
||||
src/input/mpegts/dvb_charset.c \
|
||||
src/input/mpegts/dvb_psi.c \
|
||||
src/input/mpegts/fastscan.c \
|
||||
src/input/mpegts/tsdemux.c \
|
||||
src/input/mpegts/mpegts_mux_sched.c \
|
||||
src/input/mpegts/mpegts_network_scan.c
|
||||
src/input/mpegts/mpegts_network_scan.c \
|
||||
|
||||
# MPEGTS DVB
|
||||
SRCS-${CONFIG_MPEGTS_DVB} += \
|
||||
|
@ -269,19 +230,13 @@ SRCS-${CONFIG_LINUXDVB} += \
|
|||
src/input/mpegts/linuxdvb/linuxdvb_rotor.c \
|
||||
src/input/mpegts/linuxdvb/linuxdvb_en50494.c
|
||||
|
||||
# SATIP Client
|
||||
# SATIP
|
||||
SRCS-${CONFIG_SATIP_CLIENT} += \
|
||||
src/input/mpegts/satip/satip.c \
|
||||
src/input/mpegts/satip/satip_frontend.c \
|
||||
src/input/mpegts/satip/satip_satconf.c \
|
||||
src/input/mpegts/satip/satip_rtsp.c
|
||||
|
||||
# HDHOMERUN
|
||||
SRCS_HDHOMERUN = \
|
||||
src/input/mpegts/tvhdhomerun/tvhdhomerun.c \
|
||||
src/input/mpegts/tvhdhomerun/tvhdhomerun_frontend.c
|
||||
SRCS-${CONFIG_HDHOMERUN_CLIENT} += $(SRCS_HDHOMERUN)
|
||||
|
||||
# IPTV
|
||||
SRCS-${CONFIG_IPTV} += \
|
||||
src/input/mpegts/iptv/iptv.c \
|
||||
|
@ -289,8 +244,6 @@ SRCS-${CONFIG_IPTV} += \
|
|||
src/input/mpegts/iptv/iptv_service.c \
|
||||
src/input/mpegts/iptv/iptv_http.c \
|
||||
src/input/mpegts/iptv/iptv_udp.c \
|
||||
src/input/mpegts/iptv/iptv_rtsp.c \
|
||||
src/input/mpegts/iptv/iptv_pipe.c
|
||||
|
||||
# TSfile
|
||||
SRCS-$(CONFIG_TSFILE) += \
|
||||
|
@ -316,11 +269,9 @@ SRCS-$(CONFIG_AVAHI) += src/avahi.c
|
|||
SRCS-$(CONFIG_BONJOUR) += src/bonjour.c
|
||||
|
||||
# libav
|
||||
SRCS_LIBAV = \
|
||||
src/libav.c \
|
||||
SRCS-$(CONFIG_LIBAV) += src/libav.c \
|
||||
src/muxer/muxer_libav.c \
|
||||
src/plumbing/transcoding.c
|
||||
SRCS-$(CONFIG_LIBAV) += $(SRCS_LIBAV)
|
||||
src/plumbing/transcoding.c \
|
||||
|
||||
# Tvhcsa
|
||||
SRCS-${CONFIG_TVHCSA} += \
|
||||
|
@ -334,24 +285,10 @@ SRCS-${CONFIG_CWC} += \
|
|||
SRCS-${CONFIG_CAPMT} += \
|
||||
src/descrambler/capmt.c
|
||||
|
||||
# CONSTCW
|
||||
SRCS-${CONFIG_CONSTCW} += \
|
||||
src/descrambler/constcw.c
|
||||
|
||||
# DVB CAM
|
||||
SRCS-${CONFIG_LINUXDVB_CA} += \
|
||||
src/input/mpegts/linuxdvb/linuxdvb_ca.c \
|
||||
src/descrambler/dvbcam.c
|
||||
|
||||
# TSDEBUGCW
|
||||
SRCS-${CONFIG_TSDEBUG} += \
|
||||
src/descrambler/tsdebugcw.c
|
||||
|
||||
# FFdecsa
|
||||
ifneq ($(CONFIG_DVBCSA),yes)
|
||||
FFDECSA-$(CONFIG_CAPMT) = yes
|
||||
FFDECSA-$(CONFIG_CWC) = yes
|
||||
FFDECSA-$(CONFIG_CONSTCW) = yes
|
||||
FFDECSA-$(CONFIG_CAPMT) = yes
|
||||
FFDECSA-$(CONFIG_CWC) = yes
|
||||
endif
|
||||
|
||||
ifeq ($(FFDECSA-yes),yes)
|
||||
|
@ -363,12 +300,6 @@ ${BUILDDIR}/src/descrambler/ffdecsa/ffdecsa_mmx.o : CFLAGS += -mmmx
|
|||
${BUILDDIR}/src/descrambler/ffdecsa/ffdecsa_sse2.o : CFLAGS += -msse2
|
||||
endif
|
||||
|
||||
# libaesdec
|
||||
SRCS-${CONFIG_SSL} += src/descrambler/libaesdec/libaesdec.c
|
||||
|
||||
# DBUS
|
||||
SRCS-${CONFIG_DBUS_1} += src/dbus.c
|
||||
|
||||
# File bundles
|
||||
SRCS-${CONFIG_BUNDLE} += bundle.c
|
||||
BUNDLES-yes += docs/html docs/docresources src/webui/static
|
||||
|
@ -392,13 +323,6 @@ OBJS = $(SRCS:%.c=$(BUILDDIR)/%.o)
|
|||
OBJS_EXTRA = $(SRCS_EXTRA:%.c=$(BUILDDIR)/%.so)
|
||||
DEPS = ${OBJS:%.o=%.d}
|
||||
|
||||
ifeq ($(CONFIG_LIBFFMPEG_STATIC),yes)
|
||||
DEPS += ${BUILDDIR}/libffmpeg_stamp
|
||||
endif
|
||||
ifeq ($(CONFIG_HDHOMERUN_STATIC),yes)
|
||||
DEPS += ${BUILDDIR}/libhdhomerun_stamp
|
||||
endif
|
||||
|
||||
#
|
||||
# Build Rules
|
||||
#
|
||||
|
@ -439,8 +363,6 @@ clean:
|
|||
find . -name "*~" | xargs rm -f
|
||||
|
||||
distclean: clean
|
||||
rm -rf ${ROOTDIR}/libav_static
|
||||
rm -rf ${ROOTDIR}/libhdhomerun_static
|
||||
rm -rf ${ROOTDIR}/build.*
|
||||
rm -f ${ROOTDIR}/.config.mk
|
||||
|
||||
|
@ -461,43 +383,16 @@ $(BUILDDIR)/bundle.o: $(BUILDDIR)/bundle.c
|
|||
@mkdir -p $(dir $@)
|
||||
$(CC) -I${ROOTDIR}/src -c -o $@ $<
|
||||
|
||||
$(BUILDDIR)/bundle.c: check_dvb_scan
|
||||
$(BUILDDIR)/bundle.c:
|
||||
@mkdir -p $(dir $@)
|
||||
$(MKBUNDLE) -o $@ -d ${BUILDDIR}/bundle.d $(BUNDLE_FLAGS) $(BUNDLES:%=$(ROOTDIR)/%)
|
||||
|
||||
# Static FFMPEG
|
||||
|
||||
ifeq ($(CONFIG_LIBFFMPEG_STATIC),yes)
|
||||
${ROOTDIR}/src/libav.h: ${BUILDDIR}/libffmpeg_stamp
|
||||
${SRCS_LIBAV}: ${BUILDDIR}/libffmpeg_stamp
|
||||
endif
|
||||
|
||||
${BUILDDIR}/libffmpeg_stamp: ${ROOTDIR}/libav_static/build/ffmpeg/lib/libavcodec.a
|
||||
@touch $@
|
||||
|
||||
${ROOTDIR}/libav_static/build/ffmpeg/lib/libavcodec.a:
|
||||
CONFIG_LIBFFMPEG_STATIC_X264=$(CONFIG_LIBFFMPEG_STATIC_X264) \
|
||||
$(MAKE) -f Makefile.ffmpeg build
|
||||
|
||||
# Static HDHOMERUN library
|
||||
|
||||
ifeq ($(CONFIG_LIBHDHOMERUN_STATIC),yes)
|
||||
${ROOTDIR}/src/input/mpegts/tvhdhomerun/tvhdhomerun_private.h: ${BUILDDIR}/libhdhomerun_stamp
|
||||
${SRCS_HDHOMERUN}: ${BUILDDIR}/libhdhomerun_stamp
|
||||
endif
|
||||
|
||||
${BUILDDIR}/libhdhomerun_stamp: ${ROOTDIR}/libhdhomerun_static/libhdhomerun/libhdhomerun.a
|
||||
@touch $@
|
||||
|
||||
${ROOTDIR}/libhdhomerun_static/libhdhomerun/libhdhomerun.a:
|
||||
$(MAKE) -f Makefile.hdhomerun build
|
||||
|
||||
# linuxdvb git tree
|
||||
$(ROOTDIR)/data/dvb-scan/.stamp:
|
||||
@echo "Receiving data/dvb-scan/dvb-t from http://linuxtv.org/git/dtv-scan-tables.git"
|
||||
@rm -rf $(ROOTDIR)/data/dvb-scan/*
|
||||
@$(ROOTDIR)/support/getmuxlist $(ROOTDIR)/data/dvb-scan
|
||||
@touch $@
|
||||
@touch $(ROOTDIR)/data/dvb-scan/.stamp
|
||||
|
||||
.PHONY: check_dvb_scan
|
||||
check_dvb_scan: $(ROOTDIR)/data/dvb-scan/.stamp
|
||||
|
|
248
Makefile.ffmpeg
|
@ -1,248 +0,0 @@
|
|||
#
|
||||
# Static Audio/Video libs (ffmpeg version) build
|
||||
# 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/>.
|
||||
#
|
||||
|
||||
include $(dir $(lastword $(MAKEFILE_LIST))).config.mk
|
||||
|
||||
unexport CFLAGS
|
||||
unexport LDFLAGS
|
||||
|
||||
define DOWNLOAD
|
||||
@mkdir -p $(LIBAVDIR)/build
|
||||
if test -z "$${TVHEADEND_FILE_CACHE}"; then \
|
||||
wget --no-verbose -O $(2) $(1); \
|
||||
else \
|
||||
file=$$(basename $(2)); \
|
||||
cp "$$TVHEADEND_FILE_CACHE/$$(file)" $(2); \
|
||||
fi
|
||||
@{ \
|
||||
sum=$$(sha1sum $(2) | cut -d ' ' -f 1); \
|
||||
printf "SHA1SUM test '$${sum}' == '$(3)': "; \
|
||||
test "y$${sum}" = "y$(3)"; \
|
||||
}
|
||||
@echo "OK"
|
||||
endef
|
||||
|
||||
define UNTAR
|
||||
tar x -C $(LIBAVDIR) -$(2)f $(LIBAVDIR)/$(1)
|
||||
endef
|
||||
|
||||
LIBAVDIR = $(ROOTDIR)/libav_static
|
||||
|
||||
export PATH := $(LIBAVDIR)/build/ffmpeg/bin:$(PATH)
|
||||
|
||||
ECFLAGS = -I$(LIBAVDIR)/build/ffmpeg/include
|
||||
ELIBS = -L$(LIBAVDIR)/build/ffmpeg/lib -ldl
|
||||
|
||||
CONFIGURE = PKG_CONFIG=/tmp/nobin/pkg-config ./configure
|
||||
|
||||
FFMPEG = ffmpeg-2.6.2
|
||||
FFMPEG_TB = $(FFMPEG).tar.bz2
|
||||
FFMPEG_URL = http://ffmpeg.org/releases/$(FFMPEG_TB)
|
||||
FFMPEG_SHA1 = 65470c9b967485f72f81758a7bad44cf7a1763db
|
||||
|
||||
EXTLIBS = libx264 libvorbis libvpx
|
||||
COMPONENTS = avutil avformat avcodec swresample swscale avresample
|
||||
DECODERS = mpeg2video mp2 ac3 eac3 h264 h264_vdpau aac aac_latm vorbis libvorbis
|
||||
ENCODERS = mpeg2video mp2 libx264 libvpx_vp8 libvpx_vp9 aac libaacplus vorbis libvorbis
|
||||
MUXERS = mpegts mpeg2dvd matroska webm
|
||||
BSFS = h264_mp4toannexb
|
||||
|
||||
LIBOGG = libogg-1.3.2
|
||||
LIBOGG_TB = $(LIBOGG).tar.gz
|
||||
LIBOGG_URL = http://downloads.xiph.org/releases/ogg/$(LIBOGG_TB)
|
||||
LIBOGG_SHA1 = df7f3977bbeda67306bc2a427257dd7375319d7d
|
||||
|
||||
LIBVORBIS = libvorbis-1.3.4
|
||||
LIBVORBIS_TB = $(LIBVORBIS).tar.gz
|
||||
LIBVORBIS_URL = http://downloads.xiph.org/releases/vorbis/$(LIBVORBIS_TB)
|
||||
LIBVORBIS_SHA1 = 1602716c187593ffe4302124535240cec2079df3
|
||||
|
||||
LIBX264 = x264-snapshot-20141218-2245
|
||||
LIBX264_TB = $(LIBX264).tar.bz2
|
||||
LIBX264_URL = http://ftp.via.ecp.fr/pub/videolan/x264/snapshots/$(LIBX264_TB)
|
||||
LIBX264_SHA1 = 24a3b20e2c49a112e40df9f64885cbd81250298a
|
||||
|
||||
LIBVPX = libvpx-v1.3.0
|
||||
LIBVPX_TB = $(LIBVPX).tar.bz2
|
||||
LIBVPX_URL = https://webm.googlecode.com/files/$(LIBVPX_TB)
|
||||
LIBVPX_SHA1 = 191b95817aede8c136cc3f3745fb1b8c50e6d5dc
|
||||
|
||||
YASM = yasm-1.3.0
|
||||
YASM_TB = $(YASM).tar.gz
|
||||
YASM_URL = http://www.tortall.net/projects/yasm/releases/$(YASM_TB)
|
||||
YASM_SHA1 = b7574e9f0826bedef975d64d3825f75fbaeef55e
|
||||
|
||||
.PHONY: build
|
||||
build: $(LIBAVDIR)/$(FFMPEG)/.tvh_build
|
||||
|
||||
#
|
||||
# YASM
|
||||
#
|
||||
|
||||
$(LIBAVDIR)/$(YASM)/.tvh_download:
|
||||
$(call DOWNLOAD,$(YASM_URL),$(LIBAVDIR)/$(YASM_TB),$(YASM_SHA1))
|
||||
$(call UNTAR,$(YASM_TB),z)
|
||||
@touch $@
|
||||
|
||||
$(LIBAVDIR)/$(YASM)/.tvh_build: \
|
||||
$(LIBAVDIR)/$(YASM)/.tvh_download
|
||||
cd $(LIBAVDIR)/$(YASM) && $(CONFIGURE) \
|
||||
--prefix=/ffmpeg
|
||||
DESTDIR=$(LIBAVDIR)/build \
|
||||
$(MAKE) -C $(LIBAVDIR)/$(YASM) install
|
||||
@touch $@
|
||||
|
||||
#
|
||||
# libogg & libvorbis
|
||||
#
|
||||
|
||||
$(LIBAVDIR)/$(LIBOGG)/.tvh_download:
|
||||
$(call DOWNLOAD,$(LIBOGG_URL),$(LIBAVDIR)/$(LIBOGG_TB),$(LIBOGG_SHA1))
|
||||
$(call UNTAR,$(LIBOGG_TB),z)
|
||||
@touch $@
|
||||
|
||||
$(LIBAVDIR)/$(LIBOGG)/.tvh_build: \
|
||||
$(LIBAVDIR)/$(YASM)/.tvh_build \
|
||||
$(LIBAVDIR)/$(LIBOGG)/.tvh_download
|
||||
cd $(LIBAVDIR)/$(LIBOGG) && $(CONFIGURE) \
|
||||
--prefix=/ffmpeg \
|
||||
--enable-static \
|
||||
--disable-shared
|
||||
DESTDIR=$(LIBAVDIR)/build \
|
||||
$(MAKE) -C $(LIBAVDIR)/$(LIBOGG) install
|
||||
@touch $@
|
||||
|
||||
$(LIBAVDIR)/$(LIBVORBIS)/.tvh_download: \
|
||||
$(LIBAVDIR)/$(LIBOGG)/.tvh_download
|
||||
$(call DOWNLOAD,$(LIBVORBIS_URL),$(LIBAVDIR)/$(LIBVORBIS_TB),$(LIBVORBIS_SHA1))
|
||||
$(call UNTAR,$(LIBVORBIS_TB),z)
|
||||
@touch $@
|
||||
|
||||
$(LIBAVDIR)/$(LIBVORBIS)/.tvh_build: \
|
||||
$(LIBAVDIR)/$(LIBVORBIS)/.tvh_download \
|
||||
$(LIBAVDIR)/$(YASM)/.tvh_build \
|
||||
$(LIBAVDIR)/$(LIBOGG)/.tvh_build
|
||||
cd $(LIBAVDIR)/$(LIBVORBIS) && $(CONFIGURE) \
|
||||
--prefix=/ffmpeg \
|
||||
--enable-static \
|
||||
--disable-shared \
|
||||
--with-ogg=$(LIBAVDIR)/build/ffmpeg
|
||||
DESTDIR=$(LIBAVDIR)/build \
|
||||
$(MAKE) -C $(LIBAVDIR)/$(LIBVORBIS) install
|
||||
@touch $@
|
||||
|
||||
#
|
||||
# libx264
|
||||
#
|
||||
|
||||
ifneq (yes,$(CONFIG_LIBFFMPEG_STATIC_X264))
|
||||
|
||||
$(LIBAVDIR)/$(LIBX264)/.tvh_download:
|
||||
@echo "***** LIBX264 STATIC BUILD IS DISABLED, USING INSTALLED PACKAGE *****"
|
||||
@mkdir -p $(LIBAVDIR)/$(LIBX264)
|
||||
@touch $@
|
||||
|
||||
$(LIBAVDIR)/$(LIBX264)/.tvh_build: $(LIBAVDIR)/$(LIBX264)/.tvh_download
|
||||
@touch $@
|
||||
|
||||
else
|
||||
|
||||
$(LIBAVDIR)/$(LIBX264)/.tvh_download:
|
||||
$(call DOWNLOAD,$(LIBX264_URL),$(LIBAVDIR)/$(LIBX264_TB),$(LIBX264_SHA1))
|
||||
#rm -rf $(LIBAVDIR)/x264-snapshot-*
|
||||
$(call UNTAR,$(LIBX264_TB),j)
|
||||
#{ ln -sf $$(basename $(LIBAVDIR)/x264-snapshot-*) $(LIBAVDIR)/$(LIBX264); }
|
||||
@touch $@
|
||||
|
||||
$(LIBAVDIR)/$(LIBX264)/.tvh_build: \
|
||||
$(LIBAVDIR)/$(LIBX264)/.tvh_download \
|
||||
$(LIBAVDIR)/$(YASM)/.tvh_build
|
||||
cd $(LIBAVDIR)/$(LIBX264) && $(CONFIGURE) \
|
||||
--prefix=/ffmpeg \
|
||||
--enable-static \
|
||||
--disable-shared \
|
||||
--disable-avs \
|
||||
--disable-swscale \
|
||||
--disable-lavf \
|
||||
--disable-ffms \
|
||||
--disable-gpac \
|
||||
--disable-lsmash
|
||||
DESTDIR=$(LIBAVDIR)/build \
|
||||
$(MAKE) -C $(LIBAVDIR)/$(LIBX264) install
|
||||
@touch $@
|
||||
|
||||
endif
|
||||
|
||||
#
|
||||
# libvpx (VP8)
|
||||
#
|
||||
|
||||
$(LIBAVDIR)/$(LIBVPX)/.tvh_download:
|
||||
@mkdir -p $(LIBAVDIR)
|
||||
$(call DOWNLOAD,$(LIBVPX_URL),$(LIBAVDIR)/$(LIBVPX_TB),$(LIBVPX_SHA1))
|
||||
$(call UNTAR,$(LIBVPX_TB),j)
|
||||
@touch $@
|
||||
|
||||
$(LIBAVDIR)/$(LIBVPX)/.tvh_build: \
|
||||
$(LIBAVDIR)/$(LIBVPX)/.tvh_download \
|
||||
$(LIBAVDIR)/$(YASM)/.tvh_build
|
||||
cd $(LIBAVDIR)/$(LIBVPX) && $(CONFIGURE) \
|
||||
--prefix=/ffmpeg \
|
||||
--enable-static \
|
||||
--disable-shared
|
||||
DIST_DIR=$(LIBAVDIR)/build/ffmpeg \
|
||||
$(MAKE) -C $(LIBAVDIR)/$(LIBVPX) install
|
||||
@touch $@
|
||||
|
||||
#
|
||||
# FFMPEG
|
||||
#
|
||||
|
||||
$(LIBAVDIR)/$(FFMPEG)/.tvh_download:
|
||||
@mkdir -p $(LIBAVDIR)/build
|
||||
$(call DOWNLOAD,$(FFMPEG_URL),$(LIBAVDIR)/$(FFMPEG_TB),$(FFMPEG_SHA1))
|
||||
$(call UNTAR,$(FFMPEG_TB),j)
|
||||
@touch $@
|
||||
|
||||
$(LIBAVDIR)/$(FFMPEG)/.tvh_build: \
|
||||
$(LIBAVDIR)/$(YASM)/.tvh_build \
|
||||
$(LIBAVDIR)/$(LIBVORBIS)/.tvh_build \
|
||||
$(LIBAVDIR)/$(LIBX264)/.tvh_build \
|
||||
$(LIBAVDIR)/$(LIBVPX)/.tvh_build \
|
||||
$(LIBAVDIR)/$(FFMPEG)/.tvh_download
|
||||
cd $(LIBAVDIR)/$(FFMPEG) && $(CONFIGURE) \
|
||||
--prefix=/ffmpeg \
|
||||
--disable-all \
|
||||
--enable-static \
|
||||
--disable-shared \
|
||||
--enable-gpl \
|
||||
--extra-cflags="$(ECFLAGS)" \
|
||||
--extra-libs="$(ELIBS)" \
|
||||
$(foreach extlib,$(EXTLIBS),--enable-$(extlib)) \
|
||||
$(foreach component,$(COMPONENTS),--enable-$(component)) \
|
||||
$(foreach decoder,$(DECODERS),--enable-decoder=$(decoder)) \
|
||||
$(foreach encoder,$(ENCODERS),--enable-encoder=$(encoder)) \
|
||||
$(foreach muxer,$(MUXERS),--enable-muxer=$(muxer)) \
|
||||
$(foreach bsf,$(BSFS),--enable-bsf=$(bsf))
|
||||
DESTDIR=$(LIBAVDIR)/build \
|
||||
$(MAKE) -C $(LIBAVDIR)/$(FFMPEG) install
|
||||
@touch $@
|
||||
|
||||
.PHONY: static_libav_clean
|
||||
static_libav_clean:
|
||||
@rm -rf $(LIBAVDIR)
|
|
@ -1,83 +0,0 @@
|
|||
#
|
||||
# HDhomerun library build
|
||||
# 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/>.
|
||||
#
|
||||
|
||||
include $(dir $(lastword $(MAKEFILE_LIST))).config.mk
|
||||
|
||||
unexport CFLAGS
|
||||
unexport LDFLAGS
|
||||
|
||||
define DOWNLOAD
|
||||
@mkdir -p $(LIBHDHRDIR)/build
|
||||
if test -z "$${TVHEADEND_FILE_CACHE}"; then \
|
||||
wget --no-verbose -O $(2) $(1); \
|
||||
else \
|
||||
file=$$(basename $(2)); \
|
||||
cp "$$TVHEADEND_FILE_CACHE/$$(file)" $(2); \
|
||||
fi
|
||||
@{ \
|
||||
sum=$$(sha1sum $(2) | cut -d ' ' -f 1); \
|
||||
printf "SHA1SUM test '$${sum}' == '$(3)': "; \
|
||||
test "y$${sum}" = "y$(3)"; \
|
||||
}
|
||||
@echo "OK"
|
||||
endef
|
||||
|
||||
define UNTAR
|
||||
tar x -C $(LIBHDHRDIR) -$(2)f $(LIBHDHRDIR)/$(1)
|
||||
endef
|
||||
|
||||
LIBHDHRDIR = $(ROOTDIR)/libhdhomerun_static
|
||||
|
||||
export PATH := $(LIBHDHRDIR)/build/bin:$(PATH)
|
||||
|
||||
LIBHDHR = libhdhomerun_20150406
|
||||
LIBHDHR_TB = $(LIBHDHR).tgz
|
||||
LIBHDHR_URL = http://download.silicondust.com/hdhomerun/$(LIBHDHR_TB)
|
||||
LIBHDHR_SHA1 = f0d5da744d981a80becea6cc862b5e2519e1c3c6
|
||||
|
||||
.PHONY: build
|
||||
build: $(LIBHDHRDIR)/$(LIBHDHR)/.tvh_build
|
||||
|
||||
#
|
||||
# libhdhomerun
|
||||
#
|
||||
|
||||
-include $(LIBHDHRDIR)/$(LIBHDHR)/Makefile
|
||||
|
||||
OBJS = $(foreach file,$(LIBSRCS),$(LIBHDHRDIR)/$(LIBHDHR)/$(basename $(file)).o)
|
||||
|
||||
$(LIBHDHRDIR)/$(LIBHDHR)/%.o: $(LIBHDHRDIR)/$(LIBHDHR)/%.c
|
||||
$(CC) -MD -MP $(CFLAGS) -c -o $@ $<
|
||||
|
||||
$(LIBHDHRDIR)/$(LIBHDHR)/libhdhomerun.a: $(OBJS)
|
||||
$(AR) rcs $@ $^
|
||||
|
||||
$(LIBHDHRDIR)/$(LIBHDHR)/.tvh_download:
|
||||
$(call DOWNLOAD,$(LIBHDHR_URL),$(LIBHDHRDIR)/$(LIBHDHR_TB),$(LIBHDHR_SHA1))
|
||||
$(call UNTAR,$(LIBHDHR_TB),z)
|
||||
ln -sf libhdhomerun $(LIBHDHRDIR)/$(LIBHDHR)
|
||||
@touch $@
|
||||
|
||||
$(LIBHDHRDIR)/$(LIBHDHR)/.tvh_build: \
|
||||
$(LIBHDHRDIR)/$(LIBHDHR)/.tvh_download
|
||||
$(MAKE) -f Makefile.hdhomerun $(LIBHDHRDIR)/$(LIBHDHR)/libhdhomerun.a
|
||||
@touch $@
|
||||
|
||||
.PHONY: static_libhdhr_clean
|
||||
static_libhdhr_clean:
|
||||
@rm -rf $(LIBHDHRDIR)
|
14
README.md
|
@ -1,6 +1,6 @@
|
|||
Tvheadend
|
||||
========================================
|
||||
(c) 2006 - 2015 Tvheadend Foundation CIC
|
||||
====================================
|
||||
(c) 2006 - 2014 Tvheadend Foundation CIC
|
||||
|
||||
|
||||
What it is
|
||||
|
@ -10,22 +10,14 @@ Tvheadend is a TV streaming server and digital video recorder.
|
|||
|
||||
It supports the following inputs:
|
||||
|
||||
* DVB-C(2)
|
||||
* DVB-C
|
||||
* DVB-T(2)
|
||||
* DVB-S(2)
|
||||
* ATSC
|
||||
* SAT>IP
|
||||
* HDHomeRun
|
||||
* IPTV
|
||||
* UDP
|
||||
* HTTP
|
||||
|
||||
It support the following outputs:
|
||||
|
||||
* HTTP
|
||||
* HTSP (own protocol)
|
||||
* SAT>IP
|
||||
|
||||
How to build for Linux
|
||||
----------------------
|
||||
|
||||
|
|
259
configure
vendored
|
@ -10,7 +10,6 @@
|
|||
# ###########################################################################
|
||||
|
||||
ROOTDIR=$(cd "$(dirname "$0")"; pwd)
|
||||
test -z "$PKG_CONFIG" && PKG_CONFIG=pkg-config
|
||||
|
||||
#
|
||||
# Options
|
||||
|
@ -19,12 +18,9 @@ test -z "$PKG_CONFIG" && PKG_CONFIG=pkg-config
|
|||
OPTIONS=(
|
||||
"cwc:yes"
|
||||
"capmt:yes"
|
||||
"constcw:yes"
|
||||
"v4l:no"
|
||||
"linuxdvb:yes"
|
||||
"satip_server:yes"
|
||||
"satip_client:yes"
|
||||
"hdhomerun_client:auto"
|
||||
"hdhomerun_static:no"
|
||||
"iptv:yes"
|
||||
"tsfile:yes"
|
||||
"dvbscan:yes"
|
||||
|
@ -34,8 +30,6 @@ OPTIONS=(
|
|||
"avahi:auto"
|
||||
"zlib:auto"
|
||||
"libav:auto"
|
||||
"libffmpeg_static:no"
|
||||
"libffmpeg_static_x264:yes"
|
||||
"inotify:auto"
|
||||
"epoll:auto"
|
||||
"uriparser:auto"
|
||||
|
@ -43,12 +37,7 @@ OPTIONS=(
|
|||
"tvhcsa:auto"
|
||||
"bundle:no"
|
||||
"dvbcsa:no"
|
||||
"dvben50221:auto"
|
||||
"kqueue:no"
|
||||
"dbus_1:auto"
|
||||
"android:no"
|
||||
"tsdebug:no"
|
||||
"gtimer_check:no"
|
||||
)
|
||||
|
||||
#
|
||||
|
@ -56,36 +45,7 @@ OPTIONS=(
|
|||
#
|
||||
|
||||
. "$ROOTDIR/support/configure.inc"
|
||||
|
||||
# ###########################################################################
|
||||
# Parse arguments
|
||||
# ###########################################################################
|
||||
opt=
|
||||
val=
|
||||
for opt do
|
||||
val=${opt#*=}
|
||||
opt=${opt%=*}
|
||||
opt=${opt#*--}
|
||||
case "$opt" in
|
||||
help)
|
||||
show_help
|
||||
;;
|
||||
*dir|prefix)
|
||||
eval "$opt=$val"
|
||||
;;
|
||||
cc|cflags|ldflags|arch|cpu|platform|python)
|
||||
eval "$(toupper $opt)=\"$val\""
|
||||
;;
|
||||
enable-*)
|
||||
opt=${opt#*-}
|
||||
enable $opt 1
|
||||
;;
|
||||
disable-*)
|
||||
opt=${opt#*-}
|
||||
disable $opt 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
parse_args $*
|
||||
|
||||
# ###########################################################################
|
||||
# Checks
|
||||
|
@ -165,17 +125,6 @@ int test(void)
|
|||
}
|
||||
'
|
||||
|
||||
check_cc_snippet stime '
|
||||
#include <time.h>
|
||||
#define TEST test
|
||||
int test(void)
|
||||
{
|
||||
time_t t = 1;
|
||||
stime(&t);
|
||||
return 0;
|
||||
}
|
||||
'
|
||||
|
||||
check_cc_snippet recvmmsg '
|
||||
#define _GNU_SOURCE
|
||||
#include <stdlib.h>
|
||||
|
@ -188,18 +137,6 @@ int test(void)
|
|||
}
|
||||
'
|
||||
|
||||
check_cc_snippet sendmmsg '
|
||||
#define _GNU_SOURCE
|
||||
#include <stdlib.h>
|
||||
#include <sys/socket.h>
|
||||
#define TEST test
|
||||
int test(void)
|
||||
{
|
||||
sendmmsg(0, NULL, 0, 0);
|
||||
return 0;
|
||||
}
|
||||
'
|
||||
|
||||
check_cc_snippet libiconv '
|
||||
#include <iconv.h>
|
||||
int test(void)
|
||||
|
@ -209,23 +146,6 @@ int test(void)
|
|||
}
|
||||
' -liconv
|
||||
|
||||
if enabled_or_auto dvben50221; then
|
||||
check_cc_snippet libdvben50221 '
|
||||
#include <libdvben50221/en50221_session.h>
|
||||
#define TEST test
|
||||
int test(void)
|
||||
{
|
||||
struct en50221_transport_layer *tl = en50221_tl_create(5, 32);
|
||||
return 0;
|
||||
}
|
||||
' '-ldvben50221 -ldvbapi -lucsi'
|
||||
if enabled libdvben50221; then
|
||||
enable dvben50221
|
||||
else
|
||||
disable dvben50221
|
||||
fi
|
||||
fi
|
||||
|
||||
#
|
||||
# Python
|
||||
#
|
||||
|
@ -245,8 +165,6 @@ if [ ${PLATFORM} = "freebsd" ]; then
|
|||
enable ssl
|
||||
elif check_pkg openssl || check_pkg libssl; then
|
||||
enable ssl
|
||||
elif check_cc_header 'openssl/ssl' ssl; then
|
||||
enable ssl
|
||||
else
|
||||
die "SSL development support not found"
|
||||
fi
|
||||
|
@ -272,24 +190,6 @@ if enabled_or_auto linuxdvb; then
|
|||
fi
|
||||
fi
|
||||
|
||||
#
|
||||
# HDHomeRun - libhdhomerun
|
||||
#
|
||||
if enabled hdhomerun_static; then
|
||||
|
||||
enable hdhomerun_client
|
||||
|
||||
else
|
||||
|
||||
if enabled_or_auto hdhomerun_client; then
|
||||
if check_cc_header 'libhdhomerun/hdhomerun' libhdhomerun; then
|
||||
enable hdhomerun_client
|
||||
LDFLAGS="$LDFLAGS -lhdhomerun"
|
||||
fi
|
||||
fi
|
||||
|
||||
fi
|
||||
|
||||
#
|
||||
# Gzip
|
||||
#
|
||||
|
@ -301,13 +201,6 @@ if enabled_or_auto zlib; then
|
|||
fi
|
||||
fi
|
||||
|
||||
#
|
||||
# SAT>IP server
|
||||
#
|
||||
if enabled_or_auto satip_server; then
|
||||
enable upnp
|
||||
fi
|
||||
|
||||
#
|
||||
# SAT>IP client
|
||||
#
|
||||
|
@ -349,93 +242,38 @@ fi
|
|||
#
|
||||
# libav
|
||||
#
|
||||
if enabled libffmpeg_static; then
|
||||
|
||||
enable libav
|
||||
if enabled_or_auto libav; then
|
||||
has_libav=true
|
||||
|
||||
else
|
||||
|
||||
if enabled_or_auto libav; then
|
||||
has_libav=true
|
||||
|
||||
ffmpeg=$(${PKG_CONFIG} --modversion libavcodec | cut -d '.' -f 3)
|
||||
test -z "$ffmpeg" && ffmpeg=0
|
||||
printf "$TAB" "checking for ffmpeg libraries ..."
|
||||
if test $ffmpeg -lt 100; then
|
||||
ffmpeg=
|
||||
echo "fail"
|
||||
else
|
||||
ffmpeg=yes
|
||||
echo "ok"
|
||||
fi
|
||||
|
||||
if test "$ffmpeg" == "yes"; then
|
||||
|
||||
#
|
||||
# check for version n1.2+
|
||||
#
|
||||
if $has_libav && ! check_pkg libavcodec ">=55.18.102"; then
|
||||
has_libav=false
|
||||
fi
|
||||
|
||||
if $has_libav && ! check_pkg libavutil ">=52.38.100"; then
|
||||
has_libav=false
|
||||
fi
|
||||
|
||||
if $has_libav && ! check_pkg libavformat ">=55.12.100"; then
|
||||
has_libav=false
|
||||
fi
|
||||
|
||||
if $has_libav && ! check_pkg libswscale ">=2.3.100"; then
|
||||
has_libav=false
|
||||
fi
|
||||
|
||||
if $has_libav && ! check_pkg libavresample ">=1.1.0"; then
|
||||
has_libav=false
|
||||
fi
|
||||
|
||||
else
|
||||
|
||||
#
|
||||
# check for version v10+
|
||||
#
|
||||
|
||||
if $has_libav && ! check_pkg libavcodec ">=55.34.1"; then
|
||||
has_libav=false
|
||||
fi
|
||||
|
||||
if $has_libav && ! check_pkg libavutil ">=53.3.0"; then
|
||||
has_libav=false
|
||||
fi
|
||||
|
||||
if $has_libav && ! check_pkg libavformat ">=55.12.0"; then
|
||||
has_libav=false
|
||||
fi
|
||||
|
||||
if $has_libav && ! check_pkg libswscale ">=2.1.2"; then
|
||||
has_libav=false
|
||||
fi
|
||||
|
||||
if $has_libav && ! check_pkg libavresample ">=1.1.0"; then
|
||||
has_libav=false
|
||||
fi
|
||||
|
||||
fi
|
||||
|
||||
if $has_libav; then
|
||||
enable libav
|
||||
else
|
||||
echo "WARNING: none or old libav or libffmpeg libraries were detected"
|
||||
echo " * use --disable-libav or --enable-libffmpeg_static"
|
||||
echo " ** supported ffmpeg libs n1.2+"
|
||||
echo " ** supported libav libs v10+"
|
||||
if enabled libav; then
|
||||
die "libav development support not found"
|
||||
fi
|
||||
fi
|
||||
if $has_libav && ! check_pkg libavcodec "<=55.0.0"; then
|
||||
has_libav=false
|
||||
fi
|
||||
|
||||
if $has_libav && ! check_pkg libavcodec ">=52.96.0"; then
|
||||
has_libav=false
|
||||
fi
|
||||
|
||||
if $has_libav && ! check_pkg libavutil ">=50.43.0"; then
|
||||
has_libav=false
|
||||
fi
|
||||
|
||||
if $has_libav && ! check_pkg libavformat "<=55.0.0"; then
|
||||
has_libav=false
|
||||
fi
|
||||
|
||||
if $has_libav && ! check_pkg libavformat ">=53.10.0"; then
|
||||
has_libav=false
|
||||
fi
|
||||
|
||||
if $has_libav && ! check_pkg libswscale ">=0.13.0"; then
|
||||
has_libav=false
|
||||
fi
|
||||
|
||||
if $has_libav; then
|
||||
enable libav
|
||||
elif enabled libav; then
|
||||
die "libav development support not found (use --disable-libav)"
|
||||
fi
|
||||
fi
|
||||
|
||||
#
|
||||
|
@ -452,7 +290,7 @@ fi
|
|||
#
|
||||
# libdvbcsa, tvhcsa
|
||||
#
|
||||
if enabled cwc || enabled capmt || enabled constcw; then
|
||||
if enabled cwc || enabled capmt; then
|
||||
enable tvhcsa
|
||||
if enabled dvbcsa; then
|
||||
(check_cc_header "dvbcsa/dvbcsa" dvbcsa_h &&\
|
||||
|
@ -462,14 +300,6 @@ if enabled cwc || enabled capmt || enabled constcw; then
|
|||
fi
|
||||
fi
|
||||
|
||||
#
|
||||
# libdvben50221
|
||||
#
|
||||
if enabled libdvben50221; then
|
||||
LDFLAGS="$LDFLAGS -ldvben50221 -ldvbapi -lucsi"
|
||||
enable linuxdvb_ca
|
||||
fi
|
||||
|
||||
#
|
||||
# Icon caching
|
||||
#
|
||||
|
@ -505,38 +335,23 @@ if [ ${PLATFORM} = "freebsd" ] || [ ${PLATFORM} = "darwin" ]; then
|
|||
fi
|
||||
|
||||
#
|
||||
# MPEGTS support
|
||||
# MPEGTS/PS support
|
||||
#
|
||||
disable mpegts
|
||||
disable mpegps
|
||||
disable mpegts_dvb
|
||||
if enabled linuxdvb || enabled iptv || enabled tsfile || enabled satip_client || \
|
||||
enabled hdhomerun_client || enabled satip_server;
|
||||
if enabled linuxdvb || enabled iptv || enabled tsfile || enabled satip_client;
|
||||
then
|
||||
enable mpegts
|
||||
fi
|
||||
if enabled linuxdvb || enabled satip_client || enabled hdhomerun_client || enabled satip_server; then
|
||||
if enabled linuxdvb || enabled satip_client; then
|
||||
enable mpegts_dvb
|
||||
fi
|
||||
|
||||
#
|
||||
# DBus
|
||||
#
|
||||
if enabled_or_auto dbus_1; then
|
||||
if check_pkg dbus-1; then
|
||||
enable dbus_1
|
||||
elif enabled dbus-1; then
|
||||
die "DBus-1 development support not found (use --disable-dbus-1)"
|
||||
fi
|
||||
if enabled v4l; then
|
||||
enable mpegps
|
||||
fi
|
||||
|
||||
#
|
||||
# TSDebug
|
||||
#
|
||||
if enabled_or_auto tsdebug; then
|
||||
enable mpegts_dvb
|
||||
fi
|
||||
|
||||
|
||||
# ###########################################################################
|
||||
# Write config
|
||||
# ###########################################################################
|
||||
|
|
968
data/conf/charset
Normal file
|
@ -0,0 +1,968 @@
|
|||
[
|
||||
{
|
||||
"tsid": 1050,
|
||||
"onid": 1,
|
||||
"charset": "ISO8859-15",
|
||||
"sid": 0,
|
||||
"description": "Astra 19.2E Canal + Spain 10729.00 V"
|
||||
},
|
||||
{
|
||||
"tsid": 1028,
|
||||
"onid": 1,
|
||||
"charset": "ISO8859-15",
|
||||
"sid": 0,
|
||||
"description": "Astra 19.2E Canal + Spain 10758.50 V"
|
||||
},
|
||||
{
|
||||
"tsid": 1054,
|
||||
"onid": 1,
|
||||
"charset": "ISO8859-15",
|
||||
"sid": 0,
|
||||
"description": "Astra 19.2E Canal + Spain 10788.00 V"
|
||||
},
|
||||
{
|
||||
"tsid": 1056,
|
||||
"onid": 1,
|
||||
"charset": "ISO8859-15",
|
||||
"sid": 0,
|
||||
"description": "Astra 19.2E Canal + Spain 10817.50 V"
|
||||
},
|
||||
{
|
||||
"tsid": 1058,
|
||||
"onid": 1,
|
||||
"charset": "ISO8859-15",
|
||||
"sid": 0,
|
||||
"description": "Astra 19.2E Canal + Spain 10847.00 V"
|
||||
},
|
||||
{
|
||||
"tsid": 1060,
|
||||
"onid": 1,
|
||||
"charset": "ISO8859-15",
|
||||
"sid": 0,
|
||||
"description": "Astra 19.2E Canal + Spain 10876.50 V"
|
||||
},
|
||||
{
|
||||
"tsid": 1064,
|
||||
"onid": 1,
|
||||
"charset": "ISO8859-15",
|
||||
"sid": 0,
|
||||
"description": "Astra 19.2E Canal + Spain 10935.50 V"
|
||||
},
|
||||
{
|
||||
"tsid": 1034,
|
||||
"onid": 1,
|
||||
"charset": "ISO8859-15",
|
||||
"sid": 0,
|
||||
"description": "Astra 19.2E Canal + Spain 10979.00 V"
|
||||
},
|
||||
{
|
||||
"tsid": 1038,
|
||||
"onid": 1,
|
||||
"charset": "ISO8859-15",
|
||||
"sid": 0,
|
||||
"description": "Astra 19.2E Canal + Spain 11038.00 V"
|
||||
},
|
||||
{
|
||||
"tsid": 1040,
|
||||
"onid": 1,
|
||||
"charset": "ISO8859-15",
|
||||
"sid": 0,
|
||||
"description": "Astra 19.2E Canal + Spain 11068.00 V"
|
||||
},
|
||||
{
|
||||
"tsid": 1042,
|
||||
"onid": 1,
|
||||
"charset": "ISO8859-15",
|
||||
"sid": 0,
|
||||
"description": "Astra 19.2E Canal + Spain 11097.00 V"
|
||||
},
|
||||
{
|
||||
"tsid": 1044,
|
||||
"onid": 1,
|
||||
"charset": "ISO8859-15",
|
||||
"sid": 0,
|
||||
"description": "Astra 19.2E Canal + Spain 11126.50 V"
|
||||
},
|
||||
{
|
||||
"tsid": 1046,
|
||||
"onid": 1,
|
||||
"charset": "ISO8859-15",
|
||||
"sid": 0,
|
||||
"description": "Astra 19.2E Canal + Spain 11156.00 V"
|
||||
},
|
||||
{
|
||||
"tsid": 1048,
|
||||
"onid": 1,
|
||||
"charset": "ISO8859-15",
|
||||
"sid": 0,
|
||||
"description": "Astra 19.2E Canal + Spain 11185.50 V xx"
|
||||
},
|
||||
{
|
||||
"tsid": 1004,
|
||||
"onid": 1,
|
||||
"charset": "ISO8859-15",
|
||||
"sid": 0,
|
||||
"description": "Astra 19.2E Canal + Spain 11258.50 V"
|
||||
},
|
||||
{
|
||||
"tsid": 1008,
|
||||
"onid": 1,
|
||||
"charset": "ISO8859-15",
|
||||
"sid": 0,
|
||||
"description": "Astra 19.2E Canal + Spain 11317.50 V"
|
||||
},
|
||||
{
|
||||
"tsid": 1016,
|
||||
"onid": 1,
|
||||
"charset": "ISO8859-15",
|
||||
"sid": 0,
|
||||
"description": "Astra 19.2E Canal + Spain 11435.50 V"
|
||||
},
|
||||
{
|
||||
"tsid": 1032,
|
||||
"onid": 1,
|
||||
"charset": "ISO8859-15",
|
||||
"sid": 0,
|
||||
"description": "Astra 19.2E Canal + Spain 11685.50 V"
|
||||
},
|
||||
{
|
||||
"tsid": 1066,
|
||||
"onid": 1,
|
||||
"charset": "ISO8859-15",
|
||||
"sid": 0,
|
||||
"description": "Astra 19.2E Canal + Spain 11739.00 V"
|
||||
},
|
||||
{
|
||||
"tsid": 1,
|
||||
"onid": 133,
|
||||
"charset": "ISO-8859-15",
|
||||
"sid": 0,
|
||||
"description": "Astra 19.2E Sky Germany 12070.50 H"
|
||||
},
|
||||
{
|
||||
"tsid": 2,
|
||||
"onid": 133,
|
||||
"charset": "ISO-8859-15",
|
||||
"sid": 0,
|
||||
"description": "Astra 19.2E Sky Germany 11797.50 H"
|
||||
},
|
||||
{
|
||||
"tsid": 3,
|
||||
"onid": 133,
|
||||
"charset": "ISO-8859-15",
|
||||
"sid": 0,
|
||||
"description": "Astra 19.2E Sky Germany 11719.50 H"
|
||||
},
|
||||
{
|
||||
"tsid": 4,
|
||||
"onid": 133,
|
||||
"charset": "ISO-8859-15",
|
||||
"sid": 0,
|
||||
"description": "Astra 19.2E Sky Germany 12031.50 H"
|
||||
},
|
||||
{
|
||||
"tsid": 6,
|
||||
"onid": 133,
|
||||
"charset": "ISO-8859-15",
|
||||
"sid": 0,
|
||||
"description": "Astra 19.2E Sky Germany 11914.50 H"
|
||||
},
|
||||
{
|
||||
"tsid": 10,
|
||||
"onid": 133,
|
||||
"charset": "ISO-8859-15",
|
||||
"sid": 0,
|
||||
"description": "Astra 19.2E Sky Germany 11332.25 H"
|
||||
},
|
||||
{
|
||||
"tsid": 11,
|
||||
"onid": 133,
|
||||
"charset": "ISO-8859-15",
|
||||
"sid": 0,
|
||||
"description": "Astra 19.2E Sky Germany 12382.50 H"
|
||||
},
|
||||
{
|
||||
"tsid": 12,
|
||||
"onid": 133,
|
||||
"charset": "ISO-8859-15",
|
||||
"sid": 0,
|
||||
"description": "Astra 19.2E Sky Germany 12304.50 H"
|
||||
},
|
||||
{
|
||||
"tsid": 13,
|
||||
"onid": 133,
|
||||
"charset": "ISO-8859-15",
|
||||
"sid": 0,
|
||||
"description": "Astra 19.2E Sky Germany 11992.50 H"
|
||||
},
|
||||
{
|
||||
"tsid": 14,
|
||||
"onid": 133,
|
||||
"charset": "ISO-8859-15",
|
||||
"sid": 0,
|
||||
"description": "Astra 19.2E Sky Germany 11875.50 H"
|
||||
},
|
||||
{
|
||||
"tsid": 15,
|
||||
"onid": 133,
|
||||
"charset": "ISO-8859-15",
|
||||
"sid": 0,
|
||||
"description": "Astra 19.2E Sky Germany 10920.75 H"
|
||||
},
|
||||
{
|
||||
"tsid": 17,
|
||||
"onid": 133,
|
||||
"charset": "ISO-8859-15",
|
||||
"sid": 0,
|
||||
"description": "Astra 19.2E Sky Germany 11758.50 H"
|
||||
},
|
||||
{
|
||||
"tsid": 33,
|
||||
"onid": 133,
|
||||
"charset": "ISO-8859-15",
|
||||
"sid": 0,
|
||||
"description": "Astra 19.2E Sky Germany 12480.00 V"
|
||||
},
|
||||
{
|
||||
"tsid": 1048,
|
||||
"onid": 1,
|
||||
"charset": "PL_AUTO",
|
||||
"sid": 4310,
|
||||
"description": "Astra 19.2E TV Trwam"
|
||||
},
|
||||
{
|
||||
"tsid": 1059,
|
||||
"onid": 1,
|
||||
"charset": "PL_AUTO",
|
||||
"sid": 0,
|
||||
"description": "Astra 19.2E TVP"
|
||||
},
|
||||
{
|
||||
"tsid": 3218,
|
||||
"onid": 3,
|
||||
"charset": "ISO-8859-5",
|
||||
"sid": 0,
|
||||
"description": "Astra 23.5E Satellite BG 12051.00 V"
|
||||
},
|
||||
{
|
||||
"tsid": 3226,
|
||||
"onid": 3,
|
||||
"charset": "ISO-8859-5",
|
||||
"sid": 0,
|
||||
"description": "Astra 23.5E Satellite BG 12207.00 V"
|
||||
},
|
||||
{
|
||||
"tsid": 8100,
|
||||
"onid": 156,
|
||||
"charset": "PL_AUTO",
|
||||
"sid": 1500,
|
||||
"description": "Eurobird 9.0E TV Polonia"
|
||||
},
|
||||
{
|
||||
"tsid": 8300,
|
||||
"onid": 156,
|
||||
"charset": "PL_AUTO",
|
||||
"sid": 620,
|
||||
"description": "Eurobird 9.0E TVN International"
|
||||
},
|
||||
{
|
||||
"tsid": 200,
|
||||
"onid": 318,
|
||||
"charset": "ISO-8859-7",
|
||||
"sid": 13805,
|
||||
"description": "Hotbird 13.0 Eutelsat Eurosport GR"
|
||||
},
|
||||
{
|
||||
"tsid": 200,
|
||||
"onid": 318,
|
||||
"charset": "PL_AUTO",
|
||||
"sid": 13834,
|
||||
"description": "Hotbird 13.0 Eutelsat Eurosport PL"
|
||||
},
|
||||
{
|
||||
"tsid": 200,
|
||||
"onid": 318,
|
||||
"charset": "ISO-8859-7",
|
||||
"sid": 13840,
|
||||
"description": "Hotbird 13.0 Eutelsat Eurosport GR"
|
||||
},
|
||||
{
|
||||
"tsid": 200,
|
||||
"onid": 318,
|
||||
"charset": "PL_AUTO",
|
||||
"sid": 13864,
|
||||
"description": "Hotbird 13.0 Eutelsat Eurosport 2 PL"
|
||||
},
|
||||
{
|
||||
"tsid": 200,
|
||||
"onid": 318,
|
||||
"charset": "PL_AUTO",
|
||||
"sid": 13865,
|
||||
"description": "Hotbird 13.0 Eutelsat Eurosport PL"
|
||||
},
|
||||
{
|
||||
"tsid": 200,
|
||||
"onid": 318,
|
||||
"charset": "PL_AUTO",
|
||||
"sid": 13878,
|
||||
"description": "Hotbird 13.0 Eutelsat Eurosport 2 NE PL"
|
||||
},
|
||||
{
|
||||
"tsid": 300,
|
||||
"onid": 318,
|
||||
"charset": "PL_AUTO",
|
||||
"sid": 0,
|
||||
"description": "Hotbird 13.0 NC+ HD PL"
|
||||
},
|
||||
{
|
||||
"tsid": 400,
|
||||
"onid": 318,
|
||||
"charset": "PL_AUTO",
|
||||
"sid": 13020,
|
||||
"description": "Hotbird 13.0 NC+ Canal+ HD PL"
|
||||
},
|
||||
{
|
||||
"tsid": 400,
|
||||
"onid": 318,
|
||||
"charset": "PL_AUTO",
|
||||
"sid": 13022,
|
||||
"description": "Hotbird 13.0 NC+ Canal+ Sport HD Polska"
|
||||
},
|
||||
{
|
||||
"tsid": 400,
|
||||
"onid": 318,
|
||||
"charset": "PL_AUTO",
|
||||
"sid": 13023,
|
||||
"description": "Hotbird 13.0 NC+ Nat Geographic HD Polska"
|
||||
},
|
||||
{
|
||||
"tsid": 400,
|
||||
"onid": 318,
|
||||
"charset": "PL_AUTO",
|
||||
"sid": 13025,
|
||||
"description": "Hotbird 13.0 NC+ Filmbox HD"
|
||||
},
|
||||
{
|
||||
"tsid": 400,
|
||||
"onid": 318,
|
||||
"charset": "PL_AUTO",
|
||||
"sid": 13026,
|
||||
"description": "Hotbird 13.0 NC+ AXN Spin HD"
|
||||
},
|
||||
{
|
||||
"tsid": 400,
|
||||
"onid": 318,
|
||||
"charset": "PL_AUTO",
|
||||
"sid": 13027,
|
||||
"description": "Hotbird 13.0 NC+ TVN 7 HD"
|
||||
},
|
||||
{
|
||||
"tsid": 400,
|
||||
"onid": 318,
|
||||
"charset": "PL_AUTO",
|
||||
"sid": 13070,
|
||||
"description": "Hotbird 13.0 NC+ Eurosport HD PL"
|
||||
},
|
||||
{
|
||||
"tsid": 400,
|
||||
"onid": 318,
|
||||
"charset": "PL_AUTO",
|
||||
"sid": 13080,
|
||||
"description": "Hotbird 13.0 NC+ Eurosport HD PL"
|
||||
},
|
||||
{
|
||||
"tsid": 400,
|
||||
"onid": 318,
|
||||
"charset": "PL_AUTO",
|
||||
"sid": 13081,
|
||||
"description": "Hotbird 13.0 NC+ Eurosport HD PL"
|
||||
},
|
||||
{
|
||||
"tsid": 400,
|
||||
"onid": 318,
|
||||
"charset": "PL_AUTO",
|
||||
"sid": 13082,
|
||||
"description": "Hotbird 13.0 NC+ Eurosport HD PL"
|
||||
},
|
||||
{
|
||||
"tsid": 1000,
|
||||
"onid": 318,
|
||||
"charset": "PL_AUTO",
|
||||
"sid": 0,
|
||||
"description": "Hotbird 13.0 NC+ TVN"
|
||||
},
|
||||
{
|
||||
"tsid": 1100,
|
||||
"onid": 318,
|
||||
"charset": "PL_AUTO",
|
||||
"sid": 0,
|
||||
"description": "Hotbird 13.0 NC+"
|
||||
},
|
||||
{
|
||||
"tsid": 1300,
|
||||
"onid": 318,
|
||||
"charset": "PL_AUTO",
|
||||
"sid": 0,
|
||||
"description": "Hotbird 13.0 NC+"
|
||||
},
|
||||
{
|
||||
"tsid": 1400,
|
||||
"onid": 318,
|
||||
"charset": "PL_AUTO",
|
||||
"sid": 30,
|
||||
"description": "Hotbird 13.0 Nick Junior"
|
||||
},
|
||||
{
|
||||
"tsid": 1400,
|
||||
"onid": 318,
|
||||
"charset": "PL_AUTO",
|
||||
"sid": 31,
|
||||
"description": "Hotbird 13.0 Nickelodeon HD"
|
||||
},
|
||||
{
|
||||
"tsid": 1500,
|
||||
"onid": 318,
|
||||
"charset": "PL_AUTO",
|
||||
"sid": 0,
|
||||
"description": "Hotbird 13.0 NC+"
|
||||
},
|
||||
{
|
||||
"tsid": 1600,
|
||||
"onid": 318,
|
||||
"charset": "PL_AUTO",
|
||||
"sid": 0,
|
||||
"description": "Hotbird 13.0 NC+"
|
||||
},
|
||||
{
|
||||
"tsid": 1800,
|
||||
"onid": 200,
|
||||
"charset": "PL_AUTO",
|
||||
"sid": 3623,
|
||||
"description": "Hotbird 13.0 Polo TV"
|
||||
},
|
||||
{
|
||||
"tsid": 5500,
|
||||
"onid": 318,
|
||||
"charset": "ISO-8859-7",
|
||||
"sid": 0,
|
||||
"description": "Hotbird 13.0 Nova GR"
|
||||
},
|
||||
{
|
||||
"tsid": 6100,
|
||||
"onid": 318,
|
||||
"charset": "ISO-8859-7",
|
||||
"sid": 0,
|
||||
"description": "Hotbird 13.0 Nova GR"
|
||||
},
|
||||
{
|
||||
"tsid": 7100,
|
||||
"onid": 318,
|
||||
"charset": "ISO-8859-7",
|
||||
"sid": 0,
|
||||
"description": "Hotbird 13.0 Nova GR"
|
||||
},
|
||||
{
|
||||
"tsid": 7300,
|
||||
"onid": 318,
|
||||
"charset": "ISO-8859-7",
|
||||
"sid": 0,
|
||||
"description": "Hotbird 13.0 Nova GR"
|
||||
},
|
||||
{
|
||||
"tsid": 7400,
|
||||
"onid": 113,
|
||||
"charset": "PL_AUTO",
|
||||
"sid": 0,
|
||||
"description": "Hotbird 13.0 Cyfrowy Polsat"
|
||||
},
|
||||
{
|
||||
"tsid": 7700,
|
||||
"onid": 318,
|
||||
"charset": "PL_AUTO",
|
||||
"sid": 117,
|
||||
"description": "Hotbird 13.0 Hot TV PL"
|
||||
},
|
||||
{
|
||||
"tsid": 7800,
|
||||
"onid": 113,
|
||||
"charset": "PL_AUTO",
|
||||
"sid": 0,
|
||||
"description": "Hotbird 13.0 Cyfrowy Polsat"
|
||||
},
|
||||
{
|
||||
"tsid": 7900,
|
||||
"onid": 113,
|
||||
"charset": "PL_AUTO",
|
||||
"sid": 0,
|
||||
"description": "Hotbird 13.0 Cyfrowy Polsat"
|
||||
},
|
||||
{
|
||||
"tsid": 8100,
|
||||
"onid": 318,
|
||||
"charset": "PL_AUTO",
|
||||
"sid": 14900,
|
||||
"description": "Hotbird 13.0 Eutelsat Sport Klub PL"
|
||||
},
|
||||
{
|
||||
"tsid": 8100,
|
||||
"onid": 318,
|
||||
"charset": "PL_AUTO",
|
||||
"sid": 14901,
|
||||
"description": "Hotbird 13.0 Eutelsat Universal CE"
|
||||
},
|
||||
{
|
||||
"tsid": 8100,
|
||||
"onid": 318,
|
||||
"charset": "PL_AUTO",
|
||||
"sid": 14902,
|
||||
"description": "Hotbird 13.0 Eutelsat Sci-Fi CE"
|
||||
},
|
||||
{
|
||||
"tsid": 8100,
|
||||
"onid": 318,
|
||||
"charset": "PL_AUTO",
|
||||
"sid": 14910,
|
||||
"description": "Hotbird 13.0 Eutelsat Sport Klub PL"
|
||||
},
|
||||
{
|
||||
"tsid": 8100,
|
||||
"onid": 318,
|
||||
"charset": "PL_AUTO",
|
||||
"sid": 14911,
|
||||
"description": "Hotbird 13.0 Eutelsat Universal CE"
|
||||
},
|
||||
{
|
||||
"tsid": 8100,
|
||||
"onid": 318,
|
||||
"charset": "PL_AUTO",
|
||||
"sid": 14912,
|
||||
"description": "Hotbird 13.0 Eutelsat Sci-Fi CE"
|
||||
},
|
||||
{
|
||||
"tsid": 11000,
|
||||
"onid": 318,
|
||||
"charset": "PL_AUTO",
|
||||
"sid": 0,
|
||||
"description": "Hotbird 13.0 NC+"
|
||||
},
|
||||
{
|
||||
"tsid": 11100,
|
||||
"onid": 318,
|
||||
"charset": "PL_AUTO",
|
||||
"sid": 4680,
|
||||
"description": "Hotbird 13.0 Eutelsat 13th Street PL"
|
||||
},
|
||||
{
|
||||
"tsid": 11200,
|
||||
"onid": 318,
|
||||
"charset": "PL_AUTO",
|
||||
"sid": 0,
|
||||
"description": "Hotbird 13.0 Polsat Cyfrowy"
|
||||
},
|
||||
{
|
||||
"tsid": 11400,
|
||||
"onid": 318,
|
||||
"charset": "PL_AUTO",
|
||||
"sid": 0,
|
||||
"description": "Hotbird 13.0 NC+"
|
||||
},
|
||||
{
|
||||
"tsid": 11500,
|
||||
"onid": 318,
|
||||
"charset": "PL_AUTO",
|
||||
"sid": 17309,
|
||||
"description": "Hotbird 13.0 Baby TV PL"
|
||||
},
|
||||
{
|
||||
"tsid": 11600,
|
||||
"onid": 318,
|
||||
"charset": "PL_AUTO",
|
||||
"sid": 0,
|
||||
"description": "Hotbird 13.0 NC+"
|
||||
},
|
||||
{
|
||||
"tsid": 11900,
|
||||
"onid": 318,
|
||||
"charset": "PL_AUTO",
|
||||
"sid": 0,
|
||||
"description": "Hotbird 13.0 NC+"
|
||||
},
|
||||
{
|
||||
"tsid": 12000,
|
||||
"onid": 318,
|
||||
"charset": "PL_AUTO",
|
||||
"sid": 0,
|
||||
"description": "Hotbird 13.0 Polsat Cyfrowy"
|
||||
},
|
||||
{
|
||||
"tsid": 12100,
|
||||
"onid": 318,
|
||||
"charset": "ISO-8859-7",
|
||||
"sid": 0,
|
||||
"description": "Hotbird 13.0 Nova GR"
|
||||
},
|
||||
{
|
||||
"tsid": 12200,
|
||||
"onid": 318,
|
||||
"charset": "PL_AUTO",
|
||||
"sid": 7457,
|
||||
"description": "Hotbird 13.0 Globecast Cartoon Network PL / TCM CE"
|
||||
},
|
||||
{
|
||||
"tsid": 12200,
|
||||
"onid": 318,
|
||||
"charset": "PL_AUTO",
|
||||
"sid": 7466,
|
||||
"description": "Hotbird 13.0 Globecast Disney Channel PL"
|
||||
},
|
||||
{
|
||||
"tsid": 12200,
|
||||
"onid": 318,
|
||||
"charset": "PL_AUTO",
|
||||
"sid": 7467,
|
||||
"description": "Hotbird 13.0 Globecast Cartoon Network CE"
|
||||
},
|
||||
{
|
||||
"tsid": 12200,
|
||||
"onid": 318,
|
||||
"charset": "PL_AUTO",
|
||||
"sid": 7468,
|
||||
"description": "Hotbird 13.0 Globecast TCM CE"
|
||||
},
|
||||
{
|
||||
"tsid": 12800,
|
||||
"onid": 318,
|
||||
"charset": "PL_AUTO",
|
||||
"sid": 0,
|
||||
"description": "Hotbird 13.0 MTV Networks"
|
||||
},
|
||||
{
|
||||
"tsid": 13000,
|
||||
"onid": 318,
|
||||
"charset": "PL_AUTO",
|
||||
"sid": 14602,
|
||||
"description": "Hotbird 13.0 Globecast BBC Entertainment"
|
||||
},
|
||||
{
|
||||
"tsid": 13000,
|
||||
"onid": 318,
|
||||
"charset": "PL_AUTO",
|
||||
"sid": 14603,
|
||||
"description": "Hotbird 13.0 Globecast BBC Knowledge"
|
||||
},
|
||||
{
|
||||
"tsid": 13000,
|
||||
"onid": 318,
|
||||
"charset": "PL_AUTO",
|
||||
"sid": 14604,
|
||||
"description": "Hotbird 13.0 Globecast BBC Lifestyle"
|
||||
},
|
||||
{
|
||||
"tsid": 13000,
|
||||
"onid": 318,
|
||||
"charset": "PL_AUTO",
|
||||
"sid": 14605,
|
||||
"description": "Hotbird 13.0 Globecast BBC Cbeebies"
|
||||
},
|
||||
{
|
||||
"tsid": 13000,
|
||||
"onid": 318,
|
||||
"charset": "PL_AUTO",
|
||||
"sid": 14612,
|
||||
"description": "Hotbird 13.0 Globecast IDiscovery"
|
||||
},
|
||||
{
|
||||
"tsid": 13000,
|
||||
"onid": 318,
|
||||
"charset": "PL_AUTO",
|
||||
"sid": 14613,
|
||||
"description": "Hotbird 13.0 Globecast TLC Polska"
|
||||
},
|
||||
{
|
||||
"tsid": 13000,
|
||||
"onid": 318,
|
||||
"charset": "PL_AUTO",
|
||||
"sid": 14619,
|
||||
"description": "Hotbird 13.0 Globecast MTV Dance"
|
||||
},
|
||||
{
|
||||
"tsid": 13000,
|
||||
"onid": 318,
|
||||
"charset": "PL_AUTO",
|
||||
"sid": 14620,
|
||||
"description": "Hotbird 13.0 Globecast Viasat Explorer"
|
||||
},
|
||||
{
|
||||
"tsid": 13000,
|
||||
"onid": 318,
|
||||
"charset": "PL_AUTO",
|
||||
"sid": 14621,
|
||||
"description": "Hotbird 13.0 Globecast ESPN America"
|
||||
},
|
||||
{
|
||||
"tsid": 13100,
|
||||
"onid": 318,
|
||||
"charset": "PL_AUTO",
|
||||
"sid": 7324,
|
||||
"description": "Hotbird 13.0 Crime & Investigation"
|
||||
},
|
||||
{
|
||||
"tsid": 13100,
|
||||
"onid": 318,
|
||||
"charset": "PL_AUTO",
|
||||
"sid": 7325,
|
||||
"description": "Hotbird 13.0 Crime & Investigation"
|
||||
},
|
||||
{
|
||||
"tsid": 13200,
|
||||
"onid": 113,
|
||||
"charset": "PL_AUTO",
|
||||
"sid": 0,
|
||||
"description": "Hotbird 13.0 Cyfrowy Polsat"
|
||||
},
|
||||
{
|
||||
"tsid": 13400,
|
||||
"onid": 318,
|
||||
"charset": "PL_AUTO",
|
||||
"sid": 4754,
|
||||
"description": "Hotbird 13.0 TVR"
|
||||
},
|
||||
{
|
||||
"tsid": 15400,
|
||||
"onid": 318,
|
||||
"charset": "PL_AUTO",
|
||||
"sid": 13511,
|
||||
"description": "Hotbird 13.0 RBL.TV"
|
||||
},
|
||||
{
|
||||
"tsid": 15700,
|
||||
"onid": 318,
|
||||
"charset": "PL_AUTO",
|
||||
"sid": 10626,
|
||||
"description": "Hotbird 13.0 Disco TV"
|
||||
},
|
||||
{
|
||||
"tsid": 1,
|
||||
"onid": 1,
|
||||
"charset": "ISO-8859-2",
|
||||
"sid": 0,
|
||||
"description": "Intelsat/Thor 1W RCS DigiTV"
|
||||
},
|
||||
{
|
||||
"tsid": 2,
|
||||
"onid": 1,
|
||||
"charset": "ISO-8859-2",
|
||||
"sid": 0,
|
||||
"description": "Intelsat/Thor 1W RCS DigiTV"
|
||||
},
|
||||
{
|
||||
"tsid": 3,
|
||||
"onid": 1,
|
||||
"charset": "ISO-8859-2",
|
||||
"sid": 0,
|
||||
"description": "Intelsat/Thor 1W RCS DigiTV"
|
||||
},
|
||||
{
|
||||
"tsid": 4,
|
||||
"onid": 1,
|
||||
"charset": "ISO-8859-2",
|
||||
"sid": 0,
|
||||
"description": "Intelsat/Thor 1W RCS DigiTV"
|
||||
},
|
||||
{
|
||||
"tsid": 5,
|
||||
"onid": 1,
|
||||
"charset": "ISO-8859-2",
|
||||
"sid": 0,
|
||||
"description": "Intelsat/Thor 1W RCS DigiTV"
|
||||
},
|
||||
{
|
||||
"tsid": 6,
|
||||
"onid": 1,
|
||||
"charset": "ISO-8859-2",
|
||||
"sid": 0,
|
||||
"description": "Intelsat/Thor 1W RCS DigiTV"
|
||||
},
|
||||
{
|
||||
"tsid": 7,
|
||||
"onid": 1,
|
||||
"charset": "ISO-8859-2",
|
||||
"sid": 0,
|
||||
"description": "Intelsat/Thor 1W RCS DigiTV"
|
||||
},
|
||||
{
|
||||
"tsid": 8,
|
||||
"onid": 1,
|
||||
"charset": "ISO-8859-2",
|
||||
"sid": 0,
|
||||
"description": "Intelsat/Thor 1W RCS DigiTV"
|
||||
},
|
||||
{
|
||||
"tsid": 9,
|
||||
"onid": 1,
|
||||
"charset": "ISO-8859-2",
|
||||
"sid": 0,
|
||||
"description": "Intelsat/Thor 1W RCS DigiTV"
|
||||
},
|
||||
{
|
||||
"tsid": 10,
|
||||
"onid": 1,
|
||||
"charset": "ISO-8859-2",
|
||||
"sid": 0,
|
||||
"description": "Intelsat/Thor 1W RCS DigiTV"
|
||||
},
|
||||
{
|
||||
"tsid": 11,
|
||||
"onid": 1,
|
||||
"charset": "ISO-8859-2",
|
||||
"sid": 0,
|
||||
"description": "Intelsat/Thor 1W RCS DigiTV"
|
||||
},
|
||||
{
|
||||
"tsid": 12,
|
||||
"onid": 1,
|
||||
"charset": "ISO-8859-2",
|
||||
"sid": 0,
|
||||
"description": "Intelsat/Thor 1W RCS DigiTV"
|
||||
},
|
||||
{
|
||||
"tsid": 13,
|
||||
"onid": 1,
|
||||
"charset": "ISO-8859-2",
|
||||
"sid": 0,
|
||||
"description": "Intelsat/Thor 1W RCS DigiTV"
|
||||
},
|
||||
{
|
||||
"tsid": 20400,
|
||||
"onid": 126,
|
||||
"charset": "ISO-8859-9",
|
||||
"sid": 0,
|
||||
"description": "Turksat 7E Digitürk 10762.00 V"
|
||||
},
|
||||
{
|
||||
"tsid": 20600,
|
||||
"onid": 126,
|
||||
"charset": "ISO-8859-9",
|
||||
"sid": 0,
|
||||
"description": "Turksat 7E Digitürk 10803.75 V"
|
||||
},
|
||||
{
|
||||
"tsid": 20700,
|
||||
"onid": 126,
|
||||
"charset": "ISO-8859-9",
|
||||
"sid": 0,
|
||||
"description": "Turksat 7E Digitürk 10845.00 H"
|
||||
},
|
||||
{
|
||||
"tsid": 20800,
|
||||
"onid": 126,
|
||||
"charset": "ISO-8859-9",
|
||||
"sid": 0,
|
||||
"description": "Turksat 7E Digitürk 10845.25 V"
|
||||
},
|
||||
{
|
||||
"tsid": 20900,
|
||||
"onid": 126,
|
||||
"charset": "ISO-8859-9",
|
||||
"sid": 0,
|
||||
"description": "Turksat 7E Digitürk 108877.00 H"
|
||||
},
|
||||
{
|
||||
"tsid": 21000,
|
||||
"onid": 126,
|
||||
"charset": "ISO-8859-9",
|
||||
"sid": 0,
|
||||
"description": "Turksat 7E Digitürk 10928.00 H"
|
||||
},
|
||||
{
|
||||
"tsid": 21100,
|
||||
"onid": 126,
|
||||
"charset": "ISO-8859-9",
|
||||
"sid": 0,
|
||||
"description": "Turksat 7E Digitürk 10887.00 V"
|
||||
},
|
||||
{
|
||||
"tsid": 21200,
|
||||
"onid": 126,
|
||||
"charset": "ISO-8859-9",
|
||||
"sid": 0,
|
||||
"description": "Turksat 7E Digitürk 10928.00 V"
|
||||
},
|
||||
{
|
||||
"tsid": 41200,
|
||||
"onid": 126,
|
||||
"charset": "ISO-8859-9",
|
||||
"sid": 0,
|
||||
"description": "Turksat 7E Digitürk 11455.50 V"
|
||||
},
|
||||
{
|
||||
"tsid": 50100,
|
||||
"onid": 126,
|
||||
"charset": "ISO-8859-9",
|
||||
"sid": 0,
|
||||
"description": "Turksat 7E Digitürk 11471.00 H"
|
||||
},
|
||||
{
|
||||
"tsid": 50200,
|
||||
"onid": 126,
|
||||
"charset": "ISO-8859-9",
|
||||
"sid": 0,
|
||||
"description": "Turksat 7E Digitürk 11492.00 V"
|
||||
},
|
||||
{
|
||||
"tsid": 50300,
|
||||
"onid": 126,
|
||||
"charset": "ISO-8859-9",
|
||||
"sid": 0,
|
||||
"description": "Turksat 7E Digitürk 11673.00 H"
|
||||
},
|
||||
{
|
||||
"tsid": 50400,
|
||||
"onid": 126,
|
||||
"charset": "ISO-8859-9",
|
||||
"sid": 0,
|
||||
"description": "Turksat 7E Digitürk 11534.00 V"
|
||||
},
|
||||
{
|
||||
"tsid": 50500,
|
||||
"onid": 126,
|
||||
"charset": "ISO-8859-9",
|
||||
"sid": 0,
|
||||
"description": "Turksat 7E Digitürk 11554.00 H"
|
||||
},
|
||||
{
|
||||
"tsid": 50600,
|
||||
"onid": 126,
|
||||
"charset": "ISO-8859-9",
|
||||
"sid": 0,
|
||||
"description": "Turksat 7E Digitürk 11575.00 V"
|
||||
},
|
||||
{
|
||||
"tsid": 50700,
|
||||
"onid": 126,
|
||||
"charset": "ISO-8859-9",
|
||||
"sid": 0,
|
||||
"description": "Turksat 7E Digitürk 11596.00 H"
|
||||
},
|
||||
{
|
||||
"tsid": 50800,
|
||||
"onid": 126,
|
||||
"charset": "ISO-8859-9",
|
||||
"sid": 0,
|
||||
"description": "Turksat 7E Digitürk 11679.00 H"
|
||||
},
|
||||
{
|
||||
"tsid": 50900,
|
||||
"onid": 126,
|
||||
"charset": "ISO-8859-9",
|
||||
"sid": 0,
|
||||
"description": "Turksat 7E Digitürk 11513.00 H"
|
||||
},
|
||||
{
|
||||
"tsid": 51000,
|
||||
"onid": 126,
|
||||
"charset": "ISO-8859-9",
|
||||
"sid": 0,
|
||||
"description": "Turksat 7E Digitürk 11617.00 V"
|
||||
}
|
||||
]
|
|
@ -1,258 +0,0 @@
|
|||
[
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
32,
|
||||
32,
|
||||
32,
|
||||
32,
|
||||
32,
|
||||
32,
|
||||
32,
|
||||
32,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
81,
|
||||
48,
|
||||
48,
|
||||
80,
|
||||
51,
|
||||
48,
|
||||
80,
|
||||
48,
|
||||
0,
|
||||
48,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
18,
|
||||
18,
|
||||
22,
|
||||
19,
|
||||
20,
|
||||
17,
|
||||
16,
|
||||
16,
|
||||
96,
|
||||
0,
|
||||
96,
|
||||
0,
|
||||
96,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
64,
|
||||
64,
|
||||
64,
|
||||
67,
|
||||
64,
|
||||
64,
|
||||
64,
|
||||
64,
|
||||
64,
|
||||
73,
|
||||
64,
|
||||
64,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
|
@ -1,258 +0,0 @@
|
|||
[
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
48,
|
||||
48,
|
||||
48,
|
||||
48,
|
||||
48,
|
||||
21,
|
||||
48,
|
||||
48,
|
||||
48,
|
||||
48,
|
||||
48,
|
||||
48,
|
||||
48,
|
||||
48,
|
||||
49,
|
||||
51,
|
||||
48,
|
||||
48,
|
||||
48,
|
||||
48,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
64,
|
||||
64,
|
||||
68,
|
||||
71,
|
||||
64,
|
||||
64,
|
||||
64,
|
||||
64,
|
||||
64,
|
||||
64,
|
||||
70,
|
||||
64,
|
||||
64,
|
||||
64,
|
||||
74,
|
||||
64,
|
||||
64,
|
||||
64,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
16,
|
||||
23,
|
||||
20,
|
||||
22,
|
||||
18,
|
||||
16,
|
||||
18,
|
||||
20,
|
||||
19,
|
||||
18,
|
||||
16,
|
||||
18,
|
||||
18,
|
||||
16,
|
||||
17,
|
||||
16,
|
||||
16,
|
||||
16,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
48,
|
||||
48,
|
||||
48,
|
||||
48,
|
||||
48,
|
||||
48,
|
||||
48,
|
||||
48,
|
||||
48,
|
||||
48,
|
||||
48,
|
||||
48,
|
||||
48,
|
||||
48,
|
||||
48,
|
||||
48,
|
||||
48,
|
||||
48,
|
||||
48,
|
||||
48,
|
||||
48,
|
||||
48,
|
||||
48,
|
||||
48,
|
||||
48,
|
||||
48,
|
||||
48,
|
||||
48,
|
||||
48,
|
||||
48,
|
||||
48,
|
||||
48,
|
||||
48,
|
||||
48,
|
||||
48,
|
||||
48,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
96,
|
||||
96,
|
||||
96,
|
||||
96,
|
||||
96,
|
||||
96,
|
||||
96,
|
||||
96,
|
||||
96,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
96,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
48,
|
||||
48,
|
||||
48,
|
||||
48,
|
||||
0,
|
||||
48,
|
||||
48,
|
||||
24,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
|
@ -1,257 +0,0 @@
|
|||
[ 0, 0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
16,
|
||||
17,
|
||||
18,
|
||||
19,
|
||||
20,
|
||||
16,
|
||||
22,
|
||||
23,
|
||||
23,
|
||||
16,
|
||||
19,
|
||||
23,
|
||||
23,
|
||||
23,
|
||||
18,
|
||||
16,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
32,
|
||||
33,
|
||||
34,
|
||||
35,
|
||||
36,
|
||||
144,
|
||||
35,
|
||||
144,
|
||||
32,
|
||||
145,
|
||||
115,
|
||||
146,
|
||||
118,
|
||||
148,
|
||||
144,
|
||||
32,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
48,
|
||||
49,
|
||||
51,
|
||||
51,
|
||||
48,
|
||||
48,
|
||||
48,
|
||||
48,
|
||||
48,
|
||||
48,
|
||||
48,
|
||||
48,
|
||||
49,
|
||||
48,
|
||||
51,
|
||||
50,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
64,
|
||||
65,
|
||||
66,
|
||||
67,
|
||||
68,
|
||||
69,
|
||||
70,
|
||||
71,
|
||||
72,
|
||||
73,
|
||||
74,
|
||||
75,
|
||||
69,
|
||||
64,
|
||||
64,
|
||||
64,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
80,
|
||||
81,
|
||||
82,
|
||||
83,
|
||||
84,
|
||||
85,
|
||||
80,
|
||||
80,
|
||||
84,
|
||||
85,
|
||||
80,
|
||||
80,
|
||||
80,
|
||||
80,
|
||||
80,
|
||||
80,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
96,
|
||||
97,
|
||||
98,
|
||||
99,
|
||||
100,
|
||||
101,
|
||||
102,
|
||||
96,
|
||||
96,
|
||||
96,
|
||||
96,
|
||||
96,
|
||||
96,
|
||||
96,
|
||||
96,
|
||||
96,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
112,
|
||||
113,
|
||||
114,
|
||||
115,
|
||||
116,
|
||||
117,
|
||||
118,
|
||||
119,
|
||||
120,
|
||||
121,
|
||||
122,
|
||||
123,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
112,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
|
|
@ -1,11 +1,9 @@
|
|||
{
|
||||
"name": "Ausat",
|
||||
"dict": "skyeng",
|
||||
"genre": "ausat",
|
||||
"nid": 4096,
|
||||
"tsid": 17,
|
||||
"sid": 17008,
|
||||
"bouquetid": 0,
|
||||
"channel" : [
|
||||
17
|
||||
],
|
||||
|
@ -14,11 +12,5 @@
|
|||
],
|
||||
"summary": [
|
||||
64, 65, 66, 67, 68, 69, 70, 71
|
||||
],
|
||||
"season_num": [
|
||||
" *\\(S ?([0-9]+),? Ep? ?[0-9]+\\)"
|
||||
],
|
||||
"episode_num": [
|
||||
" *\\(S ?[0-9]+,? Ep? ?([0-9]+)\\)"
|
||||
]
|
||||
}
|
||||
|
|
|
@ -1,11 +1,9 @@
|
|||
{
|
||||
"name": "Sky Italia",
|
||||
"dict": "skyit",
|
||||
"genre": "skyit",
|
||||
"nid": 64511,
|
||||
"tsid": 5800,
|
||||
"sid": 3635,
|
||||
"bouquetid": 0,
|
||||
"channel" : [
|
||||
17
|
||||
],
|
||||
|
@ -14,35 +12,5 @@
|
|||
],
|
||||
"summary": [
|
||||
64, 65, 66, 67, 68, 69, 70, 71
|
||||
],
|
||||
"season_num": [
|
||||
"([0-9]+)'?a? Stagione +Ep\\. ?[0-9]+[a-z]?",
|
||||
"([0-9]+)'?a? Stagione -? ?Puntata ?[0-9]+",
|
||||
"([0-9]+)'?a? Stagione"
|
||||
],
|
||||
"episode_num": [
|
||||
"[0-9]+'?a? Stagione +Ep\\. ?([0-9]+)[a-z]?",
|
||||
"[0-9]+'?a? Stagione -? ?Puntata ?([0-9]+)",
|
||||
"^ *Ep\\. ?([0-9]+)[a-z]?",
|
||||
"^ *Puntata ?([0-9]+)"
|
||||
],
|
||||
"part_num": [
|
||||
"[0-9]+'?a? Stagione +Ep\\. ?[0-9]+([a-z]?)",
|
||||
"^ *Ep\\. ?[0-9]+([a-z]?)"
|
||||
],
|
||||
"subtitle": [
|
||||
"[0-9]+'?a? Stagione +Ep\\. ?[0-9]+[A-Za-z]? -? ?'(([^']*(' [^A-Z0-9-])?('[^ '])?)+)'",
|
||||
"Ep\\. ?[0-9]+[A-Za-z]? -? ?'(([^']*(' [^A-Z0-9-])?('[^ '])?)+)'",
|
||||
"[0-9]+'?a? Stagione -? ?'(([^']*(' [^A-Z0-9-])?('[^ '])?)+)'",
|
||||
"[0-9]+'?a? Stagione -? ?Puntata ?[0-9]+[A-Za-z]? \"\" *([^\"]+) *\"\""
|
||||
],
|
||||
"__reference": [
|
||||
"4' Stagione Ep.9B - 'L'Hub' Gli agenti ...: sara' Ward ...",
|
||||
"3a Stagione - Puntata 1 ...",
|
||||
"4' Stagione - 'Title' ...",
|
||||
"Ep.9A ...",
|
||||
"Puntata 5 ...",
|
||||
"Ep.4 - 'Title' ...",
|
||||
"7 Stagione Puntata 8 \"\" Title \"\" ..."
|
||||
]
|
||||
}
|
||||
|
|
|
@ -1,24 +0,0 @@
|
|||
{
|
||||
"name": "Sky NZ",
|
||||
"dict": "skynz",
|
||||
"genre": "skynz",
|
||||
"nid": 169,
|
||||
"tsid": 3,
|
||||
"sid": 9003,
|
||||
"bouquetid": 0,
|
||||
"channel" : [
|
||||
17
|
||||
],
|
||||
"title": [
|
||||
48, 49, 50, 51, 52, 53, 54, 55
|
||||
],
|
||||
"summary": [
|
||||
64, 65, 66, 67, 68, 69, 70, 71
|
||||
],
|
||||
"season_num": [
|
||||
" *\\(S ?([0-9]+),? Ep? ?[0-9]+\\)"
|
||||
],
|
||||
"episode_num": [
|
||||
" *\\(S ?[0-9]+,? Ep? ?([0-9]+)\\)"
|
||||
]
|
||||
}
|
|
@ -5,7 +5,6 @@
|
|||
"nid": 2,
|
||||
"tsid": 2004,
|
||||
"sid": 4152,
|
||||
"bouquetid": 4101,
|
||||
"channel" : [
|
||||
17
|
||||
],
|
||||
|
@ -14,11 +13,5 @@
|
|||
],
|
||||
"summary": [
|
||||
64, 65, 66, 67, 68, 69, 70, 71
|
||||
],
|
||||
"season_num": [
|
||||
" *\\(S ?([0-9]+),? Ep? ?[0-9]+\\)"
|
||||
],
|
||||
"episode_num": [
|
||||
" *\\(S ?[0-9]+,? Ep? ?([0-9]+)\\)"
|
||||
]
|
||||
}
|
||||
|
|
|
@ -1,155 +0,0 @@
|
|||
[
|
||||
{
|
||||
"name": "Canal Digitaal SD",
|
||||
"position": 192,
|
||||
"frequency": 12515000,
|
||||
"symbolrate" : 22000000,
|
||||
"polarisation" : "H",
|
||||
"delsys" : "dvbs",
|
||||
"pid": 900
|
||||
},
|
||||
{
|
||||
"name": "Canal Digitaal HD",
|
||||
"position": 192,
|
||||
"frequency": 12515000,
|
||||
"symbolrate" : 22000000,
|
||||
"polarisation" : "H",
|
||||
"delsys" : "dvbs",
|
||||
"pid": 901
|
||||
},
|
||||
{
|
||||
"name": "TV Vlaanderen SD",
|
||||
"position": 192,
|
||||
"frequency": 12515000,
|
||||
"symbolrate" : 22000000,
|
||||
"polarisation" : "H",
|
||||
"delsys" : "dvbs",
|
||||
"pid": 910
|
||||
},
|
||||
{
|
||||
"name": "TV Vlaanderen HD",
|
||||
"position": 192,
|
||||
"frequency": 12515000,
|
||||
"symbolrate" : 22000000,
|
||||
"polarisation" : "H",
|
||||
"delsys" : "dvbs",
|
||||
"pid": 911
|
||||
},
|
||||
{
|
||||
"name": "TéléSAT SD",
|
||||
"position": 192,
|
||||
"frequency": 12515000,
|
||||
"symbolrate" : 22000000,
|
||||
"polarisation" : "H",
|
||||
"delsys" : "dvbs",
|
||||
"pid": 920
|
||||
},
|
||||
{
|
||||
"name": "TéléSAT HD",
|
||||
"position": 192,
|
||||
"frequency": 12515000,
|
||||
"symbolrate" : 22000000,
|
||||
"polarisation" : "H",
|
||||
"delsys" : "dvbs",
|
||||
"pid": 921
|
||||
},
|
||||
{
|
||||
"name": "Mobistar NL Astra1",
|
||||
"position": 192,
|
||||
"frequency": 12515000,
|
||||
"symbolrate" : 22000000,
|
||||
"polarisation" : "H",
|
||||
"delsys" : "dvbs",
|
||||
"pid": 930
|
||||
},
|
||||
{
|
||||
"name": "Mobistar FR Astra1",
|
||||
"position": 192,
|
||||
"frequency": 12515000,
|
||||
"symbolrate" : 22000000,
|
||||
"polarisation" : "H",
|
||||
"delsys" : "dvbs",
|
||||
"pid": 940
|
||||
},
|
||||
{
|
||||
"name": "AustriaSat Astra1",
|
||||
"position": 192,
|
||||
"frequency": 12515000,
|
||||
"symbolrate" : 22000000,
|
||||
"polarisation" : "H",
|
||||
"delsys" : "dvbs",
|
||||
"pid": 950
|
||||
},
|
||||
{
|
||||
"name": "Canal Digitaal HD",
|
||||
"position": 235,
|
||||
"frequency": 12187000,
|
||||
"symbolrate" : 27500000,
|
||||
"polarisation" : "H",
|
||||
"delsys" : "dvbs2",
|
||||
"pid": 901
|
||||
},
|
||||
{
|
||||
"name": "TV Vlaanderen HD",
|
||||
"position": 235,
|
||||
"frequency": 12187000,
|
||||
"symbolrate" : 27500000,
|
||||
"polarisation" : "H",
|
||||
"delsys" : "dvbs2",
|
||||
"pid": 911
|
||||
},
|
||||
{
|
||||
"name": "TéléSAT HD",
|
||||
"position": 235,
|
||||
"frequency": 12187000,
|
||||
"symbolrate" : 27500000,
|
||||
"polarisation" : "H",
|
||||
"delsys" : "dvbs2",
|
||||
"pid": 921
|
||||
},
|
||||
{
|
||||
"name": "Mobistar NL Astra3",
|
||||
"position": 235,
|
||||
"frequency": 12187000,
|
||||
"symbolrate" : 27500000,
|
||||
"polarisation" : "H",
|
||||
"delsys" : "dvbs2",
|
||||
"pid": 930
|
||||
},
|
||||
{
|
||||
"name": "Mobistar FR Astra3",
|
||||
"position": 235,
|
||||
"frequency": 12187000,
|
||||
"symbolrate" : 27500000,
|
||||
"polarisation" : "H",
|
||||
"delsys" : "dvbs2",
|
||||
"pid": 940
|
||||
},
|
||||
{
|
||||
"name": "AustriaSat Astra3",
|
||||
"position": 235,
|
||||
"frequency": 12187000,
|
||||
"symbolrate" : 27500000,
|
||||
"polarisation" : "H",
|
||||
"delsys" : "dvbs2",
|
||||
"pid": 950
|
||||
},
|
||||
{
|
||||
"name": "Skylink: Czech Republic",
|
||||
"position": 235,
|
||||
"frequency": 12070000,
|
||||
"symbolrate" : 27500000,
|
||||
"polarisation" : "H",
|
||||
"delsys" : "dvbs",
|
||||
"pid": 30
|
||||
},
|
||||
{
|
||||
"name": "Skylink: Slovak Republic",
|
||||
"position": 235,
|
||||
"frequency": 12070000,
|
||||
"symbolrate" : 27500000,
|
||||
"polarisation" : "H",
|
||||
"delsys" : "dvbs",
|
||||
"pid": 31
|
||||
}
|
||||
]
|
|
@ -1,638 +0,0 @@
|
|||
[
|
||||
{
|
||||
"name": "NSS 9",
|
||||
"pos": -1770
|
||||
},
|
||||
{
|
||||
"name": "AMC 8",
|
||||
"pos": -1390
|
||||
},
|
||||
{
|
||||
"name": "AMC 7",
|
||||
"pos": -1370
|
||||
},
|
||||
{
|
||||
"name": "AMC 10",
|
||||
"pos": -1350
|
||||
},
|
||||
{
|
||||
"name": "Galaxy 15",
|
||||
"pos": -1330
|
||||
},
|
||||
{
|
||||
"name": "AMC 11",
|
||||
"pos": -1310
|
||||
},
|
||||
{
|
||||
"name": "Ciel 2/Galaxy 12",
|
||||
"pos": -1290
|
||||
},
|
||||
{
|
||||
"name": "Galaxy 13/Horizons 1",
|
||||
"pos": -1270
|
||||
},
|
||||
{
|
||||
"name": "AMC 21/Galaxy 14",
|
||||
"pos": -1250
|
||||
},
|
||||
{
|
||||
"name": "Galaxy 18",
|
||||
"pos": -1230
|
||||
},
|
||||
{
|
||||
"name": "EchoStar 9/Galaxy 23",
|
||||
"pos": -1210
|
||||
},
|
||||
{
|
||||
"name": "Anik F3/DirecTV 7S/EchoStar 14",
|
||||
"pos": -1190
|
||||
},
|
||||
{
|
||||
"name": "Eutelsat 117 West A",
|
||||
"pos": -1168
|
||||
},
|
||||
{
|
||||
"name": "Eutelsat 115 West A",
|
||||
"pos": -1149
|
||||
},
|
||||
{
|
||||
"name": "Eutelsat 113 West A",
|
||||
"pos": -1130
|
||||
},
|
||||
{
|
||||
"name": "Anik F2",
|
||||
"pos": -1111
|
||||
},
|
||||
{
|
||||
"name": "DirecTV 5/EchoStar 10/11",
|
||||
"pos": -1100
|
||||
},
|
||||
{
|
||||
"name": "Anik F1R/G1",
|
||||
"pos": -1073
|
||||
},
|
||||
{
|
||||
"name": "AMC 15/18",
|
||||
"pos": -1050
|
||||
},
|
||||
{
|
||||
"name": "AMC 1/SES 3/Spaceway 1 & DirecTV 10/12",
|
||||
"pos": -1030
|
||||
},
|
||||
{
|
||||
"name": "DirecTV 4S/8/SES 1",
|
||||
"pos": -1010
|
||||
},
|
||||
{
|
||||
"name": "DirecTV 14/Galaxy 16/Spaceway 2 & DirecTV 11",
|
||||
"pos": -992
|
||||
},
|
||||
{
|
||||
"name": "Galaxy 19",
|
||||
"pos": -970
|
||||
},
|
||||
{
|
||||
"name": "Galaxy 3C/Spaceway 3",
|
||||
"pos": -950
|
||||
},
|
||||
{
|
||||
"name": "Galaxy 25",
|
||||
"pos": -931
|
||||
},
|
||||
{
|
||||
"name": "Galaxy 17/Nimiq 6",
|
||||
"pos": -910
|
||||
},
|
||||
{
|
||||
"name": "Galaxy 28",
|
||||
"pos": -890
|
||||
},
|
||||
{
|
||||
"name": "TKSat 1",
|
||||
"pos": -872
|
||||
},
|
||||
{
|
||||
"name": "SES 2",
|
||||
"pos": -870
|
||||
},
|
||||
{
|
||||
"name": "AMC 16",
|
||||
"pos": -850
|
||||
},
|
||||
{
|
||||
"name": "Brasilsat B4",
|
||||
"pos": -840
|
||||
},
|
||||
{
|
||||
"name": "AMC 9",
|
||||
"pos": -830
|
||||
},
|
||||
{
|
||||
"name": "Nimiq 4",
|
||||
"pos": -820
|
||||
},
|
||||
{
|
||||
"name": "Simon Bolivar",
|
||||
"pos": -780
|
||||
},
|
||||
{
|
||||
"name": "EchoStar 8/QuetzSat 1",
|
||||
"pos": -770
|
||||
},
|
||||
{
|
||||
"name": "Star One C3",
|
||||
"pos": -750
|
||||
},
|
||||
{
|
||||
"name": "Nimiq 5",
|
||||
"pos": -727
|
||||
},
|
||||
{
|
||||
"name": "AMC 6",
|
||||
"pos": -720
|
||||
},
|
||||
{
|
||||
"name": "Star One C2",
|
||||
"pos": -700
|
||||
},
|
||||
{
|
||||
"name": "AMC 4",
|
||||
"pos": -670
|
||||
},
|
||||
{
|
||||
"name": "Star One C1",
|
||||
"pos": -650
|
||||
},
|
||||
{
|
||||
"name": "Telstar 14R",
|
||||
"pos": -630
|
||||
},
|
||||
{
|
||||
"name": "EchoStar 12/16",
|
||||
"pos": -615
|
||||
},
|
||||
{
|
||||
"name": "Amazonas 2/3/4A",
|
||||
"pos": -610
|
||||
},
|
||||
{
|
||||
"name": "Intelsat 21",
|
||||
"pos": -580
|
||||
},
|
||||
{
|
||||
"name": "Amazonas 1/Galaxy 11/Intelsat 805",
|
||||
"pos": -555
|
||||
},
|
||||
{
|
||||
"name": "Intelsat 23",
|
||||
"pos": -530
|
||||
},
|
||||
{
|
||||
"name": "Intelsat 1R",
|
||||
"pos": -500
|
||||
},
|
||||
{
|
||||
"name": "NSS 806",
|
||||
"pos": -475
|
||||
},
|
||||
{
|
||||
"name": "Intelsat 14",
|
||||
"pos": -450
|
||||
},
|
||||
{
|
||||
"name": "Intelsat 9/11",
|
||||
"pos": -431
|
||||
},
|
||||
{
|
||||
"name": "SES 6",
|
||||
"pos": -405
|
||||
},
|
||||
{
|
||||
"name": "NSS 10/Telstar 11N",
|
||||
"pos": -375
|
||||
},
|
||||
{
|
||||
"name": "Intelsat 903",
|
||||
"pos": -345
|
||||
},
|
||||
{
|
||||
"name": "Hylas 1",
|
||||
"pos": -335
|
||||
},
|
||||
{
|
||||
"name": "Intelsat 25",
|
||||
"pos": -315
|
||||
},
|
||||
{
|
||||
"name": "Hispasat 1D/1E",
|
||||
"pos": -300
|
||||
},
|
||||
{
|
||||
"name": "Intelsat 907",
|
||||
"pos": -275
|
||||
},
|
||||
{
|
||||
"name": "Intelsat 905",
|
||||
"pos": -245
|
||||
},
|
||||
{
|
||||
"name": "SES 4",
|
||||
"pos": -220
|
||||
},
|
||||
{
|
||||
"name": "NSS 7",
|
||||
"pos": -200
|
||||
},
|
||||
{
|
||||
"name": "Intelsat 901",
|
||||
"pos": -180
|
||||
},
|
||||
{
|
||||
"name": "Telstar 12",
|
||||
"pos": -150
|
||||
},
|
||||
{
|
||||
"name": "Express A4",
|
||||
"pos": -140
|
||||
},
|
||||
{
|
||||
"name": "Eutelsat 12 West A",
|
||||
"pos": -125
|
||||
},
|
||||
{
|
||||
"name": "Express AM44",
|
||||
"pos": -110
|
||||
},
|
||||
{
|
||||
"name": "Eutelsat 8 West A",
|
||||
"pos": -80
|
||||
},
|
||||
{
|
||||
"name": "Eutelsat 7 West A/Eutelsat 8 West C/Nilesat 102/201",
|
||||
"pos": -73
|
||||
},
|
||||
{
|
||||
"name": "Eutelsat 5 West A",
|
||||
"pos": -50
|
||||
},
|
||||
{
|
||||
"name": "Amos 2/3",
|
||||
"pos": -40
|
||||
},
|
||||
{
|
||||
"name": "Thor 5/6/Intelsat 10-02",
|
||||
"pos": -8
|
||||
},
|
||||
{
|
||||
"name": "Eutelsat 3B/Rascom QAF 1R",
|
||||
"pos": 31
|
||||
},
|
||||
{
|
||||
"name": "Astra 4A/SES 5",
|
||||
"pos": 49
|
||||
},
|
||||
{
|
||||
"name": "Eutelsat 7A/7B",
|
||||
"pos": 70
|
||||
},
|
||||
{
|
||||
"name": "Eutelsat 9A/Ka-Sat 9A",
|
||||
"pos": 90
|
||||
},
|
||||
{
|
||||
"name": "Eutelsat 10A",
|
||||
"pos": 100
|
||||
},
|
||||
{
|
||||
"name": "Eutelsat Hot Bird 13B/13C/13D",
|
||||
"pos": 130
|
||||
},
|
||||
{
|
||||
"name": "Eutelsat 16A",
|
||||
"pos": 160
|
||||
},
|
||||
{
|
||||
"name": "Amos 5",
|
||||
"pos": 170
|
||||
},
|
||||
{
|
||||
"name": "Astra 1KR/1L/1M/1N",
|
||||
"pos": 192
|
||||
},
|
||||
{
|
||||
"name": "Arabsat 5C",
|
||||
"pos": 200
|
||||
},
|
||||
{
|
||||
"name": "Eutelsat 21B",
|
||||
"pos": 215
|
||||
},
|
||||
{
|
||||
"name": "Astra 3B",
|
||||
"pos": 235
|
||||
},
|
||||
{
|
||||
"name": "Eutelsat 25B/Es'hail 1",
|
||||
"pos": 255
|
||||
},
|
||||
{
|
||||
"name": "Badr 4/5/6",
|
||||
"pos": 260
|
||||
},
|
||||
{
|
||||
"name": "Astra 2A/2C/2E/2F/Eutelsat 28A",
|
||||
"pos": 282
|
||||
},
|
||||
{
|
||||
"name": "Arabsat 5A",
|
||||
"pos": 305
|
||||
},
|
||||
{
|
||||
"name": "Eutelsat 31A",
|
||||
"pos": 308
|
||||
},
|
||||
{
|
||||
"name": "Astra 5B",
|
||||
"pos": 315
|
||||
},
|
||||
{
|
||||
"name": "Eutelsat 33B/Intelsat 28",
|
||||
"pos": 330
|
||||
},
|
||||
{
|
||||
"name": "Eutelsat 36A/36B",
|
||||
"pos": 360
|
||||
},
|
||||
{
|
||||
"name": "Paksat 1R",
|
||||
"pos": 380
|
||||
},
|
||||
{
|
||||
"name": "Hellas Sat 2",
|
||||
"pos": 390
|
||||
},
|
||||
{
|
||||
"name": "Türksat 2A/3A/4A",
|
||||
"pos": 420
|
||||
},
|
||||
{
|
||||
"name": "Intelsat 12",
|
||||
"pos": 450
|
||||
},
|
||||
{
|
||||
"name": "AzerSpace 1/Africasat 1a",
|
||||
"pos": 460
|
||||
},
|
||||
{
|
||||
"name": "Intelsat 10",
|
||||
"pos": 475
|
||||
},
|
||||
{
|
||||
"name": "Afghansat 1",
|
||||
"pos": 480
|
||||
},
|
||||
{
|
||||
"name": "Yamal 202",
|
||||
"pos": 490
|
||||
},
|
||||
{
|
||||
"name": "NSS 5",
|
||||
"pos": 505
|
||||
},
|
||||
{
|
||||
"name": "Y1A",
|
||||
"pos": 525
|
||||
},
|
||||
{
|
||||
"name": "Express AM22",
|
||||
"pos": 530
|
||||
},
|
||||
{
|
||||
"name": "G-Sat 8/Yamal 402",
|
||||
"pos": 549
|
||||
},
|
||||
{
|
||||
"name": "Express AT1",
|
||||
"pos": 560
|
||||
},
|
||||
{
|
||||
"name": "NSS 12",
|
||||
"pos": 570
|
||||
},
|
||||
{
|
||||
"name": "Intelsat 904",
|
||||
"pos": 600
|
||||
},
|
||||
{
|
||||
"name": "Intelsat 902",
|
||||
"pos": 620
|
||||
},
|
||||
{
|
||||
"name": "Intelsat 906",
|
||||
"pos": 642
|
||||
},
|
||||
{
|
||||
"name": "Intelsat 17",
|
||||
"pos": 660
|
||||
},
|
||||
{
|
||||
"name": "Intelsat 20",
|
||||
"pos": 685
|
||||
},
|
||||
{
|
||||
"name": "Eutelsat 70B",
|
||||
"pos": 705
|
||||
},
|
||||
{
|
||||
"name": "Intelsat 22",
|
||||
"pos": 721
|
||||
},
|
||||
{
|
||||
"name": "Insat 3C/4CR",
|
||||
"pos": 740
|
||||
},
|
||||
{
|
||||
"name": "ABS 2",
|
||||
"pos": 750
|
||||
},
|
||||
{
|
||||
"name": "Apstar 7",
|
||||
"pos": 765
|
||||
},
|
||||
{
|
||||
"name": "Thaicom 5/6",
|
||||
"pos": 785
|
||||
},
|
||||
{
|
||||
"name": "G-Sat 10/Insat 4A",
|
||||
"pos": 830
|
||||
},
|
||||
{
|
||||
"name": "Horizons 2/Intelsat 15",
|
||||
"pos": 851
|
||||
},
|
||||
{
|
||||
"name": "KazSat 2",
|
||||
"pos": 865
|
||||
},
|
||||
{
|
||||
"name": "ChinaSat 12",
|
||||
"pos": 875
|
||||
},
|
||||
{
|
||||
"name": "ST 2",
|
||||
"pos": 880
|
||||
},
|
||||
{
|
||||
"name": "Yamal 300K/401",
|
||||
"pos": 900
|
||||
},
|
||||
{
|
||||
"name": "Measat 3/3a/3b",
|
||||
"pos": 915
|
||||
},
|
||||
{
|
||||
"name": "ChinaSat 9",
|
||||
"pos": 922
|
||||
},
|
||||
{
|
||||
"name": "Insat 3A/4B",
|
||||
"pos": 935
|
||||
},
|
||||
{
|
||||
"name": "NSS 6/SES 8",
|
||||
"pos": 950
|
||||
},
|
||||
{
|
||||
"name": "Express AM33",
|
||||
"pos": 965
|
||||
},
|
||||
{
|
||||
"name": "AsiaSat 5",
|
||||
"pos": 1005
|
||||
},
|
||||
{
|
||||
"name": "Express AM3",
|
||||
"pos": 1030
|
||||
},
|
||||
{
|
||||
"name": "AsiaSat 7/8",
|
||||
"pos": 1055
|
||||
},
|
||||
{
|
||||
"name": "NSS 11/SES 7/Telkom 1",
|
||||
"pos": 1082
|
||||
},
|
||||
{
|
||||
"name": "BSAT 3A/3C/JCSAT 110R/N-Sat 110",
|
||||
"pos": 1100
|
||||
},
|
||||
{
|
||||
"name": "ChinaSat 10",
|
||||
"pos": 1105
|
||||
},
|
||||
{
|
||||
"name": "Koreasat 5/Palapa D",
|
||||
"pos": 1130
|
||||
},
|
||||
{
|
||||
"name": "ChinaSat 6B",
|
||||
"pos": 1155
|
||||
},
|
||||
{
|
||||
"name": "ABS 7/Koreasat 6",
|
||||
"pos": 1160
|
||||
},
|
||||
{
|
||||
"name": "AsiaSat 3S/Telkom 2",
|
||||
"pos": 1180
|
||||
},
|
||||
{
|
||||
"name": "Thaicom 4",
|
||||
"pos": 1195
|
||||
},
|
||||
{
|
||||
"name": "AsiaSat 4",
|
||||
"pos": 1222
|
||||
},
|
||||
{
|
||||
"name": "JCSAT 4B",
|
||||
"pos": 1240
|
||||
},
|
||||
{
|
||||
"name": "ChinaSat 6A",
|
||||
"pos": 1250
|
||||
},
|
||||
{
|
||||
"name": "JCSAT 3A",
|
||||
"pos": 1280
|
||||
},
|
||||
{
|
||||
"name": "JCSAT 5A/Vinasat 1/2",
|
||||
"pos": 1320
|
||||
},
|
||||
{
|
||||
"name": "Apstar 6",
|
||||
"pos": 1340
|
||||
},
|
||||
{
|
||||
"name": "Telstar 18",
|
||||
"pos": 1380
|
||||
},
|
||||
{
|
||||
"name": "Express AM5/AT2",
|
||||
"pos": 1400
|
||||
},
|
||||
{
|
||||
"name": "Superbird C2",
|
||||
"pos": 1440
|
||||
},
|
||||
{
|
||||
"name": "JCSAT 1B",
|
||||
"pos": 1500
|
||||
},
|
||||
{
|
||||
"name": "Optus D2",
|
||||
"pos": 1520
|
||||
},
|
||||
{
|
||||
"name": "JCSAT 2A",
|
||||
"pos": 1540
|
||||
},
|
||||
{
|
||||
"name": "Optus C1/D3",
|
||||
"pos": 1560
|
||||
},
|
||||
{
|
||||
"name": "ABS 6",
|
||||
"pos": 1590
|
||||
},
|
||||
{
|
||||
"name": "Optus D1",
|
||||
"pos": 1600
|
||||
},
|
||||
{
|
||||
"name": "Superbird B2",
|
||||
"pos": 1620
|
||||
},
|
||||
{
|
||||
"name": "Optus 10/B3",
|
||||
"pos": 1640
|
||||
},
|
||||
{
|
||||
"name": "Intelsat 19",
|
||||
"pos": 1660
|
||||
},
|
||||
{
|
||||
"name": "Intelsat 8",
|
||||
"pos": 1690
|
||||
},
|
||||
{
|
||||
"name": "Eutelsat 172A",
|
||||
"pos": 1720
|
||||
},
|
||||
{
|
||||
"name": "Intelsat 18",
|
||||
"pos": 1800
|
||||
}
|
||||
]
|
Before Width: | Height: | Size: 31 KiB After Width: | Height: | Size: 23 KiB |
Before Width: | Height: | Size: 40 KiB After Width: | Height: | Size: 18 KiB |
Before Width: | Height: | Size: 108 KiB After Width: | Height: | Size: 40 KiB |
Before Width: | Height: | Size: 39 KiB After Width: | Height: | Size: 35 KiB |
BIN
docs/docresources/configdvrtab.png
Normal file
After Width: | Height: | Size: 61 KiB |
Before Width: | Height: | Size: 51 KiB |
Before Width: | Height: | Size: 47 KiB |
Before Width: | Height: | Size: 60 KiB |
BIN
docs/docresources/configgeneraltab.png
Normal file
After Width: | Height: | Size: 38 KiB |
Before Width: | Height: | Size: 36 KiB |
Before Width: | Height: | Size: 41 KiB |
Before Width: | Height: | Size: 51 KiB |
Before Width: | Height: | Size: 27 KiB After Width: | Height: | Size: 32 KiB |
Before Width: | Height: | Size: 31 KiB |
Before Width: | Height: | Size: 96 KiB After Width: | Height: | Size: 123 KiB |
Before Width: | Height: | Size: 32 KiB |
Before Width: | Height: | Size: 43 KiB |
Before Width: | Height: | Size: 84 KiB |
Before Width: | Height: | Size: 90 KiB |
Before Width: | Height: | Size: 27 KiB |
Before Width: | Height: | Size: 40 KiB |
Before Width: | Height: | Size: 105 KiB |
|
@ -7,9 +7,9 @@ wide open.
|
|||
|
||||
<p>
|
||||
When Tvheadend verifies access is scan through all the enabled access control entries.
|
||||
The permission flags, streaming profiles, DVR config profiles, channel tags are combined
|
||||
for all matching access entries. An access entry is said to match if the username / password
|
||||
matches and the IP source address of the requesting peer is within the prefix.
|
||||
The permission flags are combined for all matching access entries.
|
||||
An access entry is said to match if the username / password matches and the IP source
|
||||
address of the requesting peer is within the prefix.
|
||||
<p>
|
||||
|
||||
The access rules are listed / edited in a grid.
|
||||
|
@ -32,113 +32,70 @@ The access rules are listed / edited in a grid.
|
|||
</ul>
|
||||
|
||||
<p>
|
||||
<br>
|
||||
<hr>
|
||||
<b>Columns</b>
|
||||
<hr>
|
||||
The columns have the following functions:
|
||||
<br><br>
|
||||
|
||||
<dl>
|
||||
<dt><b>Enabled</b>
|
||||
<dd>Enable this access control rule. Uncheck the box to disable.
|
||||
<dt>Enabled
|
||||
<dd>Make the entry participate in access control. If disabled, the entry
|
||||
is inactive.
|
||||
|
||||
<dt><b>Username</b>
|
||||
<dt>Username
|
||||
<dd>
|
||||
Login name to be used. If no username is required, this entry should contain a single asterisk (*).
|
||||
Name of user, if no username is needed for match it should contain a
|
||||
single asterisk (*).
|
||||
|
||||
<dt><b>Password</b>
|
||||
<dt>Password
|
||||
<dd>
|
||||
Login password to be used. If username is '*' (unused), the password should be the same (i.e. match any username/password combination, or no username/password required).
|
||||
Password to combine with user, if username is '*' (unused), the password
|
||||
should be the same.
|
||||
|
||||
<dt><b>Network prefix</b>
|
||||
<dt>Prefix
|
||||
<dd>
|
||||
IPv4 prefix for matching based on source IP address.
|
||||
If set to 0.0.0.0/0 it will match everything.
|
||||
The multiple networks can be delimited using comma or semicolon.
|
||||
|
||||
<dt><b>Web interface</b>
|
||||
<dt>Streaming
|
||||
<dd>
|
||||
Required for web user interface access. Also gives access to the EPG.
|
||||
Enables access to streaming function. The 'streaming' access is enough to
|
||||
make Showtime (over HTSP) work.
|
||||
|
||||
<dt><b>Admin</b>
|
||||
<dd>
|
||||
Enables access to the Configuration tab.
|
||||
|
||||
<dt><b>Streaming</b>
|
||||
<dd>
|
||||
Enables access to streaming functionality for HTTP (web).
|
||||
|
||||
<dt><b>Advanced Streaming</b>
|
||||
<dd>
|
||||
Enables access to advanced streaming function for HTTP (web) - like direct
|
||||
service or whole MPEG-TS stream (mux)..
|
||||
|
||||
<dt><b>HTSP Streaming</b>
|
||||
<dd>
|
||||
Enables access to streaming for the HTSP protocol (Movian, Kodi etc.).
|
||||
|
||||
<dt><b>Streaming Profile</b>
|
||||
<dd>
|
||||
Specify a streaming profile to be used when this user logs in; use the (default) stream if not specified.
|
||||
|
||||
<dt><b>Limit Connections</b>
|
||||
<dd>
|
||||
If set, this will limit the number of concurrent streaming connections a user is permitted to have. 0=disabled
|
||||
|
||||
<dt><b>Video Recorder</b>
|
||||
<dt>Video Recorder
|
||||
<dd>
|
||||
Enables access to all video recording functions. This also include administration of the auto recordings.
|
||||
|
||||
<dt><b>HTSP DVR</b>
|
||||
<dt>All Configs (VR)
|
||||
<dd>
|
||||
Enables access to video recording functions for the HTSP protocol (Movian, Kodi etc.).
|
||||
Allow use of and configuration of DVR configuration profiles.
|
||||
|
||||
<dt><b>All DVR</b>
|
||||
<dt>Web interface
|
||||
<dd>
|
||||
Enable to access to DVR entries created by other users (read-only).
|
||||
Required for web user interface access. Also gives access to the EPG.
|
||||
|
||||
<dt><b>All DVR (rw)</b>
|
||||
<dt>Admin
|
||||
<dd>
|
||||
Enable to access to DVR entries created by other users with the ability to
|
||||
remove the DVR entries.
|
||||
|
||||
<dt><b>DVR Config Profile</b>
|
||||
Enables access to the Configuration tab.
|
||||
|
||||
<dt>Channel Tag Only
|
||||
<dd>
|
||||
If set, the user will only be able to use the DVR config profile
|
||||
equal to this value.
|
||||
Note that this field is unset when the DVR Config Profile is removed.
|
||||
If enabled, the user will only be able to access channels with a tag the
|
||||
same name as the username.
|
||||
|
||||
<dt><b>Min Channel Num</b>
|
||||
<dd>
|
||||
If non-zero, this sets the lower limit of the channels accessible by a user, i.e. the user will only be able to access channels where the channel number is equal to or greater than this value.
|
||||
This provides a very rudimentary way of limiting access to certain channels.
|
||||
|
||||
<dt><b>Max Channel Num</b>
|
||||
<dd>
|
||||
If non-zero, this sets the upper limit of the channels accessible by a user, i.e. the user will only be able to access channels where the channel number is equal to or less than this value.
|
||||
|
||||
<dt><b>Channel Tag</b>
|
||||
<dd>
|
||||
If set, the user will only be able to access channels containing
|
||||
this channel tag.
|
||||
Note that this field is unset when the channel tag is removed.
|
||||
|
||||
<dt><b>Comment</b>
|
||||
<dt>Comment
|
||||
<dd>
|
||||
Allows the administrator to set a comment only visible in this editor.
|
||||
It does not serve any active purpose.
|
||||
</dl>
|
||||
|
||||
<p>
|
||||
<br>
|
||||
<hr>
|
||||
Let's also take a look at an example:
|
||||
<p>
|
||||
<img src="docresources/accessconfigexample.png">
|
||||
<p>
|
||||
First line gives clients originating from 192.168.0.0 - 192.168.0.255 network
|
||||
access to streaming functions. Typically you would use this for your
|
||||
local media players at home (All though Movian can prompt for username & password
|
||||
local media players at home (All though Showtime can prompt for username & password
|
||||
in its HTSP client)
|
||||
<p>
|
||||
The second line adds a user with world wide access who might want to modify
|
||||
|
|
|
@ -1,43 +0,0 @@
|
|||
<div class="hts-doc-text">
|
||||
|
||||
<p>
|
||||
To use bouquets, ensure to add and scan all available muxes using
|
||||
the predefined muxes or manual configuration.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The bouquets are obtained automatically from the DVB source during
|
||||
the mux scan period. Note that bouquets may use more muxes and only
|
||||
services from scanned muxes are added. The mux with bouquets might
|
||||
require another scan when all muxes are discovered (manually using
|
||||
the rescan checkbox).
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The fastscan bouquets are pre-defined in the configuration tree. These
|
||||
bouquets must be manually enabled to let tvheadend to subscribe and listen
|
||||
to the specific MPEG-TS PIDs.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The bouquets are listed / edited in a grid.
|
||||
|
||||
<ul>
|
||||
<li>To edit a cell, double click on it. After a cell is changed it
|
||||
will flags one of its corner to red to indicated that it has been
|
||||
changed. To commit these changes back to Tvheadend press the
|
||||
'Save changes' button. In order to change a Checkbox cell you only
|
||||
have to click once in it.
|
||||
|
||||
<li>To add a new entry, press the 'Add entry' button. The new (empty) entry
|
||||
will be created on the server but will not be in its enabled state.
|
||||
You can now change all the cells to the desired values, check the
|
||||
'enable' box and then press 'Save changes' to activate the new entry.
|
||||
|
||||
<li>To delete one or more entries, select the lines (by clicking once on
|
||||
them), and press the 'Delete selected' button. A popup
|
||||
will ask you to confirm your request.
|
||||
</ul>
|
||||
</p>
|
||||
|
||||
</div>
|
|
@ -1,64 +1,7 @@
|
|||
<div class="hts-doc-text">
|
||||
|
||||
Tvheadend support connecting to card clients via the cwc (newcamd) or capmt
|
||||
(dvbapi) protocol for so called softcam descrambling.
|
||||
|
||||
<p>
|
||||
<img src="docresources/configcwc.png">
|
||||
|
||||
<p>
|
||||
The servers are listed / edited in a grid.
|
||||
|
||||
<ul>
|
||||
<li>To edit a cell, double click on it. After a cell is changed it
|
||||
will flags one of its corner to red to indicated that it has been
|
||||
changed. To commit these changes back to Tvheadend press the
|
||||
'Save changes' button. In order to change a Checkbox cell you only
|
||||
have to click once in it.
|
||||
|
||||
<li>To add a new entry, press the 'Add entry' button. The new (empty) entry
|
||||
will be created on the server but will not be in its enabled state.
|
||||
You can now change all the cells to the desired values, check the
|
||||
'enable' box and then press 'Save changes' to activate the new entry.
|
||||
|
||||
<li>To delete one or more entries, select the lines (by clicking once on
|
||||
them), and press the 'Delete selected' button. A pop up
|
||||
will ask you to confirm your request.
|
||||
</ul>
|
||||
|
||||
<p>
|
||||
The columns have the following functions:
|
||||
|
||||
<dl>
|
||||
<dt>Enabled
|
||||
<dd>If selected, connection will be tried to be established and retained up.
|
||||
If unselected, Tvheadend will disconnect (if connected) and not try to reconnect.
|
||||
|
||||
<dt>Hostname
|
||||
<dd>Server hostname. DNS lookup is performed upon every connection attempt.
|
||||
|
||||
<dt>Port
|
||||
<dd>Server TCP port
|
||||
|
||||
<dt>Username
|
||||
<dd>Username to use.
|
||||
|
||||
<dt>Password
|
||||
<dd>Password to use.
|
||||
|
||||
<dt>DES Key
|
||||
<dd>Initial DES key.
|
||||
|
||||
<dt>Update Card
|
||||
<dd>Forward Entitlement Management Messages (EMMs) to the server.
|
||||
|
||||
<dt>Update One
|
||||
<dd>Forward EMMs only from one channel at a time.
|
||||
|
||||
<dt>Comment
|
||||
<dd>Allows the administrator to set a comment only visible in this editor.
|
||||
It does not serve any active purpose.
|
||||
</dl>
|
||||
Tvheadend support connecting to card clients via the capmt protocol for so called softcam
|
||||
descrambling.
|
||||
|
||||
<p>
|
||||
<img src="docresources/configcapmt.png">
|
||||
|
@ -155,18 +98,6 @@
|
|||
pmt_mode = 4
|
||||
</dl>
|
||||
|
||||
<dt>mode 5 (new OSCam since revision 10087)
|
||||
<dd>Similar to mode 3 (TCP), but uses a new network protocol which also added
|
||||
client/server greeting messages and protocol version information (to be able
|
||||
to smoothly detect enhancements in the future).<br><br>
|
||||
<b>This is currently the preferred mode (the other may be removed in future)!</b><br><br>
|
||||
The following lines are required in <b>[dvbapi]</b> section of oscam.conf file:
|
||||
<dl>
|
||||
<dt>boxtype = pc<br>
|
||||
pmt_mode = 4<br>
|
||||
listen_port = 9000 # or your preferred port<br>
|
||||
</dl>
|
||||
|
||||
<dt>Comment
|
||||
<dd>Allows the administrator to set a comment only visible in this editor.
|
||||
It does not serve any active purpose.
|
|
@ -21,23 +21,6 @@
|
|||
The columns have the following functions:
|
||||
|
||||
<dl>
|
||||
<dt>Play
|
||||
<dd>Direct play link using the HTTP streaming.
|
||||
|
||||
<dl>
|
||||
<dt>URL to the stream using a channel name
|
||||
<dd>http://<i>host:port</i>/play/stream/channelname/<i>channel_name</i>
|
||||
<dt>URL to the stream using a channel number
|
||||
<dd>http://<i>host:port</i>/play/stream/channelnumber/<i>channel_number</i>
|
||||
</dl>
|
||||
|
||||
<dt>Enabled
|
||||
<dd>Whether or not the mux is enabled and thus available.
|
||||
|
||||
<dd>Channel number. This is not used by Tvheadend internally, but rather
|
||||
intended to be used by HTSP clients for mapping to remote control
|
||||
buttons, presentation order, etc
|
||||
|
||||
<dt>Number
|
||||
<dd>Channel number. This is not used by Tvheadend internally, but rather
|
||||
intended to be used by HTSP clients for mapping to remote control
|
||||
|
@ -53,12 +36,6 @@
|
|||
display a direct link that can be used to open in preferred media
|
||||
player.
|
||||
|
||||
<dt>Auto EPG Channel
|
||||
<dd>Auto-link EPG channels from XMLTV and OpenTV EPG grabbers using
|
||||
the channel name for matching. If you turn this option off, only
|
||||
OTA EPG grabber will be used for this channel unless the EPG Grab
|
||||
Source option (bellow) is not set manually.
|
||||
|
||||
<dt>EPG Grab Source
|
||||
<dd>Name of the Internet-based EPG provider (typically XMLTV) channel
|
||||
that should be used to update this channels EPG info.
|
||||
|
@ -77,13 +54,10 @@
|
|||
in the EPG if you have many channels. The tags are also presented
|
||||
in a Media player.
|
||||
|
||||
<dt>User Icon
|
||||
<dt>Icon
|
||||
<dd>An URL pointing to an image representing the channel.
|
||||
The icon URL will be set automatically when importing data from
|
||||
XMLTV, when picon path is set or when channel icon path is set
|
||||
in the general config. This field allows the user to edit it manually. The
|
||||
reset icon action allows to re-set the automatic URL for
|
||||
selected channel (e.g. after configuration change).
|
||||
XMLTV. This field allows the user to edit it manually.
|
||||
|
||||
<dt>DVR Pre-Start
|
||||
<dd>Allows the user to specify an amount of extra time that should
|
||||
|
|
61
docs/html/config_cwc.html
Normal file
|
@ -0,0 +1,61 @@
|
|||
<div class="hts-doc-text">
|
||||
|
||||
Tvheadend support connecting to card servers for so called softcam descrambling.
|
||||
|
||||
<p>
|
||||
<img src="docresources/configcwc.png">
|
||||
|
||||
<p>
|
||||
The servers are listed / edited in a grid.
|
||||
|
||||
<ul>
|
||||
<li>To edit a cell, double click on it. After a cell is changed it
|
||||
will flags one of its corner to red to indicated that it has been
|
||||
changed. To commit these changes back to Tvheadend press the
|
||||
'Save changes' button. In order to change a Checkbox cell you only
|
||||
have to click once in it.
|
||||
|
||||
<li>To add a new entry, press the 'Add entry' button. The new (empty) entry
|
||||
will be created on the server but will not be in its enabled state.
|
||||
You can now change all the cells to the desired values, check the
|
||||
'enable' box and then press 'Save changes' to activate the new entry.
|
||||
|
||||
<li>To delete one or more entries, select the lines (by clicking once on
|
||||
them), and press the 'Delete selected' button. A pop up
|
||||
will ask you to confirm your request.
|
||||
</ul>
|
||||
|
||||
<p>
|
||||
The columns have the following functions:
|
||||
|
||||
<dl>
|
||||
<dt>Enabled
|
||||
<dd>If selected, connection will be tried to be established and retained up.
|
||||
If unselected, Tvheadend will disconnect (if connected) and not try to reconnect.
|
||||
|
||||
<dt>Hostname
|
||||
<dd>Server hostname. DNS lookup is performed upon every connection attempt.
|
||||
|
||||
<dt>Port
|
||||
<dd>Server TCP port
|
||||
|
||||
<dt>Username
|
||||
<dd>Username to use.
|
||||
|
||||
<dt>Password
|
||||
<dd>Password to use.
|
||||
|
||||
<dt>DES Key
|
||||
<dd>Initial DES key.
|
||||
|
||||
<dt>Update Card
|
||||
<dd>Forward Entitlement Management Messages (EMMs) to the server.
|
||||
|
||||
<dt>Update One
|
||||
<dd>Forward EMMs only from one channel at a time.
|
||||
|
||||
<dt>Comment
|
||||
<dd>Allows the administrator to set a comment only visible in this editor.
|
||||
It does not serve any active purpose.
|
||||
</dl>
|
||||
</div>
|
|
@ -1,10 +1,6 @@
|
|||
<div class="hts-doc-text">
|
||||
|
||||
<img src="docresources/configdvrtab1.png">
|
||||
<br>
|
||||
<img src="docresources/configdvrtab2.png">
|
||||
<br>
|
||||
<img src="docresources/configdvrtab3.png">
|
||||
<img src="docresources/configdvrtab.png">
|
||||
|
||||
<p>
|
||||
This tab is used to configure operation of the Digital Video Recorder.
|
||||
|
@ -60,13 +56,8 @@
|
|||
<dd>If checked, broadcasts with matching title and matching non-zero episode number
|
||||
are considered duplicates.
|
||||
|
||||
<dt>EPG update window
|
||||
<dd>Maximum difference between event start times when the EPG event is changed.
|
||||
TVHeadend uses a fuzzy match logic (using title, start times,
|
||||
duration, episode) to check when the event was changed.
|
||||
|
||||
<dt>Post-processor command
|
||||
<dd>Command to run after finishing a recording. The command will be run in background and is executed even if a recording is aborted or an error occurred. Use the %e error formatting string to check for errors, the error string is "OK" if recording finished successfully.
|
||||
<dd>Command to run after finishing a recording. The command will be run in background and is executed even if a recording is aborted or an error occurred. Use the %e error formatting string to check for errors, the error string is empty if recording finished successfully.
|
||||
<br><br>
|
||||
Support format strings:<br>
|
||||
<table class="hts-doc-text" border="0">
|
||||
|
@ -176,19 +167,10 @@
|
|||
<dd>If checked, insert the episode number before the data and time rather than after (assumes <i>Include date</i>, <i>Include time</i> and <i>Include episode</i> options are set).
|
||||
|
||||
<dt>Remove all unsafe characters from filename
|
||||
<dd>If checked, all characters that could possibly cause problems for filenaming will be replaced with '_'.<br>
|
||||
Applies to characters:<br>
|
||||
* not supported by Windows characters: <i>/ : \ < > | * ? ' "</i><br>
|
||||
* control characters (ASCII code below 32)<br>
|
||||
* control and national characters (ASCII code above 122)<br>
|
||||
<dd>If checked, all characters that could possibly cause problems for filenaming will be removed.
|
||||
|
||||
<dt>Replace whitespace in title with '-'
|
||||
<dd>If checked, whitespace characters (spaces and tabs) will be replaced with '-'.
|
||||
|
||||
<dt>Use Windows-compatible filenames
|
||||
<dd>If checked:<br>
|
||||
* special characters not supported by Windows like: <i>/ : \ < > | * ? ' "</i> will be replaced with '_'<br>
|
||||
* trailing spaces ' ' and dots '.' will be removed
|
||||
<dd>If checked, all whitespace characters will be replaced with '-'.
|
||||
|
||||
</dl>
|
||||
Changes to any of these settings must be confirmed by pressing the 'Save configuration' button before taking effect.
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<div class="hts-doc-text">
|
||||
|
||||
This table defines rules to filter and order the elementary streams
|
||||
(PIDs) like video or audio from the input feed.
|
||||
like video or audio from the input feed.
|
||||
|
||||
<p>
|
||||
The execution order of commands is granted. It means that first rule
|
||||
|
@ -90,20 +90,10 @@ The columns have the following functions:
|
|||
<dt>USE
|
||||
<dd>Use this elementary stream.
|
||||
|
||||
<dt>ONE_TIME
|
||||
<dd>Use this elementary stream only one time per service type (like
|
||||
video, audio, subtitles) and language. The first sucessfully
|
||||
compared rule wins. For example, when one AC3 elementary stream
|
||||
is marked to be used with 'eng' language and another rule with
|
||||
the ONE_TIME action was matched, the new AC3 elementary stream
|
||||
will not be added if the language for new AC3 elementary stream
|
||||
is 'eng'. Note that the second rule might not have the language
|
||||
filter (column) set.
|
||||
<p>
|
||||
For the CA filter, this rule means that the new CA elementary stream
|
||||
is added only if another CA is not already used.
|
||||
</p>
|
||||
|
||||
<dt>ONCE
|
||||
<dd>Use this elementary stream only once per service type.
|
||||
The language is distinguished, too.
|
||||
The first successfully compared rule wins.
|
||||
|
||||
<dt>EXCLUSIVE
|
||||
<dd>Use only this elementary stream. No other elementary streams
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
<div class="hts-doc-text">
|
||||
|
||||
<img src="docresources/configgeneraltab1.png">
|
||||
<br>
|
||||
<img src="docresources/configgeneraltab2.png">
|
||||
<img src="docresources/configgeneraltab.png">
|
||||
|
||||
<p>
|
||||
This tabs allow configuration of several general parameters that affect the
|
||||
|
@ -60,44 +58,16 @@
|
|||
<dt>Update tolerance (milliseconds)</dt>
|
||||
<dd>Only update the system clock (doesn't affect NTP driver) if the delta
|
||||
between the system clock and DVB time is greater than this. This can help
|
||||
stop excessive oscillations on the system clock.</dd>
|
||||
stop horrible oscillations on the system clock.</dd>
|
||||
|
||||
<br><br>
|
||||
<hr>
|
||||
<b>Picon</b>
|
||||
<hr>
|
||||
|
||||
<dd>Picons (from p ersonal icons) are collections of similar icons that can be automatically
|
||||
matched against your channels based on a number of technical parameters that will uniquely
|
||||
define a channel. The use of these parameters (e.g. mux, frequency, orbital position)
|
||||
removes the ambiguity of using names - it's not case sensitive, it doesn't care if there
|
||||
are spaces or not, and so on.
|
||||
|
||||
You can generate picons yourself from existing images, or you can usually find sets
|
||||
pre-made on the Internet if you search for them. They're a good way to get large numbers
|
||||
of icons matched quickly, and usually in a similar style (such as square, x * y pixels, with
|
||||
a consistent highlight/reflection effect).</dd>
|
||||
|
||||
<dl>
|
||||
<dt>Prefer picons over channel name:</dt>
|
||||
<dd>If both a picon and a channel-specific (e.g. channelname.jpg) icon are defined, use the picon.</dd>
|
||||
|
||||
<dt>Channel icon path</dt>
|
||||
<dd>Path to an icon for this channel. This can be named however you wish, as a local (file://) or remote (http://) image.
|
||||
The following placeholders are available:<br>
|
||||
<ul>
|
||||
<li>%C - the transliterated channel name in ASCII (safe characters, no spaces etc.)</li>
|
||||
<li>%c - the channel name (URL encoded ASCII)</li>
|
||||
</ul>
|
||||
Example: file:///tmp/icons/%C.png or http://example.com/%c.png</dd>
|
||||
|
||||
<dt>Picon path</dt>
|
||||
<dd>Path to a directory (folder) containing your picon collection. This can be named however
|
||||
you wish, as a local (file://) or remote (http://) location - however, remember that it's pointing
|
||||
to a directory as the picon names are automatically generated from the service parameters
|
||||
frequency, orbital position, etc.).<br>
|
||||
Example: file:///home/hts/picons</dd>
|
||||
</dl>
|
||||
|
||||
<br><br>
|
||||
<hr>
|
||||
<b>Transcoding</b>
|
||||
<hr>
|
||||
|
||||
<dd>If enabled at build time (src/plumbing/transcoding.c), this allows you to switch transcoding support on and off.</dd>
|
||||
|
||||
<br><br>
|
||||
<hr>
|
||||
|
@ -131,72 +101,5 @@
|
|||
|
||||
</dl>
|
||||
|
||||
<br><br>
|
||||
<hr>
|
||||
<b>SAT>IP Server</b>
|
||||
<hr>
|
||||
|
||||
<dd>SAT>IP Server is something like DVB network tuner. TVHeadend can
|
||||
forward mpegts input streams including on-the-fly descramling to SAT>IP
|
||||
clients.</dd>
|
||||
|
||||
<dd>Only networks with the "SAT>IP Source" field set are exported
|
||||
through the SAT>IP protocol. This field is matched through the "src"
|
||||
parameter asked from the SAT>IP client. Usually (and by default) this value is 1.
|
||||
For satellite tuners, this value determines the satellite source (dish).
|
||||
By specification position 1 = DiseqC AA, 2 = DiseqC AB, 3 = DiseqC BA,
|
||||
4 = DiseqC BB, but any numbers may be used - depends on the SAT>IP client.
|
||||
Note that if you use a similar number for multiple networks, the first matched
|
||||
network containing the mux with requested parameters will win
|
||||
(also for unknown mux).</dd>
|
||||
|
||||
<dl>
|
||||
|
||||
<dt>RTSP Port
|
||||
<dd>
|
||||
Select RTSP port (TCP) for realtime commands from SAT>IP clients. Usually
|
||||
(as defined in the specification) this port is 554. But as extension,
|
||||
TVHeadend can use any TCP port value (which is default 9983 for non-root
|
||||
users). But the SAT>IP client must allow to set this value (TVHeadend
|
||||
client will obtain the RTSP port number automatically using the XML
|
||||
description). If the RTSP port value is zero, the SAT>IP server
|
||||
functionality is not enabled.
|
||||
|
||||
<dt>Subscription Weight
|
||||
<dd>
|
||||
Subscription weight value. Default value is 100 (standard streaming). Note
|
||||
that the default value for DVR is 300 (normal priority).
|
||||
|
||||
<dt>Descramble Services
|
||||
<dd>
|
||||
The maximum limit of services descrambled per a mux. If zero, the
|
||||
descrambling functionality is disabled.
|
||||
|
||||
<dt>Muxes Handling
|
||||
<dd>
|
||||
When SAT>IP client requests new mux configuration, tvheadend can handle it
|
||||
in three ways. The auto (0) configuration means that if the mux does not exists,
|
||||
a temporary mux is created and removed when the client closes the
|
||||
connection. The keep (1) configuration will remember all successfuly scanned muxes.
|
||||
The reject (2) configuration will reject unknown muxes.
|
||||
|
||||
<dt>Exported DVB-T/T2 Tuners
|
||||
<dd>
|
||||
Exported DVB-T/T2 tuners - streaming instances.
|
||||
|
||||
<dt>Exported DVB-S/S2 Tuners
|
||||
<dd>
|
||||
Exported DVB-S/S2 tuners - streaming instances.
|
||||
|
||||
<dt>Exported DVB-C/C2 Tuners
|
||||
<dd>
|
||||
Exported DVB-C/C2 tuners - streaming instances.
|
||||
|
||||
<dt>Exported ATSC/DVB-C(AnnexB) Tuners
|
||||
<dd>
|
||||
Exported ATSC/DVB-C(AnnexB) - streaming instances.
|
||||
|
||||
</dl>
|
||||
|
||||
</dl>
|
||||
</div>
|
||||
|
|
|
@ -17,40 +17,7 @@
|
|||
<dd>Whether or not the mux is enabled and thus available.
|
||||
|
||||
<dt>EPG
|
||||
<dd>EPG scan setup
|
||||
|
||||
<dl>
|
||||
<dt>Disable
|
||||
<dd>Disable the EPG scan
|
||||
|
||||
<dt>Enable (auto)
|
||||
<dd>Enable the EPG scan (when some services from this mux are assigned to channels)
|
||||
|
||||
<dt>Force (auto)
|
||||
<dd>Force the EPG scan (everytime when the EPG scan is triggered)
|
||||
|
||||
<dt>Only EIT
|
||||
<dd>Do only EIT EPG scan (when some services from this mux are assigned to channels)
|
||||
|
||||
<dt>Only UK Freesat
|
||||
<dd>Do only UK Freesat EPG scan (when some services from this mux are assigned to channels)
|
||||
|
||||
<dt>Only UK Freeview
|
||||
<dd>Do only UK Freeview EPG scan (when some services from this mux are assigned to channels)
|
||||
|
||||
<dt>Only Viasat Baltic
|
||||
<dd>Do only Viasat Baltic EPG scan (when some services from this mux are assigned to channels)
|
||||
|
||||
<dt>Only OpenTV Sky UK
|
||||
<dd>Do only OpenTV Sky UK EPG scan (the TSID must match in the skyuk configuration file)
|
||||
|
||||
<dt>Only OpenTV Sky Italia
|
||||
<dd>Do only OpenTV Sky Italia EPG scan (the TSID must match in the skyit configuration file)
|
||||
|
||||
<dt>Only OpenTV Sky Ausat
|
||||
<dd>Do only OpenTV Sky Ausat EPG scan (the TSID must match in the ausat configuration file)
|
||||
|
||||
</dl>
|
||||
<dd>Whether or not to retrieve EPG information from the mux.
|
||||
|
||||
<dt>Network
|
||||
<dd>The name of the network to which the mux belongs. Networks are defined in Configuration -> DVB Inputs -> Networks - DVB-S or ATSC, for example.
|
||||
|
@ -73,45 +40,11 @@
|
|||
<dt>URL
|
||||
<dd>Mux URL.
|
||||
|
||||
<dl>
|
||||
<dt>udp://
|
||||
<dd>Raw MPEG-TS UDP packets
|
||||
|
||||
<dt>rtp://
|
||||
<dd>MPEG-TS UDP packets with RTP header
|
||||
|
||||
<dt>http://
|
||||
<dd>HTTP stream (MPEG-TS)
|
||||
|
||||
<dt>https://
|
||||
<dd>Secure HTTP stream (MPEG-TS)
|
||||
|
||||
<dt>pipe://
|
||||
<dd>Read standard output from an external program.
|
||||
If the program name does not have the first
|
||||
character '/', the PATH environment variable
|
||||
is used to find the program name in all
|
||||
directories specified by PATH.
|
||||
Additional arguments may be separated
|
||||
using spaces. A raw MPEG-TS stream is
|
||||
expected. The string ${service_name}
|
||||
is substituted with the service name
|
||||
field contents. The \ (backslash) character means
|
||||
"take the next character asis" (usually
|
||||
space or the backslash itself.
|
||||
|
||||
</dl>
|
||||
|
||||
<dt># Services
|
||||
<dd>The number of services found on this mux.
|
||||
|
||||
<dt>Character Set
|
||||
<dd>The character encoding for this mux (e.g. UTF-8).
|
||||
|
||||
<dt>PMT Descriptor 0x06 = AC-3
|
||||
<dd>Whether or not the empty PMT descriptor 0x06 defaults to
|
||||
the AC-3 stream. Some Chinese cable providers are using
|
||||
this. If unsure, keep this off.
|
||||
|
||||
<dt>Interface
|
||||
<dd>IPTV : the network interface/card on which the IPTV source can be found.
|
||||
|
@ -119,18 +52,7 @@
|
|||
<dt>ATSC
|
||||
<dd>whether or not this is an ATSC IPTV source.
|
||||
|
||||
<dt>Priority
|
||||
<dd>IPTV : The mux priority value (higher value = higher priority to use services from this mux). Value 0 means use the IPTV network priority value.
|
||||
|
||||
<dt>Streaming Priority
|
||||
<dd>IPTV : The mux priority value for streamed channels through HTTP or HTSP (higher value = higher priority to use services from this mux). Value 0 means use the standard streaming network priority value.
|
||||
|
||||
<dt>Environment (pipe)
|
||||
<dd>IPTV : List of environment variables for pipe (like PATH=/bin:/sbin)
|
||||
separated by spaces. The backslash character is handled like
|
||||
in URL.
|
||||
|
||||
<dt>Respawn (pipe)
|
||||
<dd>IPTV : Respawn the executed process when it dies.
|
||||
</dl>
|
||||
</div>
|
||||
|
|
|
@ -2,114 +2,52 @@
|
|||
<p>
|
||||
A network is the type of carrier for your television signals. Tvheadend supports several different types of network, notably:
|
||||
<dl>
|
||||
<li><b>DVB-C</b> : Cable TV, delivered via a cable to your house
|
||||
<li><b>DVB-S</b> : Satellite (includes S2), so any signal coming in via a dish
|
||||
<li><b>DVB-T</b> : Terrestrial, so over-the-air broadcasts received through a traditional television aerial
|
||||
<li><b>ATSC</b> : Over-the-air terrestrial, common in north and central America and parts of south Asia
|
||||
<li><b>IPTV</b> : IP, so over the Internet
|
||||
<li>DVB-C : Cable TV, delivered via a cable to your house
|
||||
<li>DVB-S : Satellite (includes S2), so any signal coming in via a dish
|
||||
<li>DVB-T : Terrestrial, so over-the-air broadcasts received through a traditional television aerial
|
||||
<li>ATSC : Over-the-air terrestrial, common in north and central America and parts of south Asia
|
||||
<li>IPTV : IP, so over the Internet
|
||||
</dl>
|
||||
</p>
|
||||
<p>
|
||||
<img src="docresources/configdvbnetwork.png">
|
||||
</p>
|
||||
<br>
|
||||
<hr>
|
||||
<b>Buttons</b>
|
||||
<hr>
|
||||
Buttons have the following functions:
|
||||
<br><br>
|
||||
<dl>
|
||||
<dt><b>Add</b>
|
||||
<dd>
|
||||
Add a new network. You can choose from any of the types described above.
|
||||
<p>
|
||||
<dt><b>Delete</b>
|
||||
<dd>
|
||||
Delete an existing network. This will also remove any association with an adapter.
|
||||
<p>
|
||||
<dt><b>Edit</b>
|
||||
<dd>
|
||||
Edit an existing network. This allows you to change any of the parameters you'd otherwise set when adding a new network, e.g. network discovery, idle scan, etc. - similar to using the check boxes to enable/disable functions.
|
||||
<p>
|
||||
<dt><b>Save</b>
|
||||
<dd>
|
||||
Saves any changes.
|
||||
<p>
|
||||
<dt><b>Undo</b>
|
||||
<dd>
|
||||
Undoes any changes.
|
||||
<p>
|
||||
</dl>
|
||||
<p>
|
||||
<br>
|
||||
<hr>
|
||||
<b>Columns</b>
|
||||
<hr>
|
||||
|
||||
The columns have the following functions:
|
||||
|
||||
<dl>
|
||||
<dt><b>Network Name</b>
|
||||
<dt>Network Name
|
||||
<dd>The name of the network. This can be set automatically or you can give it a name that means something to you (e.g. if you have multiple OTA networks).
|
||||
<p>
|
||||
<dt><b>Network Discovery</b>
|
||||
|
||||
|
||||
<dt>Network Discovery
|
||||
<dd>Whether automatic discovery is enabled for this network, i.e. whether Tvheadend looks for muxes or simply stays with the list of muxes as defined initially.
|
||||
<p>
|
||||
<dt><b>Skip initial Scan</b>
|
||||
<dd>Don't scan all muxes in this network at Tvheadend start.
|
||||
The initial scan procedure is not a blind scan. Only known muxes
|
||||
registered to this network are scanned. If Network Discovery
|
||||
is enabled and new muxes are discovered using DVB
|
||||
descriptors, these muxes will be scanned too.
|
||||
<p>
|
||||
<dt><b>Idle Scan Muxes</b>
|
||||
<dd>When nothing else happens Tvheadend will continuously rotate among all muxes and tune to them to verify that they are still working
|
||||
when the inputs are not used for streaming. If your adapter have problems with lots of (endless) tuning, try to disable this.
|
||||
Note that this option should be OFF for the normal operation. This type of mux probing is not required and
|
||||
it may cause issues for SAT>IP (limited number of PID filters).
|
||||
<p>
|
||||
<dt><b>Ignore Provider's Channel Numbers</b>
|
||||
<dd>Some providers will try to set a channel number so that every receiver is consistent - "tune to Channel x on 150". This option allows you to ignore this and let tvhheadend allocate a channel number itself.
|
||||
<p>
|
||||
<dt><b>Max Input Streams</b>
|
||||
|
||||
<dt>Skip initial Scan
|
||||
<dd>Don't scan this network for muxes at Tvheadend start.
|
||||
|
||||
<dt>Idle Scan Muxes
|
||||
<dd>When nothing else happens Tvheadend will continuously rotate among all muxes and tune to them to verify that they are still working. If your adapter have problems with lots of tuning, try to disable this.
|
||||
|
||||
<dt>Max Input Streams
|
||||
<dd>IPTV : maximum simultaneous streams that can be played.
|
||||
<p>
|
||||
<dt><b>Max Bandwidth</b>
|
||||
|
||||
<dt>Max Bandwidth
|
||||
<dd>IPTV : maximum bandwidth allowed for streams.
|
||||
<p>
|
||||
<dt><b>Max timeout</b>
|
||||
|
||||
<dt>Max timeout
|
||||
<dd>IPTV : maximum timeout trying to play stream.
|
||||
<p>
|
||||
<dt><b>Network ID</b>
|
||||
|
||||
<dt>Network ID
|
||||
<dd>If you experience problems caused by overlaps between multiple network
|
||||
providers this option can be used to filter which network ID is received
|
||||
by a given adapter.
|
||||
<p>
|
||||
<dt><b>Ignore Provider's Channel Numbers</b>
|
||||
<dd>Do not use the local channel numbers defined by provider.
|
||||
<p>
|
||||
<dt><b>SAT>IP Source Number</b>
|
||||
<dd>This field is matched through the "src" parameter asked from the
|
||||
SAT>IP client. Usually (and by default) this value is 1.
|
||||
For satellite tuners, this value determines the satellite source (dish).
|
||||
By specification position 1 = DiseqC AA, 2 = DiseqC AB, 3 = DiseqC BA,
|
||||
4 = DiseqC BB, but any numbers may be used - depends on the SAT>IP
|
||||
client. Note that if you use same number for multiple networks,
|
||||
the first matched network containing the mux with requested parameters
|
||||
will win (also for unknown mux). If this field is set to zero,
|
||||
the network cannot be used by the SAT>IP server.</dd>
|
||||
<p>
|
||||
<dt><b>EIT Local Time</b>
|
||||
<dd>EPG (EIT) events uses local time instead UTC.
|
||||
<p>
|
||||
<dt><b>Character Set</b>
|
||||
<dd>The character encoding for this network (e.g. UTF-8).
|
||||
<p>
|
||||
<dt><b>Priority</b>
|
||||
<dd>IPTV : The network priority value (higher value = higher priority to use muxes/services from this network).
|
||||
<p>
|
||||
<dt><b>Streaming Priority</b>
|
||||
<dd>IPTV : The network priority value for streamed channels through HTTP or HTSP (higher value = higher priority to use muxes/services from this
|
||||
network). If not set, the standard network priority value is used.
|
||||
|
||||
<dt>Character Set
|
||||
<dd>The character encoding for this network (e.g. UTF-8).
|
||||
|
||||
|
||||
|
||||
|
||||
</dl>
|
||||
</div>
|
||||
|
|
|
@ -18,17 +18,6 @@
|
|||
<dt>Enabled
|
||||
<dd>Whether or not this service is available for use
|
||||
|
||||
<dt>Automatic Checking
|
||||
<dd>Check for the service presence. If service is no longer broadcasted,
|
||||
this field will become as "Missing In PAT/SDT". The
|
||||
check can be also disabled for given service using this
|
||||
column.
|
||||
|
||||
<dt>Priority
|
||||
<dd>Define priority (range 0-10) for this service. The higher value means more preferred.
|
||||
Note that this value is _added_ to the input (tuner) priority.
|
||||
Take this in account when you set the input priorities.
|
||||
|
||||
<dt>Channel
|
||||
<dd>The channel to which the service is mapped
|
||||
|
||||
|
|
|
@ -1,41 +0,0 @@
|
|||
<div class="hts-doc-text">
|
||||
|
||||
<p>
|
||||
<br>
|
||||
<hr>
|
||||
<b>Buttons</b>
|
||||
<hr>
|
||||
Buttons have the following functions:
|
||||
<br><br>
|
||||
<dl>
|
||||
<dt><b>Add</b>
|
||||
<dd>
|
||||
Add a new profile. You can choose from any of the types from the list.
|
||||
<p>
|
||||
<dt><b>Delete</b>
|
||||
<dd>
|
||||
Delete an existing profile.
|
||||
<p>
|
||||
<dt><b>Save</b>
|
||||
<dd>
|
||||
Saves any changes.
|
||||
<p>
|
||||
<dt><b>Undo</b>
|
||||
<dd>
|
||||
Undoes any changes.
|
||||
<p>
|
||||
</dl>
|
||||
|
||||
<p>
|
||||
<br>
|
||||
<hr>
|
||||
<b>Columns</b>
|
||||
<hr>
|
||||
The columns have the following functions:
|
||||
|
||||
<dl>
|
||||
<dt><b>Stream Profile Name</b>
|
||||
<dd>This column contains the name of Stream Profile.
|
||||
|
||||
</dl>
|
||||
</div>
|
|
@ -7,12 +7,12 @@
|
|||
Tags are used to define a set of channels.
|
||||
Notice that nothing prohibits a channel to be a member of multiple tags.
|
||||
Also, there is no requirement to configure tags for running Tvheadend
|
||||
itself. It is, however, required if you run Tvheadend together with Movian.
|
||||
itself. It is, however, required if you run Tvheadend together with Showtime.
|
||||
<p>
|
||||
The tag-sets are used for:
|
||||
<ul>
|
||||
<li>Searches in the EPG.
|
||||
<li>Display of channel groups in the Movian Media player.
|
||||
<li>Display of channel groups in the Showtime Media player.
|
||||
</ul>
|
||||
|
||||
<p>
|
||||
|
@ -48,16 +48,9 @@
|
|||
automatic recordings, groups, etc.
|
||||
|
||||
<dt>Internal
|
||||
<dd>Tags are exported via HTSP/HTTP and used there for grouping of
|
||||
TV channels. If you do not wish to export a tag you can flag
|
||||
it as internal only.
|
||||
|
||||
<dt>Private
|
||||
<dd>Tags are exported via HTSP/HTTP and used there for grouping of TV
|
||||
channels. If you do not wish to export a tag to other users you can
|
||||
flag it as private only. Only users with this tag configured
|
||||
in the access configuration (or users with not set tags) can
|
||||
use it.
|
||||
<dd>Tags are exported via HTSP (to the Showtime Media player) and used
|
||||
there for grouping of TV channels. If you do not wish to export a
|
||||
tag you can flag it as internal only.
|
||||
|
||||
<dt>Icon
|
||||
<dd>Full path to an icon used to depict the tag. This can be a TV network
|
||||
|
|
|
@ -36,11 +36,6 @@
|
|||
specify an unlimited period its highly recommended you specifying a value
|
||||
here.
|
||||
|
||||
<dt>Max. RAM Size (MegaBytes)
|
||||
<dd>Specifies the maximum RAM (system memory) size for timeshift buffers.
|
||||
When free RAM buffers are available, they are used instead storage to
|
||||
save the timeshift data.
|
||||
|
||||
<dt>Unlimited:
|
||||
<dd>If checked, this allows the combined size of all timeshift buffers to
|
||||
potentially grow unbounded until your storage media runs out of space
|
||||
|
|
|
@ -8,167 +8,71 @@
|
|||
you only have to click once in it.
|
||||
</ul>
|
||||
</p>
|
||||
<p>
|
||||
<img src="docresources/configtvadapters.png">
|
||||
</p>
|
||||
<br>
|
||||
<hr>
|
||||
<b>Rows</b>
|
||||
<hr>
|
||||
The rows have the following functions
|
||||
<br><br>
|
||||
<dt><u><i><b>Basic Settings</b></i></u></dt>
|
||||
|
||||
<h4>The rows have the following functions</h4>
|
||||
|
||||
<dl>
|
||||
<dt><b>Enabled</b></dt>
|
||||
<dd>If selected, this tuner/adapter will be enabled and will become available to receive broadcasts or programmes.</dd>
|
||||
<p>
|
||||
<dt><b>Name</b></dt>
|
||||
<dt>Enabled</dt>
|
||||
<dd>If selected, the IPTV service will be enabled an use for channel
|
||||
subscriptions.</dd>
|
||||
|
||||
<dt>Name</dt>
|
||||
<dd>The name of this tuner.</dd>
|
||||
<p>
|
||||
<dt><b>Over-the-Air EPG</b></dt>
|
||||
<dd>Enable over-the-air programme guide (EPG) scanning on this input device.</dd>
|
||||
<p>
|
||||
<dt><b>Networks</b></dt>
|
||||
<dd>Associate this device with one or more networks.</dd>
|
||||
<p>
|
||||
</dl>
|
||||
<dt><u><i><b>Advanced Settings</b></i></u></dt>
|
||||
<dl>
|
||||
<dt><b>Priority</b></dt>
|
||||
|
||||
<dt>OTA EPG</dt>
|
||||
<dd>Allow OTA EPG (epggrab) scan on this input device</dd>
|
||||
|
||||
<dt>Priority</dt>
|
||||
<dd>The tuner priority value (higher value = higher priority to use this
|
||||
tuner).</dd>
|
||||
<p>
|
||||
<dt><b>Streaming Priority</b></dt>
|
||||
<dd>The tuner priority value for streamed channels through HTTP or HTSP
|
||||
(higher value = higher priority to use this tuner). If not set (zero),
|
||||
the standard priority value is used.</dd>
|
||||
<p>
|
||||
<dt><b>Init Scan</b></dt>
|
||||
<dd>Allow the initial scan tuning on this device. See to
|
||||
Skip initial Scan in the network settings for the further description.</dd>
|
||||
<p>
|
||||
<dt><b>Idle Scan</b></dt>
|
||||
<dd>Allow the idle scan tuning on this device.</dd>
|
||||
<p>
|
||||
<dt><b>Linked Input</b></dt>
|
||||
<dd>Always make alive also the linked input. The subscriptions are named as "keep".</dd>
|
||||
</dl>
|
||||
</p>
|
||||
|
||||
<br>
|
||||
<hr>
|
||||
<b>LinuxDVB Specific Rows</b>
|
||||
<hr>
|
||||
</dl>
|
||||
</p>
|
||||
|
||||
<h4>LinuxDVB specific rows</h4>
|
||||
|
||||
<dl>
|
||||
<dt><b>Power Save</b></dt>
|
||||
<dd>If enabled, allows the tuner to go to sleep when idle.</dd>
|
||||
<p>
|
||||
<dt><b>Tune Before DiseqC</b></dt>
|
||||
<dd>If set, one tune request (setup) is proceed before the DiseqC
|
||||
sequence (voltage, tone settings). Some linux drivers require this
|
||||
procedure.</dd>
|
||||
<p>
|
||||
<dt><b>Tune Repeats</b></dt>
|
||||
<dd>If set, the tune requests are repeated using this number. Zero means
|
||||
one tune requests, one two tune requests etc.</dd>
|
||||
<p>
|
||||
<dt><b>Skip Initial Bytes</b></dt>
|
||||
<dd>If set, first bytes from the MPEG-TS stream are discarded. It may be
|
||||
required for some drivers / hardware which does not flush completely
|
||||
the MPEG-TS buffers after a frequency/parameters change.</dd>
|
||||
<p>
|
||||
<dt><b>Input Buffer (Bytes)</b></dt>
|
||||
<dd>By default, linuxdvb input buffer is 18800 bytes long. The accepted
|
||||
range is 18800-1880000 bytes.</dd>
|
||||
<p>
|
||||
<dt><b>Status Period</b></dt>
|
||||
<dd>By default, linuxdvb status read period is 1000ms (one second). The
|
||||
accepted range is 250ms to 8000ms. Note that for some hardware /
|
||||
drivers (like USB), the status operations takes too much time and CPU.
|
||||
In this case, increase the default value. For fast hardware, this value
|
||||
might be descreased to make the decision of the re-tune algorithm
|
||||
based on the signal status faster.</dd>
|
||||
<p>
|
||||
<dt><b>Force old status</b></dt>
|
||||
<dd>Always use the old ioctls to read the linuxdvb status (signal strenght,
|
||||
SNR, error counters). Some drivers are not matured enough to provide
|
||||
the correct values using the new v5 linuxdvb API.</dd>
|
||||
</dl>
|
||||
<dt>Keep FE open</dt>
|
||||
<dd>Enable to not close the LinuxDVB frontend device in the idle state.</dd>
|
||||
</dl>
|
||||
|
||||
<br>
|
||||
<hr>
|
||||
<b>LinuxDVB Satellite Config Rows</b>
|
||||
<hr>
|
||||
<h4>SAT>IP specific rows</h4>
|
||||
|
||||
<dl>
|
||||
<dt><b>DiseqC repeats</b></dt>
|
||||
<dd>Number of repeats for the DiseqC commands (default is zero - no DiseqC repeats).</dd>
|
||||
<p>
|
||||
<dt><b>Full DiseqC</b></dt>
|
||||
<dd>Always sent the whole DiseqC sequence including LNB setup (voltage, tone).
|
||||
If this is not checked, only changed settings is set. It may cause
|
||||
issues with some drivers. If the tuning is not reliable, try to
|
||||
activate this option.</dd>
|
||||
<p>
|
||||
<dt><b>Turn off LNB when idle</b></dt>
|
||||
<dd>Turn off LNB when it is not used. It may save some power.</dd>
|
||||
<p>
|
||||
<dt><b>Switch Then Rotor</b></dt>
|
||||
<dd>If the DiseqC switch is before rotor (tuner - switch - rotor), enable this.</dd>
|
||||
<p>
|
||||
<dt><b>Init Rotor Time (seconds)</b></dt>
|
||||
<dd>Upon new start, tvheadend does not know the last rotor position. This
|
||||
value defined the initial rotor movement. TVHeadend waits the
|
||||
specified seconds when the first movement is requested.</dd>
|
||||
<dt><b>Min Rotor Time (seconds)</b></dt>
|
||||
<dd>The minimum delay after the rotor movement command is send.</dd>
|
||||
</dl>
|
||||
|
||||
<p>
|
||||
<br>
|
||||
<hr>
|
||||
<b>SAT>IP Specific Rows</b>
|
||||
<hr>
|
||||
|
||||
<dl>
|
||||
<dt><b>Full Mux Rx mode supported</b></dt>
|
||||
<dd>Enable if the SAT>IP box supports the full mux rx mode (pids=all)<br>
|
||||
note: no comma after 'Enable'</dd>
|
||||
<p>
|
||||
<dt><b>Signal scale (240 or 100)</b></dt>
|
||||
<dd>Some SAT>IP boxes only report a 0-100 (percentage) signal strength. If your signal strength reports as too low, try
|
||||
setting this to 100.</dd>
|
||||
<p>
|
||||
<dt><b>Maximum PIDs</b><dt>
|
||||
<dt>Full Mux Rx mode supported</dt>
|
||||
<dd>Enable, if the SAT>IP box supports the full mux rx mode (pids=all)
|
||||
parameter.</dd>
|
||||
|
||||
<dt>Signal scale (240 or 100)</dt>
|
||||
<dd>Some SAT>IP boxes has only 0-100 scale. If your signal is too low, try
|
||||
value 100 here.</dd>
|
||||
|
||||
<dt>Maximum PIDs<dt>
|
||||
<dd>Maximum supported PIDs in the filter of the SAT>IP box.</dd>
|
||||
<p>
|
||||
<dt><b>Maximum length of PIDs</b><dt>
|
||||
|
||||
<dt>Maximum length of PIDs<dt>
|
||||
<dd>Maximum length in characters for the command setting PIDs to the
|
||||
SAT>IP box.</dd>
|
||||
<p>
|
||||
<dt><b>Addpids/delpids supported</b></dt>
|
||||
<dd>Enable if the SAT>IP box supports the addpids/delpids command.
|
||||
<p>
|
||||
<dt><b>PIDs in setup</b></dt>
|
||||
|
||||
<dt>addpids/delpids supported</dt>
|
||||
<dd>Enable, if the SAT>IP box supports the addpids/delpids command.
|
||||
|
||||
<dt>PIDs in setup</dt>
|
||||
<dd>Enable, if the SAT>IP box requires pids=0 parameter in the SETUP RTSP command.</dd>
|
||||
<p>
|
||||
<dt><b>Double RTSP Shutdown</b></dt>
|
||||
<dd>Enable, if the SAT>IP box might require to send twice the RTSP SHUTDOWN command.</dd>
|
||||
<p>
|
||||
<dt><b>Force pilot for DVB-S2</b></dt>
|
||||
|
||||
<dt>Force pilot for DVB-S2</dt>
|
||||
<dd>Enable, if the SAT>IP box requiest plts=on parameter in the SETUP RTSP
|
||||
command for DVB-S2 muxes.</dd>
|
||||
<p>
|
||||
<dt><b>UDP RTP Port Number (2 ports)</b></dt>
|
||||
|
||||
<dt>UDP RTP Port Number (2 ports)</dt>
|
||||
<dd>Force the local UDP Port number here. The number should be even (RTP port).
|
||||
The next odd number (+1) will be used as the RTCP port.</dd>
|
||||
<p>
|
||||
<dt><b>Satellite Positions</b></dt>
|
||||
|
||||
<dt>Satellite Positions</dt>
|
||||
<dd>Select the number of satellite positions supported by the SAT>IP
|
||||
hardware and your coaxial cable wiring.</dd>
|
||||
<p>
|
||||
<dt><b>Master Tuner</b></dt>
|
||||
|
||||
<dt>Master Tuner</dt>
|
||||
<dd>Select the master tuner.
|
||||
<p>The signal from the standard universal LNB can be split using
|
||||
a simple coaxial splitter (no multiswitch) to several outputs.
|
||||
|
@ -178,22 +82,21 @@ setting this to 100.</dd>
|
|||
a slave one and tvheadend will assure that this tuner will not
|
||||
use incompatible parameters (position, polarization, lo-hi).</p>
|
||||
</dd>
|
||||
<P>
|
||||
<dt><b>Next tune delay in ms (0-2000)</b></dt>
|
||||
|
||||
<dt>Next tune delay in ms (0-2000)</dt>
|
||||
<dd>The delay before tuning in milliseconds after tuner stop. If the time
|
||||
after previous start and next start is greater than this value -
|
||||
the delay is not applied.</dt>
|
||||
<p>
|
||||
<dt><b>Send full PLAY cmd</b></dt>
|
||||
|
||||
<dt>Send full PLAY cmd</dt>
|
||||
<dd>Send the full RTSP PLAY command after full RTSP SETUP command. Some
|
||||
device firmwares requires this to get MPEG-TS stream.</dd>
|
||||
<p>
|
||||
<dt><b>Force teardown delay</b><dt>
|
||||
|
||||
<dt>Force teardown delay<dt>
|
||||
<dd>Force the delay between RTSP TEARDOWN and RTSP SETUP command (value
|
||||
from 'Next tune delay in ms' is used). Some devices are not able to handle
|
||||
quick continuous tuning.</dd>
|
||||
|
||||
</dl>
|
||||
</p>
|
||||
|
||||
</div>
|
||||
|
|
|
@ -24,15 +24,5 @@
|
|||
<dd></dd>
|
||||
|
||||
</dl>
|
||||
<p>
|
||||
Changes to any of these settings must be confirmed by pressing
|
||||
the 'Save configuration' button before taking effect.
|
||||
</p>
|
||||
<p>
|
||||
Note that the settings is not saved to a storage. It is available
|
||||
only until the actual tvheadend process is running. If you like to change the
|
||||
default behaviour permanently, use the command line options like -l,
|
||||
--debug, --trace. This configuration is stored usually in the /etc/sysconfig
|
||||
tree (depending on the distribution) or an init script.
|
||||
<p>
|
||||
Changes to any of these settings must be confirmed by pressing the 'Save configuration' button before taking effect.
|
||||
</div>
|
||||
|
|
|
@ -1,118 +1,5 @@
|
|||
<div class="hts-doc-section">Automatic recordings</div>
|
||||
<div class="hts-doc-text">
|
||||
This tab is used to create and maintain Digital Video Recorder rules. These can be EPG-driven (such as those created from the initial EPG tab) through the DVR AutoRec Entries tab , or can be timer-based through the Time Schedules tab.
|
||||
<br>
|
||||
<br>
|
||||
This tab controls EPG-driven recording rules.
|
||||
<p>
|
||||
<img src="docresources/dvrautorecentries.png">
|
||||
</p>
|
||||
<p>
|
||||
<br>
|
||||
<hr>
|
||||
<b>Buttons</b>
|
||||
<hr>
|
||||
Buttons have the following functions:
|
||||
<br><br>
|
||||
<dl>
|
||||
<dt><b>Add</b>
|
||||
<dd>
|
||||
Add and configure a recording rule - define the channel, schedule, DVR configuration, priority, etc.
|
||||
<p>
|
||||
<dt><b>Delete</b>
|
||||
<dd>
|
||||
Delete an existing recording rule.
|
||||
<p>
|
||||
<dt><b>Edit</b>
|
||||
<dd>
|
||||
Manually edit an existing recording rule. This uses the same fields as <b>Add</b>, but they're pre-populated with their current values.
|
||||
<p>
|
||||
<dt><b>Save</b>
|
||||
<dd>
|
||||
Saves any changes made to the recording rule list.
|
||||
<p>
|
||||
<dt><b>Undo</b>
|
||||
<dd>
|
||||
Undoes any changes made to the recording rules list (any changed fields will be marked with a small red triangle).
|
||||
<p>
|
||||
</dl>
|
||||
<p>
|
||||
<br>
|
||||
<hr>
|
||||
<b>Columns</b>
|
||||
<hr>
|
||||
The columns have the following functions:
|
||||
<br><br>
|
||||
<dl>
|
||||
<dt><b>Enabled</b>
|
||||
<dd>
|
||||
Check or clear this box to enable or disable this rule.
|
||||
<p>
|
||||
<dt><b>Name</b>
|
||||
<dd>
|
||||
The name you've given to the rule, e.g. 'Stuff involving Jeremy Clarkson'.
|
||||
<p>
|
||||
<dt><b>Directory</b>
|
||||
<dd>
|
||||
When specified, this setting overrides the subdirectory rules (except the base directory) specified by the DVR configuration
|
||||
and puts all recordings done by this entry into the specified subdirectory. Useful for e.g. recording multiple different news
|
||||
broadcasts into one common subdirectory called "News". The backshlash and other special characters are escaped, so it is possible
|
||||
to create only one sublevel subdirectories (the base path for the target directory is always taken from the DVR configuration).
|
||||
<p>
|
||||
<dt><b>Title (Regexp)</b>
|
||||
<dd>
|
||||
The title of the programme to look for. Note that this accepts case-insensitive regular expressions, so you can use pattern matching as Tvheadend scans the EPG for programmes to record.
|
||||
<p>
|
||||
<dt><b>Fulltext</b>
|
||||
<dd>
|
||||
When the fulltext is checked, the title pattern is matched against title,
|
||||
subtitle, summary and description.
|
||||
<p>
|
||||
<dt><b>Channel</b>
|
||||
<dd>
|
||||
The channel on which this rule applies, i.e. the channel you're aiming to record.
|
||||
<p>
|
||||
<dt><b>Channel Tag</b>
|
||||
<dd>
|
||||
A channel tag (e.g. a group of channels) on which this rule applies.
|
||||
<p>
|
||||
<dt><b>Content Type</b>
|
||||
<dd>
|
||||
The content type (Movie/Drama, Sports...) to be used to filter matching events/programmes.
|
||||
<p>
|
||||
<dt><b>Minimal Duration</b>
|
||||
<dd>
|
||||
The minimal duration of a matching event - in other words, only match programmes that are no shorter than this duration.
|
||||
<p>
|
||||
<dt><b>Maximal Duration</b>
|
||||
<dd>
|
||||
The maximal duration of a matching event - in other words, only match programmes that are no longer than this duration.
|
||||
<p>
|
||||
<dt><b>Week Days</b>
|
||||
<dd>
|
||||
On which specific days of the week to find matching programmes.
|
||||
<p>
|
||||
<dt><b>Start After</b>
|
||||
<dd>
|
||||
An event which starts between this "start after" and "start before" will be matched (including boundary values).
|
||||
<p>
|
||||
<dt><b>Start Before</b>
|
||||
<dd>
|
||||
An event which starts between this "start after" and "start before" will be matched (including boundary values).
|
||||
<p>
|
||||
<dt><b>Priority</b>
|
||||
<dd>
|
||||
The priority of any recordings set because of this rule: important, high, normal, low, unimportant.
|
||||
<p>
|
||||
<dt><b>DVR Configuration</b>
|
||||
<dd>
|
||||
The DVR configuration (e.g. extra start/stop time, post-processing rules) to be used for any recordings set because of this rule.
|
||||
<p>
|
||||
<dt><b>Creator</b>
|
||||
<dd>
|
||||
The creator of the rule. Automatically set.
|
||||
<p>
|
||||
<dt><b>Comment</b>
|
||||
<dd>
|
||||
A free-text comment. Not used otherwise.
|
||||
<p>
|
||||
is niiice.
|
||||
|
||||
</div>
|
||||
|
|
|
@ -1,82 +0,0 @@
|
|||
<div class="hts-doc-text">
|
||||
This tab show your all failed recordings.
|
||||
|
||||
<p>
|
||||
<img src="docresources/failedrecordings1.png">
|
||||
</p>
|
||||
<p>
|
||||
<br>
|
||||
<hr>
|
||||
<b>Buttons</b>
|
||||
<hr>
|
||||
Buttons have the following functions:
|
||||
<br><br>
|
||||
<dl>
|
||||
<dt><b>Delete</b>
|
||||
<dd>
|
||||
If clicked delete selected failed recordings you delete recordings. Before deleted show message: Do you really want to delete the selection ? Answer Yes or No.
|
||||
<p>
|
||||
<dt><b>Download</b>
|
||||
<dd>
|
||||
Click this button to download the selected failed recordings to a local disk. You will be prompted to select the path for the saved file(s).
|
||||
</dl>
|
||||
<p>
|
||||
<br>
|
||||
<hr>
|
||||
<b>Columns</b>
|
||||
<hr>
|
||||
The columns have the following functions:
|
||||
<br><br>
|
||||
<dl>
|
||||
<dt><b>Details</b>
|
||||
<dd>
|
||||
Show red status and blue icon "i". After click on icon "i" you see info about select failed recordings.
|
||||
<p>
|
||||
<img src="docresources/failedrecordings2.png">
|
||||
<p>
|
||||
<dt><b>Play</b>
|
||||
<dd>
|
||||
Can play selected record in web browser by VLC Plugin or other external player.
|
||||
<p>
|
||||
<dt><b>Title</b>
|
||||
<dd>
|
||||
Showing title of record.
|
||||
<p>
|
||||
<dt><b>Episod</b>
|
||||
<dd>
|
||||
Showing number episod of record.
|
||||
<p>
|
||||
<dt><b>Scheduled Start Time</b>
|
||||
<dd>
|
||||
Showing date and time when the recording was started.
|
||||
<p>
|
||||
<dt><b>Scheduled Stop Time</b>
|
||||
<dd>
|
||||
Showing date and time when the recording was stoped.
|
||||
<p>
|
||||
<dt><b>Duration</b>
|
||||
<dd>
|
||||
Showing how long it took the recording.
|
||||
<p>
|
||||
<dt><b>File Size</b>
|
||||
<dd>
|
||||
<p>
|
||||
Showing size of file recording.
|
||||
<dt><b>Channel Name</b>
|
||||
<dd>
|
||||
Showing the name of the channel from which the recording was made.
|
||||
<p>
|
||||
<dt><b>Creator</b>
|
||||
<dd>
|
||||
Showing the name of the user who created the recording.
|
||||
<p>
|
||||
<dt><b>Schedule Status</b>
|
||||
<dd>
|
||||
Showing the status info of record.
|
||||
<p>
|
||||
<dt><b>URL</b>
|
||||
<dd>
|
||||
Showing the URL of record.
|
||||
<p>
|
||||
|
||||
</div>
|
|
@ -1,82 +0,0 @@
|
|||
<div class="hts-doc-text">
|
||||
This tab show your all finished recordings.
|
||||
|
||||
<p>
|
||||
<img src="docresources/finishedrecordings1.png">
|
||||
</p>
|
||||
<p>
|
||||
<br>
|
||||
<hr>
|
||||
<b>Buttons</b>
|
||||
<hr>
|
||||
Buttons have the following functions:
|
||||
<br><br>
|
||||
<dl>
|
||||
<dt><b>Delete</b>
|
||||
<dd>
|
||||
If clicked delete selected finished recordings you delete recordings. Before deleted show message: Do you really want to delete the selection ? Answer Yes or No.
|
||||
<p>
|
||||
<dt><b>Download</b>
|
||||
<dd>
|
||||
Click this button to download the selected finished recordings to a local disk. You will be prompted to select the path for the saved file(s).
|
||||
</dl>
|
||||
<p>
|
||||
<br>
|
||||
<hr>
|
||||
<b>Columns</b>
|
||||
<hr>
|
||||
The columns have the following functions:
|
||||
<br><br>
|
||||
<dl>
|
||||
<dt><b>Details</b>
|
||||
<dd>
|
||||
Show green status and blue icon "i". After click on icon "i" you see info about select finished recordings.
|
||||
<p>
|
||||
<img src="docresources/finishedrecordings2.png">
|
||||
<p>
|
||||
<dt><b>Play</b>
|
||||
<dd>
|
||||
Can play selected record in web browser by VLC Plugin or other external player.
|
||||
<p>
|
||||
<dt><b>Title</b>
|
||||
<dd>
|
||||
Showing title of record.
|
||||
<p>
|
||||
<dt><b>Episod</b>
|
||||
<dd>
|
||||
Showing number episod of record.
|
||||
<p>
|
||||
<dt><b>Scheduled Start Time</b>
|
||||
<dd>
|
||||
Showing date and time when the recording was started.
|
||||
<p>
|
||||
<dt><b>Scheduled Stop Time</b>
|
||||
<dd>
|
||||
Showing date and time when the recording was stoped.
|
||||
<p>
|
||||
<dt><b>Duration</b>
|
||||
<dd>
|
||||
Showing how long it took the recording.
|
||||
<p>
|
||||
<dt><b>File Size</b>
|
||||
<dd>
|
||||
<p>
|
||||
Showing size of file recording.
|
||||
<dt><b>Channel Name</b>
|
||||
<dd>
|
||||
Showing the name of the channel from which the recording was made.
|
||||
<p>
|
||||
<dt><b>Creator</b>
|
||||
<dd>
|
||||
Showing the name of the user who created the recording.
|
||||
<p>
|
||||
<dt><b>Schedule Status</b>
|
||||
<dd>
|
||||
Showing the status info of record.
|
||||
<p>
|
||||
<dt><b>URL</b>
|
||||
<dd>
|
||||
Showing the URL of record.
|
||||
<p>
|
||||
|
||||
</div>
|
|
@ -1,101 +0,0 @@
|
|||
<div class="hts-doc-text">
|
||||
This tab is used to create and maintain Digital Video Recorder rules. These can be EPG-driven (such as those created from the initial EPG tab) through the DVR AutoRec Entries tab , or can be timer-based through the Time Schedules tab.
|
||||
<br>
|
||||
<br>
|
||||
This tab controls timer-driven recording rules.
|
||||
<p>
|
||||
<img src="docresources/timeschedules.png">
|
||||
<p>
|
||||
<br>
|
||||
<hr>
|
||||
<b>Buttons</b>
|
||||
<hr>
|
||||
Buttons have the following functions:
|
||||
<br><br>
|
||||
<dl>
|
||||
<dt><b>Add</b>
|
||||
<dd>
|
||||
Add and configure a recording rule - define the channel, schedule, DVR configuration, priority, etc.
|
||||
<p>
|
||||
<dt><b>Delete</b>
|
||||
<dd>
|
||||
Delete an existing recording rule.
|
||||
<p>
|
||||
<dt><b>Edit</b>
|
||||
<dd>
|
||||
Manually edit an existing recording rule. This uses the same fields as Add, but they're pre-populated with their current values.
|
||||
<p>
|
||||
<dt><b>Save</b>
|
||||
<dd>
|
||||
Saves any changes made to the recording rule list.
|
||||
<p>
|
||||
<dt><b>Undo</b>
|
||||
<dd>
|
||||
Undoes any changes made to the recording rules list (any changed fields will be marked with a small red triangle).
|
||||
<p>
|
||||
</dl>
|
||||
<p>
|
||||
<br>
|
||||
<hr>
|
||||
<b>Columns</b>
|
||||
<hr>
|
||||
The columns have the following functions:
|
||||
<br><br>
|
||||
<dl>
|
||||
<dt><b>Enabled</b>
|
||||
<dd>
|
||||
Check or clear this box to enable or disable this rule.
|
||||
<p>
|
||||
<dt><b>Name</b>
|
||||
<dd>
|
||||
The name you've given to the rule, e.g. 'Evening cartoons for the children'.
|
||||
<p>
|
||||
<dt><b>Directory</b>
|
||||
<dd>
|
||||
When specified, this setting overrides the subdirectory rules specified by the DVR configuration and puts all recordings done by this entry into the specified subdirectory. Useful for e.g. recording multiple different news broadcasts into one common subdirectory called "News".
|
||||
<p>
|
||||
<dt><b>Title</b>
|
||||
<dd>
|
||||
The title is used in the filename that is created for the recording
|
||||
<br>
|
||||
<br>
|
||||
The default format string suggests Time-[date]_[time]:
|
||||
<br>
|
||||
<br>
|
||||
The escape-codes use <a href="http://man7.org/linux/man-pages/man3/strftime.3.html">strftime</a> format. Examples:
|
||||
<br>
|
||||
%F The date in ISO-format (e.g. 2015-02-28)
|
||||
<br>
|
||||
%R The time in 24h HH:MM format (e.g. 19:45)
|
||||
<br>
|
||||
%x The date, formatted according to your locale settings
|
||||
<p>
|
||||
<dt><b>Channel</b>
|
||||
<dd>
|
||||
The channel on which this rule applies, i.e. the channel you're aiming to record.
|
||||
<p>
|
||||
<dt><b>Week Days</b>
|
||||
<dd>
|
||||
On which specific days of the week you wish this rule to be active (e.g. only record channel XXX at xx:yy on Saturdays and Sundays).
|
||||
<p>
|
||||
<dt><b>Start</b>
|
||||
<dd>
|
||||
Start recording at this time.
|
||||
<p>
|
||||
<dt><b>Stop</b>
|
||||
<dd>
|
||||
Stop recording at this time.
|
||||
<p>
|
||||
<dt><b>Priority</b>
|
||||
<dd>
|
||||
The priority of any recordings set because of this rule: important, high, normal, low, unimportant.
|
||||
<p>
|
||||
<dt><b>DVR Configuration</b>
|
||||
<dd>
|
||||
The DVR configuration (e.g. extra start/stop time, post-processing rules) to be used for any recordings set because of this rule.
|
||||
<p>
|
||||
<dt><b>Comment</b>
|
||||
<dd>
|
||||
A free-text comment. Not used otherwise.
|
||||
<p>
|
||||
</div>
|
|
@ -1,103 +0,0 @@
|
|||
<div class="hts-doc-text">
|
||||
This tab show your all upcoming/current recordings.
|
||||
|
||||
<p>
|
||||
<img src="docresources/upcomingrecordings1.png">
|
||||
</p>
|
||||
<p>
|
||||
<br>
|
||||
<hr>
|
||||
<b>Buttons</b>
|
||||
<hr>
|
||||
Buttons have the following functions:
|
||||
<br><br>
|
||||
<dl>
|
||||
<dt><b>Add</b>
|
||||
<dd>
|
||||
Add and configure a recording event by hand as opposed to choosing something from the EPG. This is useful if you wish to record something that isn't yet in the EPG, or record at a particular time that perhaps spans several EPG events.
|
||||
<p>
|
||||
<dt><b>Delete</b>
|
||||
<dd>
|
||||
If clicked delete selected upcoming/current recordings you delete recordings. Before deleted show message: Do you really want to delete the selection ? Answer Yes or No.
|
||||
<p>
|
||||
<dt><b>Abort</b>
|
||||
<dd>
|
||||
Abort an already-underway recording. Note that this does not remove the (partial) recording file from disk.
|
||||
<p>
|
||||
<dt><b>Edit</b>
|
||||
<dd>
|
||||
Manually edit an already-scheduled recording event. This uses the same fields as <b>Add</b>, but they're obviously pre-populated with their current values.
|
||||
<p>
|
||||
<dt><b>Save</b>
|
||||
<dd>
|
||||
Saves any changes made to the recording list.
|
||||
<p>
|
||||
<dt><b>Undo</b>
|
||||
<dd>
|
||||
Undoes any changes made to the recording list.
|
||||
<p>
|
||||
</dl>
|
||||
<p>
|
||||
<br>
|
||||
<hr>
|
||||
<b>Columns</b>
|
||||
<hr>
|
||||
The columns have the following functions:
|
||||
<br><br>
|
||||
<dl>
|
||||
<dt><b>Details</b>
|
||||
<dd>
|
||||
Shows the status of the recording event:<br>
|
||||
<br>
|
||||
<b>Clock</b> - the recording is scheduled (upcoming).<br>
|
||||
<br>
|
||||
<b>Record symbol (red circle)</b> - the recording is active and underway (current).<br>
|
||||
<br>
|
||||
<b>InInfo</b> - displays detailed information about the selected recording (upcoming or current).<br>
|
||||
<p>
|
||||
<img src="docresources/upcomingrecordings2.png">
|
||||
<p>
|
||||
<dt><b>Title</b>
|
||||
<dd>
|
||||
The title (name) of the recording. While this is copied from the EPG when you create a recording, it's not used to match the event itself and is thus used here as the name of the event (see also: adding an event manually with the <b>Add</b> button).
|
||||
<p>
|
||||
<dt><b>Episode</b>
|
||||
<dd>
|
||||
The episode number of the recording (whether this is available depends on your broadcaster and/or EPG data source).
|
||||
<p>
|
||||
<dt><b>Priority</b>
|
||||
<dd>
|
||||
The priority of the recording: Not set, Important, High, Normal, Low, Unimportant.
|
||||
<br>
|
||||
If there is a clash, more important recordings will take priority over less important ones.
|
||||
<p>
|
||||
<dt><b>Scheduled Start Time</b>
|
||||
<dd>
|
||||
The date and time when the scheduled recording will start. Note that this includes any extra time defined in the recording profile (e.g. "start two minutes earlier than the EPG start time").
|
||||
<p>
|
||||
<dt><b>Scheduled Stop Time</b>
|
||||
<dd>
|
||||
The date and time when the scheduled recording will stop. Note that this includes any extra time defined in the recording profile (e.g. "finish recording five minutes after the EPG stop time").
|
||||
<p>
|
||||
<dt><b>Duration</b>
|
||||
<dd>
|
||||
The total duration of the scheduled recording, including any extra time before or after.
|
||||
<p>
|
||||
<dt><b>Channel Name</b>
|
||||
<dd>
|
||||
The channel to be recorded.
|
||||
<p>
|
||||
<dt><b>Creator</b>
|
||||
<dd>
|
||||
The user who created the recording or the auto-recording source and IP address if scheduled by a matching rule.
|
||||
<p>
|
||||
<dt><b>DVR Configuration</b>
|
||||
<dd>
|
||||
The DVR configuration to be used for this recording.
|
||||
<p>
|
||||
<dt><b>Schedule Status</b>
|
||||
<dd>
|
||||
The status of the recording(scheduled or recording).
|
||||
<p>
|
||||
|
||||
</div>
|
|
@ -20,8 +20,7 @@ sorted based on start time.</p>
|
|||
Only display events that match the given title. The filter uses case-insensitive
|
||||
regular expressions. If you don't know what a regular expression is, this simply
|
||||
means that you can type just parts of the title and filter on that - there's no need
|
||||
for full, exact matching. If the fulltext checkbox is checked, the title
|
||||
text is matched against title, subtitle, summary and description.</dd>
|
||||
for full, exact matching.</dd>
|
||||
<dt>[Filter channel...]</dt>
|
||||
<dd>
|
||||
Only display events from the selected channel. Channels in the drop down are
|
||||
|
|
|
@ -2,12 +2,12 @@
|
|||
|
||||
<dl>
|
||||
|
||||
<dt>Why does Tvheadend deliver data over TCP to Movian? I thought it was
|
||||
<dt>Why does Tvheadend deliver data over TCP to Showtime? I thought it was
|
||||
bad to use TCP for realtime sensitive traffic?
|
||||
|
||||
<dd>
|
||||
'HTSP' - the protocol used for streaming TV, sending meta information
|
||||
updates and RPC between Tvheadend and Movian uses a transmission
|
||||
updates and RPC between Tvheadend and Showtime uses a transmission
|
||||
scheduler with multiple queues on the Tvheadend side. This means that
|
||||
Tvheadend can measure the available bandwidth between itself and the
|
||||
mediaplayer and when congestion happens it's even capable of dropping
|
||||
|
@ -15,7 +15,7 @@
|
|||
links and DSL connections with zero picture/audio artifacts.
|
||||
<p>
|
||||
It's possible to get view drop statistics and bitrates directly in
|
||||
Movian. (Open the menu when watching a TV-channel and switch on
|
||||
Showtime. (Open the menu when watching a TV-channel and switch on
|
||||
'Detailed Information')
|
||||
|
||||
</div>
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
<dt>Input sources
|
||||
<dl>
|
||||
<dt>DVB-T, DVB-C, DVB-S, DVB-S2, ATSC and SAT>IP.
|
||||
<dt>DVB-T, DVB-C, DVB-S, DVB-S2 and ATSC.
|
||||
<dd>
|
||||
Multiple adapters are supported.
|
||||
Each adapter can receive all programs available on the currently
|
||||
|
@ -20,17 +20,13 @@
|
|||
</dd>
|
||||
<dt>Analog TV
|
||||
<dd>
|
||||
The IPTV extension URL - pipe:// allow to process any MPEG-TS input.
|
||||
FFMPEG or LIBAV library can be used to produce analog to digital
|
||||
conversion.
|
||||
Using the Video4Linux2 API. Currently, only PAL is supported.
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
<dt>Output targets
|
||||
<dl>
|
||||
<dt>HTTP (Web Protocol), supported by <a href="http://www.videolan.org/vlc/">VLC</a>, <a href="http://www.mplayerhq.hu">MPlayer</a>
|
||||
<dt>HTSP (Home TV Streaming Protocol), supported by <a href="http://movian.tv">Movian Media player</a> and <a href="http://kodi.tv/">Kodi</a>
|
||||
<dt>SAT>IP Server
|
||||
<dt>HTSP (Home TV Streaming Protocol), supported by Showtime Media player and <a href="http://www.xbmc.org/">XBMC</a>
|
||||
<dt>The Built-in Digital Video Recorder
|
||||
</dl>
|
||||
|
||||
|
@ -44,7 +40,7 @@
|
|||
All setup and configuration is done from the built in web user interface.
|
||||
Even so, all settings are stored in human readable text files.
|
||||
|
||||
<dt>Fully integrated with HTS Movian Media player or Kodi HTS PVR addon.
|
||||
<dt>Fully integrated with HTS Showtime Media player.
|
||||
<dd>
|
||||
All channel data and their grouping, EPG and TV streaming is conducted over a
|
||||
single TCP connection.
|
||||
|
@ -83,10 +79,6 @@
|
|||
<dd>
|
||||
Requires a card server (newcamd and capmt protocol is supported).
|
||||
|
||||
<dt>Hardware based CSA descrambling
|
||||
<dd>
|
||||
Requires the standard dvben50221 linuxdvb library.
|
||||
|
||||
<dt>Internationalization
|
||||
<dd>
|
||||
All text is encoded in UTF-8 to provide full international support. All major
|
||||
|
|
32
rpm/Makefile
|
@ -1,32 +0,0 @@
|
|||
#
|
||||
# RPM build
|
||||
# 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/>.
|
||||
#
|
||||
|
||||
include $(dir $(lastword $(MAKEFILE_LIST)))../.config.mk
|
||||
|
||||
COMMIT ?= $(shell git rev-parse HEAD)
|
||||
COMMIT1 = $(shell git rev-parse $(COMMIT))
|
||||
VERSION = $(shell cd .. && git describe --match "v*" $(COMMIT1) | sed -e 's/-/./g' -e 's/^v//g' )
|
||||
|
||||
tvheadend.spec: tvheadend.spec.in
|
||||
@sed -e 's/@VERSION@/$(VERSION)/g' \
|
||||
-e 's/@COMMIT@/$(COMMIT1)/g' \
|
||||
$< > $@
|
||||
|
||||
build: tvheadend.spec
|
||||
spectool --get-files --sourcedir tvheadend.spec
|
||||
rpmbuild -ba tvheadend.spec
|
|
@ -1,14 +0,0 @@
|
|||
[Unit]
|
||||
Description=Tvheadend - a TV streaming server and DVR
|
||||
After=syslog.target network.target auditd.service
|
||||
|
||||
[Service]
|
||||
EnvironmentFile=/etc/sysconfig/tvheadend
|
||||
ExecStart=/usr/bin/tvheadend -f -p /var/run/tvheadend.pid $OPTIONS
|
||||
PIDFile=/var/run/tvheadend.pid
|
||||
Type=forking
|
||||
Restart=on-failure
|
||||
RestartSec=54s
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
|
@ -1,91 +0,0 @@
|
|||
%global commit @COMMIT@
|
||||
%global shortcommit %(c=%{commit}; echo ${c:0:7})
|
||||
|
||||
Summary: Tvheadend - a TV streaming server and DVR
|
||||
Name: tvheadend
|
||||
Version: @VERSION@
|
||||
Release: 1
|
||||
|
||||
License: GPLv3
|
||||
Group: Applications/Multimedia
|
||||
URL: http://tvheadend.org
|
||||
|
||||
Source: https://github.com/tvheadend/tvheadend/archive/%{commit}/tvheadend-%{commit}.tar.gz
|
||||
#Patch999: test.patch
|
||||
|
||||
BuildRequires: systemd-units >= 1
|
||||
BuildRequires: dbus-devel
|
||||
BuildRequires: avahi-libs
|
||||
BuildRequires: openssl-devel
|
||||
BuildRequires: git wget
|
||||
|
||||
Requires: systemd-units >= 1
|
||||
|
||||
%description
|
||||
Tvheadend is a TV streaming server with DVR for Linux supporting
|
||||
DVB, ATSC, IPTV, SAT>IP as input sources. Can be used as a backend
|
||||
to Showtime, XBMC and various other clients.
|
||||
|
||||
%prep
|
||||
%setup -q -n tvheadend-%{commit}
|
||||
#%patch999 -p1 -b .test
|
||||
|
||||
%build
|
||||
echo %{version} > %{_builddir}/%{buildsubdir}/rpm/version
|
||||
%ifarch %arm
|
||||
%configure --disable-lockowner --enable-bundle --disable-libffmpeg_static
|
||||
%else
|
||||
%configure --disable-lockowner --enable-bundle --enable-libffmpeg_static
|
||||
%endif
|
||||
%{__make}
|
||||
|
||||
%install
|
||||
# binary
|
||||
mkdir -p -m755 %{buildroot}%{_bindir}
|
||||
install -p -m 755 build.linux/tvheadend %{buildroot}%{_bindir}
|
||||
# systemd
|
||||
mkdir -p -m755 %{buildroot}%{_sysconfdir}/sysconfig
|
||||
install -p -m 644 rpm/tvheadend.sysconfig %{buildroot}%{_sysconfdir}/sysconfig/tvheadend
|
||||
mkdir -p -m755 %{buildroot}%{_unitdir}
|
||||
install -p -m 644 rpm/tvheadend.service %{buildroot}%{_unitdir}
|
||||
|
||||
%pre
|
||||
getent group tvheadend >/dev/null || groupadd -f -g 283 -r tvheadend
|
||||
if ! getent passwd tvheadend > /dev/null ; then
|
||||
if ! getent passwd 283 > /dev/null ; then
|
||||
useradd -r -l -u 283 -g tvheadend -d /home/tvheadend -s /sbin/nologin -c "Tvheadend TV server" tvheadend
|
||||
else
|
||||
useradd -r -l -g tvheadend -d /home/tvheadend -s /sbin/nologin -c "Tvheadend TV server" tvheadend
|
||||
fi
|
||||
fi
|
||||
if ! test -d /home/tvheadend ; then
|
||||
mkdir -m 0755 /home/tvheadend || exit 1
|
||||
chown tvheadend.tvheadend /home/tvheadend || exit 1
|
||||
fi
|
||||
exit 0
|
||||
|
||||
%post
|
||||
%systemd_post tvheadend.service
|
||||
|
||||
%postun
|
||||
%systemd_postun_with_restart tvheadend.service
|
||||
|
||||
%files
|
||||
%{_bindir}/*
|
||||
%{_sysconfdir}/sysconfig/*
|
||||
%{_unitdir}/*
|
||||
|
||||
%changelog
|
||||
* Wed Mar 25 2015 Bob Lightfoot <boblfoot@gmail.com> 3.9-2658-gb427d7e
|
||||
- Patching rpm spec file so the arm architecture builds properly
|
||||
|
||||
* Mon Oct 13 2014 Jaroslav Kysela <perex@perex.cz> 3.9-1806-g6f3324e
|
||||
- RPM: Typo fixes
|
||||
|
||||
* Mon Oct 13 2014 Jaroslav Kysela <perex@perex.cz> 3.9-1805-g14a7de8
|
||||
- RPM build - config fixes
|
||||
|
||||
* Mon Oct 13 2014 Jaroslav Kysela <perex@perex.cz> 3.9-1803-g392dec0
|
||||
- Add basic RPM build support
|
||||
|
||||
~
|
|
@ -1,3 +0,0 @@
|
|||
# Configuration file for the tvheadend service.
|
||||
|
||||
OPTIONS="-c /home/tvheadend/config -u tvheadend -g tvheadend -6 --http_port 9981 --htsp_port 9982"
|
1342
src/access.c
148
src/access.h
|
@ -19,24 +19,19 @@
|
|||
#ifndef ACCESS_H_
|
||||
#define ACCESS_H_
|
||||
|
||||
#include "idnode.h"
|
||||
#include "htsmsg.h"
|
||||
|
||||
struct profile;
|
||||
struct dvr_config;
|
||||
struct channel_tag;
|
||||
|
||||
typedef struct access_ipmask {
|
||||
TAILQ_ENTRY(access_ipmask) ai_link;
|
||||
|
||||
int ai_family;
|
||||
int ai_ipv6;
|
||||
|
||||
struct in_addr ai_ip;
|
||||
struct in6_addr ai_ip6;
|
||||
|
||||
int ai_prefixlen;
|
||||
|
||||
uint32_t ai_netmask;
|
||||
uint32_t ai_network;
|
||||
uint32_t ai_netmask;
|
||||
} access_ipmask_t;
|
||||
|
||||
TAILQ_HEAD(access_entry_queue, access_entry);
|
||||
|
@ -44,62 +39,21 @@ TAILQ_HEAD(access_entry_queue, access_entry);
|
|||
extern struct access_entry_queue access_entries;
|
||||
|
||||
typedef struct access_entry {
|
||||
idnode_t ae_id;
|
||||
char *ae_id;
|
||||
|
||||
TAILQ_ENTRY(access_entry) ae_link;
|
||||
char *ae_username;
|
||||
char *ae_password;
|
||||
char *ae_password2;
|
||||
char *ae_comment;
|
||||
|
||||
int ae_index;
|
||||
int ae_enabled;
|
||||
|
||||
int ae_streaming;
|
||||
int ae_adv_streaming;
|
||||
int ae_htsp_streaming;
|
||||
|
||||
struct profile *ae_profile;
|
||||
LIST_ENTRY(access_entry) ae_profile_link;
|
||||
|
||||
uint32_t ae_conn_limit;
|
||||
|
||||
int ae_dvr;
|
||||
int ae_htsp_dvr;
|
||||
int ae_all_dvr;
|
||||
int ae_all_rw_dvr;
|
||||
struct dvr_config *ae_dvr_config;
|
||||
LIST_ENTRY(access_entry) ae_dvr_config_link;
|
||||
|
||||
int ae_webui;
|
||||
int ae_admin;
|
||||
|
||||
uint64_t ae_chmin;
|
||||
uint64_t ae_chmax;
|
||||
|
||||
struct channel_tag *ae_chtag;
|
||||
LIST_ENTRY(access_entry) ae_channel_tag_link;
|
||||
int ae_tagonly;
|
||||
|
||||
|
||||
uint32_t ae_rights;
|
||||
|
||||
TAILQ_HEAD(, access_ipmask) ae_ipmasks;
|
||||
} access_entry_t;
|
||||
|
||||
extern const idclass_t access_entry_class;
|
||||
|
||||
typedef struct access {
|
||||
char *aa_username;
|
||||
char *aa_representative;
|
||||
uint32_t aa_rights;
|
||||
htsmsg_t *aa_profiles;
|
||||
htsmsg_t *aa_dvrcfgs;
|
||||
uint64_t aa_chmin;
|
||||
uint64_t aa_chmax;
|
||||
htsmsg_t *aa_chtags;
|
||||
int aa_match;
|
||||
uint32_t aa_conn_limit;
|
||||
} access_t;
|
||||
|
||||
TAILQ_HEAD(access_ticket_queue, access_ticket);
|
||||
|
||||
extern struct access_ticket_queue access_tickets;
|
||||
|
@ -111,49 +65,27 @@ typedef struct access_ticket {
|
|||
|
||||
gtimer_t at_timer;
|
||||
char *at_resource;
|
||||
access_t *at_access;
|
||||
} access_ticket_t;
|
||||
|
||||
#define ACCESS_ANONYMOUS 0
|
||||
#define ACCESS_STREAMING (1<<0)
|
||||
#define ACCESS_ADVANCED_STREAMING (1<<1)
|
||||
#define ACCESS_HTSP_STREAMING (1<<2)
|
||||
#define ACCESS_WEB_INTERFACE (1<<3)
|
||||
#define ACCESS_RECORDER (1<<4)
|
||||
#define ACCESS_HTSP_RECORDER (1<<5)
|
||||
#define ACCESS_ALL_RECORDER (1<<6)
|
||||
#define ACCESS_ADMIN (1<<7)
|
||||
#define ACCESS_ALL_RW_RECORDER (1<<8)
|
||||
#define ACCESS_OR (1<<30)
|
||||
|
||||
#define ACCESS_FULL \
|
||||
(ACCESS_STREAMING | ACCESS_ADVANCED_STREAMING | \
|
||||
ACCESS_HTSP_STREAMING | ACCESS_WEB_INTERFACE | \
|
||||
ACCESS_RECORDER | ACCESS_HTSP_RECORDER | \
|
||||
ACCESS_ALL_RECORDER | ACCESS_ADMIN | ACCESS_ALL_RW_RECORDER)
|
||||
#define ACCESS_ANONYMOUS 0x0
|
||||
#define ACCESS_STREAMING 0x1
|
||||
#define ACCESS_WEB_INTERFACE 0x2
|
||||
#define ACCESS_RECORDER 0x4
|
||||
#define ACCESS_RECORDER_ALL 0x8
|
||||
#define ACCESS_ADMIN 0x10
|
||||
#define ACCESS_FULL 0x3f
|
||||
|
||||
/**
|
||||
* Create a new ticket for the requested resource and generate a id for it
|
||||
*/
|
||||
const char* access_ticket_create(const char *resource, access_t *a);
|
||||
const char* access_ticket_create(const char *resource);
|
||||
|
||||
/**
|
||||
* Verifies that a given ticket id matches a resource
|
||||
*/
|
||||
access_t *access_ticket_verify2(const char *id, const char *resource);
|
||||
int access_ticket_verify(const char *id, const char *resource);
|
||||
|
||||
int access_ticket_delete(const char *ticket_id);
|
||||
|
||||
/**
|
||||
* Free the access structure
|
||||
*/
|
||||
void access_destroy(access_t *a);
|
||||
|
||||
/**
|
||||
* Copy the access structure
|
||||
*/
|
||||
access_t *access_copy(access_t *src);
|
||||
|
||||
/**
|
||||
* Verifies that the given user in combination with the source ip
|
||||
* complies with the requested mask
|
||||
|
@ -163,53 +95,18 @@ access_t *access_copy(access_t *src);
|
|||
int access_verify(const char *username, const char *password,
|
||||
struct sockaddr *src, uint32_t mask);
|
||||
|
||||
static inline int access_verify2(access_t *a, uint32_t mask)
|
||||
{ return (mask & ACCESS_OR) ?
|
||||
((a->aa_rights & mask) ? 0 : -1) :
|
||||
((a->aa_rights & mask) == mask ? 0 : -1); }
|
||||
|
||||
int access_verify_list(htsmsg_t *list, const char *item);
|
||||
|
||||
/**
|
||||
* Get the access structure
|
||||
*
|
||||
*/
|
||||
access_t *access_get(const char *username, const char *password,
|
||||
struct sockaddr *src);
|
||||
uint32_t access_get_hashed(const char *username, const uint8_t digest[20],
|
||||
const uint8_t *challenge, struct sockaddr *src,
|
||||
int *entrymatch);
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
access_t *
|
||||
access_get_hashed(const char *username, const uint8_t digest[20],
|
||||
const uint8_t *challenge, struct sockaddr *src);
|
||||
uint32_t access_get_by_addr(struct sockaddr *src);
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
access_t *
|
||||
access_get_by_addr(struct sockaddr *src);
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
access_entry_t *
|
||||
access_entry_create(const char *uuid, htsmsg_t *conf);
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
void
|
||||
access_entry_save(access_entry_t *ae);
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
void
|
||||
access_destroy_by_profile(struct profile *pro, int delconf);
|
||||
void
|
||||
access_destroy_by_dvr_config(struct dvr_config *cfg, int delconf);
|
||||
void
|
||||
access_destroy_by_channel_tag(struct channel_tag *ct, int delconf);
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -217,4 +114,9 @@ access_destroy_by_channel_tag(struct channel_tag *ct, int delconf);
|
|||
void access_init(int createdefault, int noacl);
|
||||
void access_done(void);
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
uint32_t access_tag_only(const char *username);
|
||||
|
||||
#endif /* ACCESS_H_ */
|
||||
|
|
15
src/api.c
|
@ -61,8 +61,7 @@ api_register_all ( const api_hook_t *hooks )
|
|||
}
|
||||
|
||||
int
|
||||
api_exec ( access_t *perm, const char *subsystem,
|
||||
htsmsg_t *args, htsmsg_t **resp )
|
||||
api_exec ( const char *subsystem, htsmsg_t *args, htsmsg_t **resp )
|
||||
{
|
||||
api_hook_t h;
|
||||
api_link_t *ah, skel;
|
||||
|
@ -84,9 +83,6 @@ api_exec ( access_t *perm, const char *subsystem,
|
|||
return ENOSYS; // TODO: is this really the right error code?
|
||||
}
|
||||
|
||||
if (access_verify2(perm, ah->hook->ah_access))
|
||||
return EPERM;
|
||||
|
||||
/* Extract method */
|
||||
op = htsmsg_get_str(args, "method");
|
||||
if (!op)
|
||||
|
@ -94,12 +90,12 @@ api_exec ( access_t *perm, const char *subsystem,
|
|||
// Note: this is not required (so no final validation)
|
||||
|
||||
/* Execute */
|
||||
return ah->hook->ah_callback(perm, ah->hook->ah_opaque, op, args, resp);
|
||||
return ah->hook->ah_callback(ah->hook->ah_opaque, op, args, resp);
|
||||
}
|
||||
|
||||
static int
|
||||
api_serverinfo
|
||||
( access_t *perm, void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp )
|
||||
( void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp )
|
||||
{
|
||||
*resp = htsmsg_create_map();
|
||||
htsmsg_add_str(*resp, "sw_version", tvheadend_version);
|
||||
|
@ -125,17 +121,12 @@ void api_init ( void )
|
|||
api_mpegts_init();
|
||||
api_service_init();
|
||||
api_channel_init();
|
||||
api_bouquet_init();
|
||||
api_epg_init();
|
||||
api_epggrab_init();
|
||||
api_status_init();
|
||||
api_imagecache_init();
|
||||
api_esfilter_init();
|
||||
api_intlconv_init();
|
||||
api_access_init();
|
||||
api_dvr_init();
|
||||
api_caclient_init();
|
||||
api_profile_init();
|
||||
}
|
||||
|
||||
void api_done ( void )
|
||||
|
|
35
src/api.h
|
@ -23,17 +23,15 @@
|
|||
#include "htsmsg.h"
|
||||
#include "idnode.h"
|
||||
#include "redblack.h"
|
||||
#include "access.h"
|
||||
|
||||
#define TVH_API_VERSION 15
|
||||
#define TVH_API_VERSION 12
|
||||
|
||||
/*
|
||||
* Command hook
|
||||
*/
|
||||
|
||||
typedef int (*api_callback_t)
|
||||
( access_t *perm, void *opaque, const char *op,
|
||||
htsmsg_t *args, htsmsg_t **resp );
|
||||
( void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp );
|
||||
|
||||
typedef struct api_hook
|
||||
{
|
||||
|
@ -52,8 +50,7 @@ void api_register_all ( const api_hook_t *hooks );
|
|||
/*
|
||||
* Execute
|
||||
*/
|
||||
int api_exec ( access_t *perm, const char *subsystem,
|
||||
htsmsg_t *args, htsmsg_t **resp );
|
||||
int api_exec ( const char *subsystem, htsmsg_t *args, htsmsg_t **resp );
|
||||
|
||||
/*
|
||||
* Initialise
|
||||
|
@ -62,9 +59,9 @@ void api_init ( void );
|
|||
void api_done ( void );
|
||||
void api_idnode_init ( void );
|
||||
void api_input_init ( void );
|
||||
void api_input_satip_init ( void );
|
||||
void api_service_init ( void );
|
||||
void api_channel_init ( void );
|
||||
void api_bouquet_init ( void );
|
||||
void api_mpegts_init ( void );
|
||||
void api_epg_init ( void );
|
||||
void api_epggrab_init ( void );
|
||||
|
@ -72,41 +69,35 @@ void api_status_init ( void );
|
|||
void api_imagecache_init ( void );
|
||||
void api_esfilter_init ( void );
|
||||
void api_intlconv_init ( void );
|
||||
void api_access_init ( void );
|
||||
void api_dvr_init ( void );
|
||||
void api_caclient_init ( void );
|
||||
void api_profile_init ( void );
|
||||
|
||||
/*
|
||||
* IDnode
|
||||
*/
|
||||
typedef struct api_idnode_grid_conf
|
||||
{
|
||||
uint32_t start;
|
||||
uint32_t limit;
|
||||
int tindex;
|
||||
int start;
|
||||
int limit;
|
||||
idnode_filter_t filter;
|
||||
idnode_sort_t sort;
|
||||
} api_idnode_grid_conf_t;
|
||||
|
||||
typedef void (*api_idnode_grid_callback_t)
|
||||
(access_t *perm, idnode_set_t*, api_idnode_grid_conf_t*, htsmsg_t *args);
|
||||
(idnode_set_t*, api_idnode_grid_conf_t*, htsmsg_t *args);
|
||||
typedef idnode_set_t *(*api_idnode_tree_callback_t)
|
||||
(access_t *perm);
|
||||
(void);
|
||||
|
||||
int api_idnode_grid
|
||||
( access_t *perm, void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp );
|
||||
( void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp );
|
||||
|
||||
int api_idnode_class
|
||||
( access_t *perm, void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp );
|
||||
( void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp );
|
||||
|
||||
int api_idnode_tree
|
||||
( access_t *perm, void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp );
|
||||
( void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp );
|
||||
|
||||
int api_idnode_load_by_class
|
||||
( access_t *perm, void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp );
|
||||
|
||||
int api_idnode_handler
|
||||
( access_t *perm, htsmsg_t *args, htsmsg_t **resp, void (*handler)(access_t *perm, idnode_t *in) );
|
||||
( void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp );
|
||||
|
||||
/*
|
||||
* Service mapper
|
||||
|
|
|
@ -1,63 +0,0 @@
|
|||
/*
|
||||
* API - access control
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
#include "tvheadend.h"
|
||||
#include "access.h"
|
||||
#include "api.h"
|
||||
|
||||
static void
|
||||
api_access_entry_grid
|
||||
( access_t *perm, idnode_set_t *ins, api_idnode_grid_conf_t *conf, htsmsg_t *args )
|
||||
{
|
||||
access_entry_t *ae;
|
||||
|
||||
TAILQ_FOREACH(ae, &access_entries, ae_link)
|
||||
idnode_set_add(ins, (idnode_t*)ae, &conf->filter);
|
||||
}
|
||||
|
||||
static int
|
||||
api_access_entry_create
|
||||
( access_t *perm, void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp )
|
||||
{
|
||||
htsmsg_t *conf;
|
||||
access_entry_t *ae;
|
||||
|
||||
if (!(conf = htsmsg_get_map(args, "conf")))
|
||||
return EINVAL;
|
||||
|
||||
pthread_mutex_lock(&global_lock);
|
||||
if ((ae = access_entry_create(NULL, conf)) != NULL)
|
||||
access_entry_save(ae);
|
||||
pthread_mutex_unlock(&global_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void api_access_init ( void )
|
||||
{
|
||||
static api_hook_t ah[] = {
|
||||
{ "access/entry/class", ACCESS_ADMIN, api_idnode_class, (void*)&access_entry_class },
|
||||
{ "access/entry/grid", ACCESS_ADMIN, api_idnode_grid, api_access_entry_grid },
|
||||
{ "access/entry/create", ACCESS_ADMIN, api_access_entry_create, NULL },
|
||||
|
||||
{ NULL },
|
||||
};
|
||||
|
||||
api_register_all(ah);
|
||||
}
|
|
@ -1,93 +0,0 @@
|
|||
/*
|
||||
* API - bouquet calls
|
||||
*
|
||||
* 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_API_BOUQUET_H__
|
||||
#define __TVH_API_BOUQUET_H__
|
||||
|
||||
#include "tvheadend.h"
|
||||
#include "bouquet.h"
|
||||
#include "access.h"
|
||||
#include "api.h"
|
||||
|
||||
static int
|
||||
api_bouquet_list
|
||||
( access_t *perm, void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp )
|
||||
{
|
||||
bouquet_t *bq;
|
||||
htsmsg_t *l, *e;
|
||||
|
||||
l = htsmsg_create_list();
|
||||
pthread_mutex_lock(&global_lock);
|
||||
RB_FOREACH(bq, &bouquets, bq_link) {
|
||||
e = htsmsg_create_map();
|
||||
htsmsg_add_str(e, "key", idnode_uuid_as_str(&bq->bq_id));
|
||||
htsmsg_add_str(e, "val", bq->bq_name ?: "");
|
||||
htsmsg_add_msg(l, NULL, e);
|
||||
}
|
||||
pthread_mutex_unlock(&global_lock);
|
||||
*resp = htsmsg_create_map();
|
||||
htsmsg_add_msg(*resp, "entries", l);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
api_bouquet_grid
|
||||
( access_t *perm, idnode_set_t *ins, api_idnode_grid_conf_t *conf )
|
||||
{
|
||||
bouquet_t *bq;
|
||||
|
||||
RB_FOREACH(bq, &bouquets, bq_link)
|
||||
idnode_set_add(ins, (idnode_t*)bq, &conf->filter);
|
||||
}
|
||||
|
||||
static int
|
||||
api_bouquet_create
|
||||
( access_t *perm, void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp )
|
||||
{
|
||||
htsmsg_t *conf;
|
||||
bouquet_t *bq;
|
||||
|
||||
if (!(conf = htsmsg_get_map(args, "conf")))
|
||||
return EINVAL;
|
||||
|
||||
pthread_mutex_lock(&global_lock);
|
||||
bq = bouquet_create(NULL, conf, NULL, NULL);
|
||||
if (bq)
|
||||
bouquet_save(bq, 0);
|
||||
pthread_mutex_unlock(&global_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void api_bouquet_init ( void )
|
||||
{
|
||||
static api_hook_t ah[] = {
|
||||
{ "bouquet/list", ACCESS_ADMIN, api_bouquet_list, NULL },
|
||||
{ "bouquet/class", ACCESS_ADMIN, api_idnode_class, (void*)&bouquet_class },
|
||||
{ "bouquet/grid", ACCESS_ADMIN, api_idnode_grid, api_bouquet_grid },
|
||||
{ "bouquet/create", ACCESS_ADMIN, api_bouquet_create, NULL },
|
||||
|
||||
{ NULL },
|
||||
};
|
||||
|
||||
api_register_all(ah);
|
||||
}
|
||||
|
||||
#endif /* __TVH_API_BOUQUET_H__ */
|
|
@ -1,108 +0,0 @@
|
|||
/*
|
||||
* tvheadend - API access to Conditional Access Clients
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
#include "tvheadend.h"
|
||||
#include "access.h"
|
||||
#include "htsmsg.h"
|
||||
#include "api.h"
|
||||
#include "descrambler/caclient.h"
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
static int
|
||||
api_caclient_list
|
||||
( access_t *perm, void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp )
|
||||
{
|
||||
caclient_t *cac;
|
||||
htsmsg_t *l, *e;
|
||||
|
||||
l = htsmsg_create_list();
|
||||
pthread_mutex_lock(&global_lock);
|
||||
TAILQ_FOREACH(cac, &caclients, cac_link) {
|
||||
e = htsmsg_create_map();
|
||||
htsmsg_add_str(e, "uuid", idnode_uuid_as_str(&cac->cac_id));
|
||||
htsmsg_add_str(e, "title", idnode_get_title(&cac->cac_id));
|
||||
htsmsg_add_str(e, "status", caclient_get_status(cac));
|
||||
htsmsg_add_msg(l, NULL, e);
|
||||
}
|
||||
pthread_mutex_unlock(&global_lock);
|
||||
*resp = htsmsg_create_map();
|
||||
htsmsg_add_msg(*resp, "entries", l);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
api_caclient_builders
|
||||
( access_t *perm, void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp )
|
||||
{
|
||||
const idclass_t **r;
|
||||
htsmsg_t *l, *e;
|
||||
|
||||
/* List of available builder classes */
|
||||
l = htsmsg_create_list();
|
||||
for (r = caclient_classes; *r; r++)
|
||||
if ((e = idclass_serialize(*r)))
|
||||
htsmsg_add_msg(l, NULL, e);
|
||||
|
||||
/* Output */
|
||||
*resp = htsmsg_create_map();
|
||||
htsmsg_add_msg(*resp, "entries", l);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
api_caclient_create
|
||||
( access_t *perm, void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp )
|
||||
{
|
||||
int err = 0;
|
||||
const char *clazz;
|
||||
htsmsg_t *conf;
|
||||
|
||||
if (!(clazz = htsmsg_get_str(args, "class")))
|
||||
return EINVAL;
|
||||
if (!(conf = htsmsg_get_map(args, "conf")))
|
||||
return EINVAL;
|
||||
htsmsg_set_str(conf, "class", clazz);
|
||||
|
||||
pthread_mutex_lock(&global_lock);
|
||||
if (caclient_create(NULL, conf, 1) == NULL)
|
||||
err = -EINVAL;
|
||||
pthread_mutex_unlock(&global_lock);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/*
|
||||
* Init
|
||||
*/
|
||||
void
|
||||
api_caclient_init ( void )
|
||||
{
|
||||
static api_hook_t ah[] = {
|
||||
{ "caclient/list", ACCESS_ADMIN, api_caclient_list, NULL },
|
||||
{ "caclient/class", ACCESS_ADMIN, api_idnode_class, (void*)&caclient_class },
|
||||
{ "caclient/builders", ACCESS_ADMIN, api_caclient_builders, NULL },
|
||||
{ "caclient/create", ACCESS_ADMIN, api_caclient_create, NULL },
|
||||
{ NULL },
|
||||
};
|
||||
|
||||
api_register_all(ah);
|
||||
}
|
|
@ -17,50 +17,29 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __TVH_API_CHANNEL_H__
|
||||
#define __TVH_API_CHANNEL_H__
|
||||
#ifndef __TVH_API_SERVICE_H__
|
||||
#define __TVH_API_SERVICE_H__
|
||||
|
||||
#include "tvheadend.h"
|
||||
#include "channels.h"
|
||||
#include "access.h"
|
||||
#include "api.h"
|
||||
|
||||
static void
|
||||
api_channel_key_val(htsmsg_t *dst, const char *key, const char *val)
|
||||
{
|
||||
htsmsg_t *e = htsmsg_create_map();
|
||||
htsmsg_add_str(e, "key", key);
|
||||
htsmsg_add_str(e, "val", val ?: "");
|
||||
htsmsg_add_msg(dst, NULL, e);
|
||||
}
|
||||
|
||||
static int
|
||||
api_channel_is_all(access_t *perm, htsmsg_t *args)
|
||||
{
|
||||
return htsmsg_get_bool_or_default(args, "all", 0) &&
|
||||
!access_verify2(perm, ACCESS_ADMIN);
|
||||
}
|
||||
|
||||
// TODO: this will need converting to an idnode system
|
||||
static int
|
||||
api_channel_list
|
||||
( access_t *perm, void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp )
|
||||
( void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp )
|
||||
{
|
||||
channel_t *ch;
|
||||
htsmsg_t *l;
|
||||
int cfg = api_channel_is_all(perm, args);
|
||||
char buf[128];
|
||||
htsmsg_t *l, *e;
|
||||
|
||||
l = htsmsg_create_list();
|
||||
pthread_mutex_lock(&global_lock);
|
||||
CHANNEL_FOREACH(ch) {
|
||||
if (!cfg && !channel_access(ch, perm, 0)) continue;
|
||||
if (!ch->ch_enabled) {
|
||||
snprintf(buf, sizeof(buf), "{%s}", channel_get_name(ch));
|
||||
api_channel_key_val(l, idnode_uuid_as_str(&ch->ch_id), buf);
|
||||
} else {
|
||||
api_channel_key_val(l, idnode_uuid_as_str(&ch->ch_id), channel_get_name(ch));
|
||||
}
|
||||
e = htsmsg_create_map();
|
||||
htsmsg_add_str(e, "key", idnode_uuid_as_str(&ch->ch_id));
|
||||
htsmsg_add_str(e, "val", channel_get_name(ch));
|
||||
htsmsg_add_msg(l, NULL, e);
|
||||
}
|
||||
pthread_mutex_unlock(&global_lock);
|
||||
*resp = htsmsg_create_map();
|
||||
|
@ -71,19 +50,17 @@ api_channel_list
|
|||
|
||||
static void
|
||||
api_channel_grid
|
||||
( access_t *perm, idnode_set_t *ins, api_idnode_grid_conf_t *conf, htsmsg_t *args )
|
||||
( idnode_set_t *ins, api_idnode_grid_conf_t *conf )
|
||||
{
|
||||
channel_t *ch;
|
||||
int cfg = api_channel_is_all(perm, args);
|
||||
|
||||
CHANNEL_FOREACH(ch)
|
||||
if (cfg || channel_access(ch, perm, 0))
|
||||
idnode_set_add(ins, (idnode_t*)ch, &conf->filter);
|
||||
idnode_set_add(ins, (idnode_t*)ch, &conf->filter);
|
||||
}
|
||||
|
||||
static int
|
||||
api_channel_create
|
||||
( access_t *perm, void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp )
|
||||
( void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp )
|
||||
{
|
||||
htsmsg_t *conf;
|
||||
channel_t *ch;
|
||||
|
@ -101,57 +78,27 @@ api_channel_create
|
|||
}
|
||||
|
||||
static int
|
||||
api_channel_tag_list
|
||||
( access_t *perm, void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp )
|
||||
api_channeltag_enum
|
||||
( void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp )
|
||||
{
|
||||
channel_tag_t *ct;
|
||||
htsmsg_t *l;
|
||||
int cfg = api_channel_is_all(perm, args);
|
||||
char buf[128];
|
||||
htsmsg_t *l, *e;
|
||||
|
||||
int _enum = htsmsg_get_bool_or_default(args, "enum", 0);
|
||||
|
||||
l = htsmsg_create_list();
|
||||
TAILQ_FOREACH(ct, &channel_tags, ct_link)
|
||||
if (cfg || channel_tag_access(ct, perm, 0)) {
|
||||
if (ct->ct_enabled) {
|
||||
api_channel_key_val(l, idnode_uuid_as_str(&ct->ct_id), ct->ct_name);
|
||||
} else {
|
||||
snprintf(buf, sizeof(buf), "{%s}", ct->ct_name);
|
||||
api_channel_key_val(l, idnode_uuid_as_str(&ct->ct_id), buf);
|
||||
}
|
||||
if (_enum) {
|
||||
l = htsmsg_create_list();
|
||||
TAILQ_FOREACH(ct, &channel_tags, ct_link) {
|
||||
e = htsmsg_create_map();
|
||||
htsmsg_add_u32(e, "key", ct->ct_identifier);
|
||||
htsmsg_add_str(e, "val", ct->ct_name);
|
||||
htsmsg_add_msg(l, NULL, e);
|
||||
}
|
||||
*resp = htsmsg_create_map();
|
||||
htsmsg_add_msg(*resp, "entries", l);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
api_channel_tag_grid
|
||||
( access_t *perm, idnode_set_t *ins, api_idnode_grid_conf_t *conf, htsmsg_t *args )
|
||||
{
|
||||
channel_tag_t *ct;
|
||||
int cfg = api_channel_is_all(perm, args);
|
||||
|
||||
TAILQ_FOREACH(ct, &channel_tags, ct_link)
|
||||
if (cfg || channel_tag_access(ct, perm, 0))
|
||||
idnode_set_add(ins, (idnode_t*)ct, &conf->filter);
|
||||
}
|
||||
|
||||
static int
|
||||
api_channel_tag_create
|
||||
( access_t *perm, void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp )
|
||||
{
|
||||
htsmsg_t *conf;
|
||||
channel_tag_t *ct;
|
||||
|
||||
if (!(conf = htsmsg_get_map(args, "conf")))
|
||||
return EINVAL;
|
||||
|
||||
pthread_mutex_lock(&global_lock);
|
||||
ct = channel_tag_create(NULL, conf);
|
||||
if (ct)
|
||||
channel_tag_save(ct);
|
||||
pthread_mutex_unlock(&global_lock);
|
||||
|
||||
*resp = htsmsg_create_map();
|
||||
htsmsg_add_msg(*resp, "entries", l);
|
||||
} else {
|
||||
// TODO: support full listing v enum
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -163,10 +110,7 @@ void api_channel_init ( void )
|
|||
{ "channel/list", ACCESS_ANONYMOUS, api_channel_list, NULL },
|
||||
{ "channel/create", ACCESS_ADMIN, api_channel_create, NULL },
|
||||
|
||||
{ "channeltag/class",ACCESS_ANONYMOUS, api_idnode_class, (void*)&channel_tag_class },
|
||||
{ "channeltag/grid", ACCESS_ANONYMOUS, api_idnode_grid, api_channel_tag_grid },
|
||||
{ "channeltag/list", ACCESS_ANONYMOUS, api_channel_tag_list, NULL },
|
||||
{ "channeltag/create", ACCESS_ADMIN, api_channel_tag_create, NULL },
|
||||
{ "channeltag/list", ACCESS_ANONYMOUS, api_channeltag_enum, NULL },
|
||||
|
||||
{ NULL },
|
||||
};
|
||||
|
@ -175,4 +119,4 @@ void api_channel_init ( void )
|
|||
}
|
||||
|
||||
|
||||
#endif /* __TVH_API_CHANNEL_H__ */
|
||||
#endif /* __TVH_API_IDNODE_H__ */
|
||||
|
|
|
@ -1,394 +0,0 @@
|
|||
/*
|
||||
* API - DVR
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
#include "tvheadend.h"
|
||||
#include "dvr/dvr.h"
|
||||
#include "epg.h"
|
||||
#include "api.h"
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
|
||||
static void
|
||||
api_dvr_config_grid
|
||||
( access_t *perm, idnode_set_t *ins, api_idnode_grid_conf_t *conf, htsmsg_t *args )
|
||||
{
|
||||
dvr_config_t *cfg;
|
||||
|
||||
LIST_FOREACH(cfg, &dvrconfigs, config_link)
|
||||
if (!idnode_perm((idnode_t *)cfg, perm, NULL))
|
||||
idnode_set_add(ins, (idnode_t*)cfg, &conf->filter);
|
||||
}
|
||||
|
||||
static int
|
||||
api_dvr_config_create
|
||||
( access_t *perm, void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp )
|
||||
{
|
||||
dvr_config_t *cfg;
|
||||
htsmsg_t *conf;
|
||||
const char *s;
|
||||
|
||||
if (!(conf = htsmsg_get_map(args, "conf")))
|
||||
return EINVAL;
|
||||
if (!(s = htsmsg_get_str(conf, "name")))
|
||||
return EINVAL;
|
||||
if (s[0] == '\0')
|
||||
return EINVAL;
|
||||
|
||||
pthread_mutex_lock(&global_lock);
|
||||
if ((cfg = dvr_config_create(NULL, NULL, conf)))
|
||||
dvr_config_save(cfg);
|
||||
pthread_mutex_unlock(&global_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int is_dvr_entry_finished(dvr_entry_t *entry)
|
||||
{
|
||||
dvr_entry_sched_state_t state = entry->de_sched_state;
|
||||
return state == DVR_COMPLETED && !entry->de_last_error && dvr_get_filesize(entry) != -1;
|
||||
}
|
||||
|
||||
static int is_dvr_entry_upcoming(dvr_entry_t *entry)
|
||||
{
|
||||
dvr_entry_sched_state_t state = entry->de_sched_state;
|
||||
return state == DVR_RECORDING || state == DVR_SCHEDULED || state == DVR_NOSTATE;
|
||||
}
|
||||
|
||||
static int is_dvr_entry_failed(dvr_entry_t *entry)
|
||||
{
|
||||
if (is_dvr_entry_finished(entry))
|
||||
return 0;
|
||||
if (is_dvr_entry_upcoming(entry))
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void
|
||||
api_dvr_entry_grid
|
||||
( access_t *perm, idnode_set_t *ins, api_idnode_grid_conf_t *conf, htsmsg_t *args )
|
||||
{
|
||||
dvr_entry_t *de;
|
||||
|
||||
LIST_FOREACH(de, &dvrentries, de_global_link)
|
||||
idnode_set_add(ins, (idnode_t*)de, &conf->filter);
|
||||
}
|
||||
|
||||
static void
|
||||
api_dvr_entry_grid_upcoming
|
||||
( access_t *perm, idnode_set_t *ins, api_idnode_grid_conf_t *conf, htsmsg_t *args )
|
||||
{
|
||||
dvr_entry_t *de;
|
||||
|
||||
LIST_FOREACH(de, &dvrentries, de_global_link)
|
||||
if (is_dvr_entry_upcoming(de))
|
||||
idnode_set_add(ins, (idnode_t*)de, &conf->filter);
|
||||
}
|
||||
|
||||
static void
|
||||
api_dvr_entry_grid_finished
|
||||
( access_t *perm, idnode_set_t *ins, api_idnode_grid_conf_t *conf, htsmsg_t *args )
|
||||
{
|
||||
dvr_entry_t *de;
|
||||
|
||||
LIST_FOREACH(de, &dvrentries, de_global_link)
|
||||
if (is_dvr_entry_finished(de))
|
||||
idnode_set_add(ins, (idnode_t*)de, &conf->filter);
|
||||
}
|
||||
|
||||
static void
|
||||
api_dvr_entry_grid_failed
|
||||
( access_t *perm, idnode_set_t *ins, api_idnode_grid_conf_t *conf, htsmsg_t *args )
|
||||
{
|
||||
dvr_entry_t *de;
|
||||
|
||||
LIST_FOREACH(de, &dvrentries, de_global_link)
|
||||
if (is_dvr_entry_failed(de))
|
||||
idnode_set_add(ins, (idnode_t*)de, &conf->filter);
|
||||
}
|
||||
|
||||
static int
|
||||
api_dvr_entry_create
|
||||
( access_t *perm, void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp )
|
||||
{
|
||||
dvr_entry_t *de;
|
||||
dvr_config_t *cfg;
|
||||
htsmsg_t *conf;
|
||||
const char *s1;
|
||||
int res = EPERM;
|
||||
|
||||
if (!(conf = htsmsg_get_map(args, "conf")))
|
||||
return EINVAL;
|
||||
|
||||
pthread_mutex_lock(&global_lock);
|
||||
s1 = htsmsg_get_str(conf, "config_name");
|
||||
cfg = dvr_config_find_by_list(perm->aa_dvrcfgs, s1);
|
||||
if (cfg) {
|
||||
htsmsg_set_str(conf, "config_name", idnode_uuid_as_str(&cfg->dvr_id));
|
||||
|
||||
if (perm->aa_representative)
|
||||
htsmsg_set_str(conf, "creator", perm->aa_representative);
|
||||
|
||||
if ((de = dvr_entry_create(NULL, conf)))
|
||||
dvr_entry_save(de);
|
||||
|
||||
res = 0;
|
||||
}
|
||||
pthread_mutex_unlock(&global_lock);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static htsmsg_t *
|
||||
api_dvr_entry_create_from_single(htsmsg_t *args)
|
||||
{
|
||||
htsmsg_t *entries, *m;
|
||||
const char *s1, *s2, *s3;
|
||||
|
||||
if (!(s1 = htsmsg_get_str(args, "config_uuid")))
|
||||
return NULL;
|
||||
if (!(s2 = htsmsg_get_str(args, "event_id")))
|
||||
return NULL;
|
||||
s3 = htsmsg_get_str(args, "comment");
|
||||
entries = htsmsg_create_list();
|
||||
m = htsmsg_create_map();
|
||||
htsmsg_add_str(m, "config_uuid", s1);
|
||||
htsmsg_add_str(m, "event_id", s2);
|
||||
if (s3)
|
||||
htsmsg_add_str(m, "comment", s3);
|
||||
htsmsg_add_msg(entries, NULL, m);
|
||||
return entries;
|
||||
}
|
||||
|
||||
static int
|
||||
api_dvr_entry_create_by_event
|
||||
( access_t *perm, void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp )
|
||||
{
|
||||
dvr_entry_t *de;
|
||||
const char *config_uuid, *comment;
|
||||
epg_broadcast_t *e;
|
||||
htsmsg_t *entries, *entries2 = NULL, *m;
|
||||
htsmsg_field_t *f;
|
||||
const char *s;
|
||||
int count = 0;
|
||||
|
||||
if (!(entries = htsmsg_get_list(args, "entries"))) {
|
||||
entries = entries2 = api_dvr_entry_create_from_single(args);
|
||||
if (!entries)
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
HTSMSG_FOREACH(f, entries) {
|
||||
if (!(m = htsmsg_get_map_by_field(f))) continue;
|
||||
|
||||
if (!(s = htsmsg_get_str(m, "event_id")))
|
||||
continue;
|
||||
|
||||
config_uuid = htsmsg_get_str(m, "config_uuid");
|
||||
comment = htsmsg_get_str(m, "comment");
|
||||
|
||||
pthread_mutex_lock(&global_lock);
|
||||
if ((e = epg_broadcast_find_by_id(strtoll(s, NULL, 10)))) {
|
||||
dvr_config_t *cfg = dvr_config_find_by_list(perm->aa_dvrcfgs, config_uuid);
|
||||
if (cfg) {
|
||||
de = dvr_entry_create_by_event(idnode_uuid_as_str(&cfg->dvr_id),
|
||||
e, 0, 0,
|
||||
perm->aa_username,
|
||||
perm->aa_representative,
|
||||
NULL, DVR_PRIO_NORMAL, 0, comment);
|
||||
if (de)
|
||||
dvr_entry_save(de);
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(&global_lock);
|
||||
count++;
|
||||
}
|
||||
|
||||
htsmsg_destroy(entries2);
|
||||
|
||||
return !count ? EINVAL : 0;
|
||||
}
|
||||
|
||||
static void
|
||||
api_dvr_cancel(access_t *perm, idnode_t *self)
|
||||
{
|
||||
dvr_entry_cancel((dvr_entry_t *)self);
|
||||
}
|
||||
|
||||
static int
|
||||
api_dvr_entry_cancel
|
||||
( access_t *perm, void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp )
|
||||
{
|
||||
return api_idnode_handler(perm, args, resp, api_dvr_cancel);
|
||||
}
|
||||
|
||||
static void
|
||||
api_dvr_autorec_grid
|
||||
( access_t *perm, idnode_set_t *ins, api_idnode_grid_conf_t *conf, htsmsg_t *args )
|
||||
{
|
||||
dvr_autorec_entry_t *dae;
|
||||
|
||||
TAILQ_FOREACH(dae, &autorec_entries, dae_link)
|
||||
idnode_set_add(ins, (idnode_t*)dae, &conf->filter);
|
||||
}
|
||||
|
||||
static int
|
||||
api_dvr_autorec_create
|
||||
( access_t *perm, void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp )
|
||||
{
|
||||
htsmsg_t *conf;
|
||||
dvr_autorec_entry_t *dae;
|
||||
|
||||
if (!(conf = htsmsg_get_map(args, "conf")))
|
||||
return EINVAL;
|
||||
|
||||
if (perm->aa_username)
|
||||
htsmsg_set_str(conf, "owner", perm->aa_username);
|
||||
if (perm->aa_representative)
|
||||
htsmsg_set_str(conf, "creator", perm->aa_representative);
|
||||
|
||||
pthread_mutex_lock(&global_lock);
|
||||
dae = dvr_autorec_create(NULL, conf);
|
||||
if (dae) {
|
||||
dvr_autorec_save(dae);
|
||||
dvr_autorec_changed(dae, 1);
|
||||
}
|
||||
pthread_mutex_unlock(&global_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
api_dvr_autorec_create_by_series
|
||||
( access_t *perm, void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp )
|
||||
{
|
||||
dvr_autorec_entry_t *dae;
|
||||
epg_broadcast_t *e;
|
||||
htsmsg_t *entries, *entries2 = NULL, *m;
|
||||
htsmsg_field_t *f;
|
||||
const char *config_uuid, *s;
|
||||
int count = 0;
|
||||
|
||||
if (!(entries = htsmsg_get_list(args, "entries"))) {
|
||||
entries = entries2 = api_dvr_entry_create_from_single(args);
|
||||
if (!entries)
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
HTSMSG_FOREACH(f, entries) {
|
||||
if (!(m = htsmsg_get_map_by_field(f))) continue;
|
||||
|
||||
if (!(s = htsmsg_get_str(m, "event_id")))
|
||||
continue;
|
||||
|
||||
config_uuid = htsmsg_get_str(m, "config_uuid");
|
||||
|
||||
pthread_mutex_lock(&global_lock);
|
||||
if ((e = epg_broadcast_find_by_id(strtoll(s, NULL, 10)))) {
|
||||
dvr_config_t *cfg = dvr_config_find_by_list(perm->aa_dvrcfgs, config_uuid);
|
||||
if (cfg) {
|
||||
dae = dvr_autorec_add_series_link(idnode_uuid_as_str(&cfg->dvr_id),
|
||||
e,
|
||||
perm->aa_username,
|
||||
perm->aa_representative,
|
||||
"Created from EPG query");
|
||||
if (dae) {
|
||||
dvr_autorec_save(dae);
|
||||
dvr_autorec_changed(dae, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(&global_lock);
|
||||
count++;
|
||||
}
|
||||
|
||||
htsmsg_destroy(entries2);
|
||||
|
||||
return !count ? EINVAL : 0;
|
||||
}
|
||||
|
||||
static void
|
||||
api_dvr_timerec_grid
|
||||
( access_t *perm, idnode_set_t *ins, api_idnode_grid_conf_t *conf, htsmsg_t *args )
|
||||
{
|
||||
dvr_timerec_entry_t *dte;
|
||||
|
||||
TAILQ_FOREACH(dte, &timerec_entries, dte_link)
|
||||
idnode_set_add(ins, (idnode_t*)dte, &conf->filter);
|
||||
}
|
||||
|
||||
static int
|
||||
api_dvr_timerec_create
|
||||
( access_t *perm, void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp )
|
||||
{
|
||||
htsmsg_t *conf;
|
||||
dvr_timerec_entry_t *dte;
|
||||
|
||||
if (!(conf = htsmsg_get_map(args, "conf")))
|
||||
return EINVAL;
|
||||
|
||||
if (perm->aa_username)
|
||||
htsmsg_set_str(conf, "owner", perm->aa_username);
|
||||
if (perm->aa_representative)
|
||||
htsmsg_set_str(conf, "creator", perm->aa_representative);
|
||||
|
||||
pthread_mutex_lock(&global_lock);
|
||||
dte = dvr_timerec_create(NULL, conf);
|
||||
if (dte) {
|
||||
dvr_timerec_save(dte);
|
||||
dvr_timerec_check(dte);
|
||||
}
|
||||
pthread_mutex_unlock(&global_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void api_dvr_init ( void )
|
||||
{
|
||||
static api_hook_t ah[] = {
|
||||
{ "dvr/config/class", ACCESS_OR|ACCESS_ADMIN|ACCESS_RECORDER,
|
||||
api_idnode_class, (void*)&dvr_config_class },
|
||||
{ "dvr/config/grid", ACCESS_OR|ACCESS_ADMIN|ACCESS_RECORDER,
|
||||
api_idnode_grid, api_dvr_config_grid },
|
||||
{ "dvr/config/create", ACCESS_ADMIN, api_dvr_config_create, NULL },
|
||||
|
||||
{ "dvr/entry/class", ACCESS_RECORDER, api_idnode_class, (void*)&dvr_entry_class },
|
||||
{ "dvr/entry/grid", ACCESS_RECORDER, api_idnode_grid, api_dvr_entry_grid },
|
||||
{ "dvr/entry/grid_upcoming", ACCESS_RECORDER, api_idnode_grid, api_dvr_entry_grid_upcoming },
|
||||
{ "dvr/entry/grid_finished", ACCESS_RECORDER, api_idnode_grid, api_dvr_entry_grid_finished },
|
||||
{ "dvr/entry/grid_failed", ACCESS_RECORDER, api_idnode_grid, api_dvr_entry_grid_failed },
|
||||
{ "dvr/entry/create", ACCESS_RECORDER, api_dvr_entry_create, NULL },
|
||||
{ "dvr/entry/create_by_event", ACCESS_RECORDER, api_dvr_entry_create_by_event, NULL },
|
||||
{ "dvr/entry/cancel", ACCESS_RECORDER, api_dvr_entry_cancel, NULL },
|
||||
|
||||
{ "dvr/autorec/class", ACCESS_RECORDER, api_idnode_class, (void*)&dvr_autorec_entry_class },
|
||||
{ "dvr/autorec/grid", ACCESS_RECORDER, api_idnode_grid, api_dvr_autorec_grid },
|
||||
{ "dvr/autorec/create", ACCESS_RECORDER, api_dvr_autorec_create, NULL },
|
||||
{ "dvr/autorec/create_by_series", ACCESS_RECORDER, api_dvr_autorec_create_by_series, NULL },
|
||||
|
||||
{ "dvr/timerec/class", ACCESS_RECORDER, api_idnode_class, (void*)&dvr_timerec_entry_class },
|
||||
{ "dvr/timerec/grid", ACCESS_RECORDER, api_idnode_grid, api_dvr_timerec_grid },
|
||||
{ "dvr/timerec/create", ACCESS_RECORDER, api_dvr_timerec_create, NULL },
|
||||
|
||||
{ NULL },
|
||||
};
|
||||
|
||||
api_register_all(ah);
|
||||
}
|
|
@ -22,63 +22,17 @@
|
|||
#include "access.h"
|
||||
#include "api.h"
|
||||
#include "epg.h"
|
||||
#include "imagecache.h"
|
||||
#include "dvr/dvr.h"
|
||||
|
||||
static htsmsg_t *
|
||||
api_epg_get_list ( const char *s )
|
||||
{
|
||||
htsmsg_t *m = NULL;
|
||||
char *r, *saveptr = NULL;
|
||||
if (s && s[0] != '\0') {
|
||||
s = r = strdup(s);
|
||||
r = strtok_r(r, ";", &saveptr);
|
||||
while (r) {
|
||||
while (*r != '\0' && *r <= ' ')
|
||||
r++;
|
||||
if (*r != '\0') {
|
||||
if (m == NULL)
|
||||
m = htsmsg_create_list();
|
||||
htsmsg_add_str(m, NULL, r);
|
||||
}
|
||||
r = strtok_r(NULL, ";", &saveptr);
|
||||
}
|
||||
free((char *)s);
|
||||
}
|
||||
return m;
|
||||
}
|
||||
|
||||
static void
|
||||
api_epg_add_channel ( htsmsg_t *m, channel_t *ch )
|
||||
{
|
||||
int64_t chnum;
|
||||
char buf[32];
|
||||
const char *s;
|
||||
htsmsg_add_str(m, "channelName", channel_get_name(ch));
|
||||
htsmsg_add_str(m, "channelUuid", channel_get_uuid(ch));
|
||||
if ((chnum = channel_get_number(ch)) >= 0) {
|
||||
uint32_t maj = chnum / CHANNEL_SPLIT;
|
||||
uint32_t min = chnum % CHANNEL_SPLIT;
|
||||
if (min)
|
||||
snprintf(buf, sizeof(buf), "%u.%u", maj, min);
|
||||
else
|
||||
snprintf(buf, sizeof(buf), "%u", maj);
|
||||
htsmsg_add_str(m, "channelNumber", buf);
|
||||
}
|
||||
if ((s = channel_get_icon(ch)) != NULL)
|
||||
htsmsg_add_str(m, "channelIcon", s);
|
||||
}
|
||||
|
||||
static htsmsg_t *
|
||||
api_epg_entry ( epg_broadcast_t *eb, const char *lang, access_t *perm )
|
||||
api_epg_entry ( epg_broadcast_t *eb, const char *lang )
|
||||
{
|
||||
const char *s;
|
||||
char buf[64];
|
||||
epg_episode_t *ee = eb->episode;
|
||||
channel_t *ch = eb->channel;
|
||||
htsmsg_t *m, *m2;
|
||||
htsmsg_t *m;
|
||||
epg_episode_num_t epnum;
|
||||
epg_genre_t *eg;
|
||||
dvr_entry_t *de;
|
||||
|
||||
if (!ee || !ch) return NULL;
|
||||
|
@ -86,6 +40,8 @@ api_epg_entry ( epg_broadcast_t *eb, const char *lang, access_t *perm )
|
|||
m = htsmsg_create_map();
|
||||
|
||||
/* EPG IDs */
|
||||
// Note: "id" is for UI compat, remove it?
|
||||
htsmsg_add_u32(m, "id", eb->id);
|
||||
htsmsg_add_u32(m, "eventId", eb->id);
|
||||
if (ee) {
|
||||
htsmsg_add_u32(m, "episodeId", ee->id);
|
||||
|
@ -99,17 +55,25 @@ api_epg_entry ( epg_broadcast_t *eb, const char *lang, access_t *perm )
|
|||
}
|
||||
|
||||
/* Channel Info */
|
||||
api_epg_add_channel(m, ch);
|
||||
// Note: "channel" is for UI compat, remove it?
|
||||
htsmsg_add_str(m, "channel", channel_get_name(ch));
|
||||
htsmsg_add_str(m, "channelName", channel_get_name(ch));
|
||||
htsmsg_add_str(m, "channelUuid", channel_get_uuid(ch));
|
||||
htsmsg_add_u32(m, "channelId", channel_get_id(ch));
|
||||
|
||||
/* Time */
|
||||
htsmsg_add_s64(m, "start", eb->start);
|
||||
htsmsg_add_s64(m, "stop", eb->stop);
|
||||
htsmsg_add_s64(m, "duration", eb->stop - eb->start);
|
||||
// TODO: the above can be removed
|
||||
|
||||
/* Title/description */
|
||||
if ((s = epg_broadcast_get_title(eb, lang)))
|
||||
htsmsg_add_str(m, "title", s);
|
||||
#if TODO
|
||||
if ((s = epg_broadcast_get_subtitle(eb, lang)))
|
||||
htsmsg_add_str(m, "subtitle", s);
|
||||
#endif
|
||||
if ((s = epg_broadcast_get_summary(eb, lang)))
|
||||
htsmsg_add_str(m, "summary", s);
|
||||
if ((s = epg_broadcast_get_description(eb, lang)))
|
||||
|
@ -144,32 +108,11 @@ api_epg_entry ( epg_broadcast_t *eb, const char *lang, access_t *perm )
|
|||
/* Image */
|
||||
if (ee->image)
|
||||
htsmsg_add_str(m, "image", ee->image);
|
||||
|
||||
/* Rating */
|
||||
if (ee->star_rating)
|
||||
htsmsg_add_u32(m, "starRating", ee->star_rating);
|
||||
if (ee->age_rating)
|
||||
htsmsg_add_u32(m, "ageRating", ee->age_rating);
|
||||
|
||||
/* Content Type */
|
||||
m2 = NULL;
|
||||
LIST_FOREACH(eg, &ee->genre, link) {
|
||||
if (m2 == NULL)
|
||||
m2 = htsmsg_create_list();
|
||||
htsmsg_add_u32(m2, NULL, eg->code);
|
||||
}
|
||||
if (m2)
|
||||
htsmsg_add_msg(m, "genre", m2);
|
||||
}
|
||||
|
||||
|
||||
/* Recording */
|
||||
if (!access_verify2(perm, ACCESS_RECORDER) &&
|
||||
(de = dvr_entry_find_by_event(eb)) &&
|
||||
!access_verify_list(perm->aa_dvrcfgs,
|
||||
idnode_uuid_as_str(&de->de_config->dvr_id))) {
|
||||
htsmsg_add_str(m, "dvrUuid", idnode_uuid_as_str(&de->de_id));
|
||||
htsmsg_add_str(m, "dvrState", dvr_entry_schedstatus(de));
|
||||
}
|
||||
if ((de = dvr_entry_find_by_event(eb)))
|
||||
htsmsg_add_u32(m, "dvrId", de->de_id);
|
||||
|
||||
/* Next event */
|
||||
if ((eb = epg_broadcast_get_next(eb)))
|
||||
|
@ -178,244 +121,30 @@ api_epg_entry ( epg_broadcast_t *eb, const char *lang, access_t *perm )
|
|||
return m;
|
||||
}
|
||||
|
||||
static void
|
||||
api_epg_filter_set_str
|
||||
( epg_filter_str_t *f, const char *str, int comp )
|
||||
{
|
||||
f->str = strdup(str);
|
||||
f->comp = comp;
|
||||
}
|
||||
|
||||
static void
|
||||
api_epg_filter_add_str
|
||||
( epg_query_t *eq, const char *k, const char *v, int comp )
|
||||
{
|
||||
if (!strcmp(k, "channelName"))
|
||||
api_epg_filter_set_str(&eq->channel_name, v, comp);
|
||||
else if (!strcmp(k, "title"))
|
||||
api_epg_filter_set_str(&eq->title, v, comp);
|
||||
else if (!strcmp(k, "subtitle"))
|
||||
api_epg_filter_set_str(&eq->subtitle, v, comp);
|
||||
else if (!strcmp(k, "summary"))
|
||||
api_epg_filter_set_str(&eq->summary, v, comp);
|
||||
else if (!strcmp(k, "description"))
|
||||
api_epg_filter_set_str(&eq->description, v, comp);
|
||||
}
|
||||
|
||||
static void
|
||||
api_epg_filter_set_num
|
||||
( epg_filter_num_t *f, int64_t v1, int64_t v2, int comp )
|
||||
{
|
||||
/* Range? */
|
||||
if (f->comp == EC_LT && comp == EC_GT) {
|
||||
f->val2 = f->val1;
|
||||
f->val1 = v1;
|
||||
f->comp = EC_RG;
|
||||
return;
|
||||
}
|
||||
if (f->comp == EC_GT && comp == EC_LT) {
|
||||
f->val2 = v1;
|
||||
f->comp = EC_RG;
|
||||
return;
|
||||
}
|
||||
f->val1 = v1;
|
||||
f->val2 = v2;
|
||||
f->comp = comp;
|
||||
}
|
||||
|
||||
static void
|
||||
api_epg_filter_add_num
|
||||
( epg_query_t *eq, const char *k, int64_t v1, int64_t v2, int comp )
|
||||
{
|
||||
if (!strcmp(k, "start"))
|
||||
api_epg_filter_set_num(&eq->start, v1, v2, comp);
|
||||
else if (!strcmp(k, "stop"))
|
||||
api_epg_filter_set_num(&eq->stop, v1, v2, comp);
|
||||
else if (!strcmp(k, "duration"))
|
||||
api_epg_filter_set_num(&eq->duration, v1, v2, comp);
|
||||
else if (!strcmp(k, "episode"))
|
||||
api_epg_filter_set_num(&eq->episode, v1, v2, comp);
|
||||
else if (!strcmp(k, "stars"))
|
||||
api_epg_filter_set_num(&eq->episode, v1, v2, comp);
|
||||
else if (!strcmp(k, "age"))
|
||||
api_epg_filter_set_num(&eq->age, v1, v2, comp);
|
||||
}
|
||||
|
||||
static struct strtab sortcmptab[] = {
|
||||
{ "start", ESK_START },
|
||||
{ "stop", ESK_STOP },
|
||||
{ "duration", ESK_DURATION },
|
||||
{ "title", ESK_TITLE },
|
||||
{ "subtitle", ESK_SUBTITLE },
|
||||
{ "summary", ESK_SUMMARY },
|
||||
{ "description", ESK_DESCRIPTION },
|
||||
{ "channelName", ESK_CHANNEL },
|
||||
{ "channelNumber", ESK_CHANNEL_NUM },
|
||||
{ "starRating", ESK_STARS },
|
||||
{ "ageRating", ESK_AGE },
|
||||
{ "genre", ESK_GENRE }
|
||||
};
|
||||
|
||||
static struct strtab filtcmptab[] = {
|
||||
{ "gt", EC_GT },
|
||||
{ "lt", EC_LT },
|
||||
{ "eq", EC_EQ },
|
||||
{ "regex", EC_RE },
|
||||
{ "range", EC_RG }
|
||||
};
|
||||
|
||||
static int64_t
|
||||
api_epg_decode_channel_num ( const char *s )
|
||||
{
|
||||
int64_t v = atol(s);
|
||||
const char *s1 = strchr(s, '.');
|
||||
if (s1)
|
||||
v += atol(s1 + 1) % CHANNEL_SPLIT;
|
||||
return v;
|
||||
}
|
||||
|
||||
static int
|
||||
api_epg_grid
|
||||
( access_t *perm, void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp )
|
||||
( void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp )
|
||||
{
|
||||
int i;
|
||||
epg_query_t eq;
|
||||
const char *lang, *str;
|
||||
uint32_t start, limit, end, genre;
|
||||
int64_t duration_min, duration_max;
|
||||
htsmsg_field_t *f, *f2;
|
||||
htsmsg_t *l = NULL, *e, *filter;
|
||||
epg_query_result_t eqr;
|
||||
const char *ch, *tag, *title, *lang/*, *genre*/;
|
||||
uint32_t start, limit, end;
|
||||
htsmsg_t *l = NULL, *e;
|
||||
int min_duration;
|
||||
int max_duration;
|
||||
|
||||
memset(&eq, 0, sizeof(eq));
|
||||
*resp = htsmsg_create_map();
|
||||
|
||||
lang = htsmsg_get_str(args, "lang");
|
||||
if (lang)
|
||||
eq.lang = strdup(lang);
|
||||
str = htsmsg_get_str(args, "title");
|
||||
if (str)
|
||||
eq.stitle = strdup(str);
|
||||
eq.fulltext = htsmsg_get_bool_or_default(args, "fulltext", 0);
|
||||
str = htsmsg_get_str(args, "channel");
|
||||
if (str)
|
||||
eq.channel = strdup(str);
|
||||
str = htsmsg_get_str(args, "channelTag");
|
||||
if (str)
|
||||
eq.channel_tag = strdup(str);
|
||||
/* Query params */
|
||||
ch = htsmsg_get_str(args, "channel");
|
||||
tag = htsmsg_get_str(args, "tag");
|
||||
//genre = htsmsg_get_str(args, "genre");
|
||||
title = htsmsg_get_str(args, "title");
|
||||
lang = htsmsg_get_str(args, "lang");
|
||||
// TODO: support multiple tag/genre/channel?
|
||||
|
||||
duration_min = -1;
|
||||
duration_max = -1;
|
||||
htsmsg_get_s64(args, "durationMin", &duration_min);
|
||||
htsmsg_get_s64(args, "durationMax", &duration_max);
|
||||
if (duration_min > 0 || duration_max > 0) {
|
||||
eq.duration.comp = EC_RG;
|
||||
eq.duration.val1 = duration_min < 0 ? 0 : duration_min;
|
||||
eq.duration.val2 = duration_max < 0 ? 0 : duration_max;
|
||||
}
|
||||
|
||||
if (!htsmsg_get_u32(args, "contentType", &genre)) {
|
||||
eq.genre = eq.genre_static;
|
||||
eq.genre[0] = genre;
|
||||
eq.genre_count = 1;
|
||||
}
|
||||
|
||||
/* Filter params */
|
||||
if ((filter = htsmsg_get_list(args, "filter"))) {
|
||||
HTSMSG_FOREACH(f, filter) {
|
||||
const char *k, *t, *v;
|
||||
int comp;
|
||||
if (!(e = htsmsg_get_map_by_field(f))) continue;
|
||||
if (!(k = htsmsg_get_str(e, "field"))) continue;
|
||||
if (!(t = htsmsg_get_str(e, "type"))) continue;
|
||||
comp = str2val(htsmsg_get_str(e, "comparison") ?: "", filtcmptab);
|
||||
if (comp == -1) comp = EC_EQ;
|
||||
if (!strcmp(k, "channelNumber")) {
|
||||
if (!strcmp(t, "numeric")) {
|
||||
f2 = htsmsg_field_find(e, "value");
|
||||
if (f2) {
|
||||
int64_t v1, v2 = 0;
|
||||
if (f2->hmf_type == HMF_STR) {
|
||||
const char *s = htsmsg_field_get_str(f2);
|
||||
const char *z = s ? strchr(s, ';') : NULL;
|
||||
if (s) {
|
||||
v1 = api_epg_decode_channel_num(s);
|
||||
if (z)
|
||||
v2 = api_epg_decode_channel_num(z);
|
||||
api_epg_filter_set_num(&eq.channel_num, v1, v2, comp);
|
||||
}
|
||||
} else {
|
||||
if (!htsmsg_field_get_s64(f2, &v1)) {
|
||||
if (v1 < CHANNEL_SPLIT)
|
||||
v1 *= CHANNEL_SPLIT;
|
||||
api_epg_filter_set_num(&eq.channel_num, v1, 0, comp);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (!strcmp(k, "genre")) {
|
||||
if (!strcmp(t, "numeric")) {
|
||||
f2 = htsmsg_field_find(e, "value");
|
||||
if (f2) {
|
||||
int64_t v;
|
||||
if (f2->hmf_type == HMF_STR) {
|
||||
htsmsg_t *z = api_epg_get_list(htsmsg_field_get_str(f2));
|
||||
if (z) {
|
||||
htsmsg_field_t *f3;
|
||||
uint32_t count = 0;
|
||||
HTSMSG_FOREACH(f3, z)
|
||||
count++;
|
||||
if (ARRAY_SIZE(eq.genre_static) > count)
|
||||
eq.genre = malloc(sizeof(eq.genre[0]) * count);
|
||||
else
|
||||
eq.genre = eq.genre_static;
|
||||
HTSMSG_FOREACH(f3, z)
|
||||
if (!htsmsg_field_get_s64(f3, &v))
|
||||
eq.genre[eq.genre_count++] = v;
|
||||
}
|
||||
} else {
|
||||
if (!htsmsg_field_get_s64(f2, &v)) {
|
||||
eq.genre_count = 1;
|
||||
eq.genre = eq.genre_static;
|
||||
eq.genre[0] = v;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (!strcmp(t, "string")) {
|
||||
if ((v = htsmsg_get_str(e, "value")))
|
||||
api_epg_filter_add_str(&eq, k, v, EC_RE);
|
||||
} else if (!strcmp(t, "numeric")) {
|
||||
f2 = htsmsg_field_find(e, "value");
|
||||
if (f2) {
|
||||
int64_t v1 = 0, v2 = 0;
|
||||
if (f2->hmf_type == HMF_STR) {
|
||||
const char *z = htsmsg_field_get_str(f2);
|
||||
if (z) {
|
||||
const char *z2 = strchr(z, ';');
|
||||
if (z2)
|
||||
v2 = strtoll(z2 + 1, NULL, 0);
|
||||
v1 = strtoll(z, NULL, 0);
|
||||
}
|
||||
api_epg_filter_add_num(&eq, k, v1, v2, comp);
|
||||
} else {
|
||||
if (!htsmsg_field_get_s64(f2, &v1))
|
||||
api_epg_filter_add_num(&eq, k, v1, v2, comp);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Sort */
|
||||
if ((str = htsmsg_get_str(args, "sort"))) {
|
||||
int skey = str2val(str, sortcmptab);
|
||||
if (skey >= 0) {
|
||||
eq.sort_key = skey;
|
||||
if ((str = htsmsg_get_str(args, "dir")) && !strcasecmp(str, "DESC"))
|
||||
eq.sort_dir = IS_DSC;
|
||||
else
|
||||
eq.sort_dir = IS_ASC;
|
||||
}
|
||||
} /* else.. keep default start time ascending sorting */
|
||||
min_duration = htsmsg_get_u32_or_default(args, "minduration", 0);
|
||||
max_duration = htsmsg_get_u32_or_default(args, "maxduration", INT_MAX);
|
||||
|
||||
/* Pagination settings */
|
||||
start = htsmsg_get_u32_or_default(args, "start", 0);
|
||||
|
@ -423,151 +152,34 @@ api_epg_grid
|
|||
|
||||
/* Query the EPG */
|
||||
pthread_mutex_lock(&global_lock);
|
||||
epg_query(&eq, perm);
|
||||
epg_query(&eqr, ch, tag, NULL, /*genre,*/ title, lang, min_duration, max_duration);
|
||||
epg_query_sort(&eqr);
|
||||
// TODO: optional sorting
|
||||
|
||||
/* Build response */
|
||||
start = MIN(eq.entries, start);
|
||||
end = MIN(eq.entries, start + limit);
|
||||
l = htsmsg_create_list();
|
||||
start = MIN(eqr.eqr_entries, start);
|
||||
end = MIN(eqr.eqr_entries, start + limit);
|
||||
for (i = start; i < end; i++) {
|
||||
if (!(e = api_epg_entry(eq.result[i], lang, perm))) continue;
|
||||
if (!(e = api_epg_entry(eqr.eqr_array[i], lang))) continue;
|
||||
if (!l) l = htsmsg_create_list();
|
||||
htsmsg_add_msg(l, NULL, e);
|
||||
}
|
||||
pthread_mutex_unlock(&global_lock);
|
||||
|
||||
epg_query_free(&eq);
|
||||
|
||||
/* Build response */
|
||||
*resp = htsmsg_create_map();
|
||||
htsmsg_add_u32(*resp, "totalCount", eq.entries);
|
||||
htsmsg_add_msg(*resp, "entries", l);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
api_epg_episode_broadcasts
|
||||
( access_t *perm, htsmsg_t *l, const char *lang, epg_episode_t *ep,
|
||||
uint32_t *entries, epg_broadcast_t *ebc_skip )
|
||||
{
|
||||
epg_broadcast_t *ebc;
|
||||
channel_t *ch;
|
||||
htsmsg_t *m;
|
||||
|
||||
LIST_FOREACH(ebc, &ep->broadcasts, ep_link) {
|
||||
ch = ebc->channel;
|
||||
if (ch == NULL) continue;
|
||||
if (ebc == ebc_skip) continue;
|
||||
m = api_epg_entry(ebc, lang, perm);
|
||||
htsmsg_add_msg(l, NULL, m);
|
||||
(*entries)++;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
api_epg_alternative
|
||||
( access_t *perm, void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp )
|
||||
{
|
||||
uint32_t id, entries = 0;
|
||||
htsmsg_t *l = htsmsg_create_list();
|
||||
epg_broadcast_t *e;
|
||||
const char *lang = htsmsg_get_str(args, "lang");
|
||||
|
||||
if (!htsmsg_get_u32(args, "eventId", &id))
|
||||
return -EINVAL;
|
||||
|
||||
/* Main Job */
|
||||
pthread_mutex_lock(&global_lock);
|
||||
e = epg_broadcast_find_by_id(id);
|
||||
if (e && e->episode)
|
||||
api_epg_episode_broadcasts(perm, l, lang, e->episode, &entries, e);
|
||||
pthread_mutex_unlock(&global_lock);
|
||||
|
||||
/* Build response */
|
||||
htsmsg_add_u32(*resp, "totalCount", entries);
|
||||
htsmsg_add_msg(*resp, "entries", l);
|
||||
htsmsg_add_u32(*resp, "totalCount", eqr.eqr_entries);
|
||||
if (l)
|
||||
htsmsg_add_msg(*resp, "events", l);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
api_epg_related
|
||||
( access_t *perm, void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp )
|
||||
{
|
||||
uint32_t id, entries = 0;
|
||||
htsmsg_t *l = htsmsg_create_list();
|
||||
epg_broadcast_t *e;
|
||||
epg_episode_t *ep, *ep2;
|
||||
const char *lang = htsmsg_get_str(args, "lang");
|
||||
|
||||
if (!htsmsg_get_u32(args, "eventId", &id))
|
||||
return -EINVAL;
|
||||
|
||||
/* Main Job */
|
||||
pthread_mutex_lock(&global_lock);
|
||||
e = epg_broadcast_find_by_id(id);
|
||||
ep = e ? e->episode : NULL;
|
||||
if (ep && ep->brand) {
|
||||
LIST_FOREACH(ep2, &ep->brand->episodes, blink) {
|
||||
if (ep2 == ep) continue;
|
||||
if (!ep2->title) continue;
|
||||
api_epg_episode_broadcasts(perm, l, lang, ep2, &entries, e);
|
||||
entries++;
|
||||
}
|
||||
} else if (ep && ep->season) {
|
||||
LIST_FOREACH(ep2, &ep->season->episodes, slink) {
|
||||
if (ep2 == ep) continue;
|
||||
if (!ep2->title) continue;
|
||||
api_epg_episode_broadcasts(perm, l, lang, ep2, &entries, e);
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(&global_lock);
|
||||
|
||||
/* Build response */
|
||||
htsmsg_add_u32(*resp, "totalCount", entries);
|
||||
htsmsg_add_msg(*resp, "entries", l);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
api_epg_brand_list(access_t *perm, void *opaque, const char *op,
|
||||
htsmsg_t *args, htsmsg_t **resp)
|
||||
{
|
||||
htsmsg_t *array;
|
||||
|
||||
*resp = htsmsg_create_map();
|
||||
pthread_mutex_lock(&global_lock);
|
||||
array = epg_brand_list();
|
||||
pthread_mutex_unlock(&global_lock);
|
||||
htsmsg_add_msg(*resp, "entries", array);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
api_epg_content_type_list(access_t *perm, void *opaque, const char *op,
|
||||
htsmsg_t *args, htsmsg_t **resp)
|
||||
{
|
||||
htsmsg_t *array;
|
||||
int full = 0;
|
||||
|
||||
htsmsg_get_bool(args, "full", &full);
|
||||
|
||||
*resp = htsmsg_create_map();
|
||||
array = epg_genres_list_all(full ? 0 : 1, 0);
|
||||
htsmsg_add_msg(*resp, "entries", array);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void api_epg_init ( void )
|
||||
{
|
||||
static api_hook_t ah[] = {
|
||||
{ "epg/events/grid", ACCESS_ANONYMOUS, api_epg_grid, NULL },
|
||||
{ "epg/events/alternative", ACCESS_ANONYMOUS, api_epg_alternative, NULL },
|
||||
{ "epg/events/related", ACCESS_ANONYMOUS, api_epg_related, NULL },
|
||||
{ "epg/brand/list", ACCESS_ANONYMOUS, api_epg_brand_list, NULL },
|
||||
{ "epg/content_type/list", ACCESS_ANONYMOUS, api_epg_content_type_list, NULL },
|
||||
|
||||
{ "epg/grid", ACCESS_ANONYMOUS, api_epg_grid, NULL },
|
||||
{ NULL },
|
||||
};
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
|
||||
static int
|
||||
api_epggrab_channel_list
|
||||
( access_t *perm, void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp )
|
||||
( void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp )
|
||||
{
|
||||
htsmsg_t *m;
|
||||
pthread_mutex_lock(&global_lock);
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
|
||||
static void
|
||||
api_esfilter_grid
|
||||
( access_t *perm, idnode_set_t *ins, api_idnode_grid_conf_t *conf, htsmsg_t *args,
|
||||
( idnode_set_t *ins, api_idnode_grid_conf_t *conf, htsmsg_t *args,
|
||||
esfilter_class_t cls )
|
||||
{
|
||||
esfilter_t *esf;
|
||||
|
@ -37,7 +37,7 @@ api_esfilter_grid
|
|||
|
||||
static int
|
||||
api_esfilter_create
|
||||
( access_t *perm, void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp,
|
||||
( void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp,
|
||||
esfilter_class_t cls )
|
||||
{
|
||||
htsmsg_t *conf;
|
||||
|
@ -54,11 +54,11 @@ api_esfilter_create
|
|||
|
||||
#define ESFILTER(func, t) \
|
||||
static void api_esfilter_grid_##func \
|
||||
( access_t *perm, idnode_set_t *ins, api_idnode_grid_conf_t *conf, htsmsg_t *args ) \
|
||||
{ return api_esfilter_grid(perm, ins, conf, args, (t)); } \
|
||||
( idnode_set_t *ins, api_idnode_grid_conf_t *conf, htsmsg_t *args ) \
|
||||
{ return api_esfilter_grid(ins, conf, args, (t)); } \
|
||||
static int api_esfilter_create_##func \
|
||||
( access_t *perm, void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp ) \
|
||||
{ return api_esfilter_create(perm, opaque, op, args, resp, (t)); }
|
||||
( void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp ) \
|
||||
{ return api_esfilter_create(opaque, op, args, resp, (t)); }
|
||||
|
||||
ESFILTER(video, ESF_CLASS_VIDEO);
|
||||
ESFILTER(audio, ESF_CLASS_AUDIO);
|
||||
|
|
|
@ -23,35 +23,6 @@
|
|||
#include "htsmsg.h"
|
||||
#include "api.h"
|
||||
|
||||
static htsmsg_t *
|
||||
api_idnode_flist_conf( htsmsg_t *args, const char *name )
|
||||
{
|
||||
htsmsg_t *m = NULL;
|
||||
const char *s = htsmsg_get_str(args, name);
|
||||
char *r, *saveptr = NULL;
|
||||
int use = 1;
|
||||
if (s && s[0] == '-') {
|
||||
use = 0;
|
||||
s++;
|
||||
}
|
||||
if (s && s[0] != '\0') {
|
||||
s = r = strdup(s);
|
||||
r = strtok_r(r, ",;:", &saveptr);
|
||||
while (r) {
|
||||
while (*r != '\0' && *r <= ' ')
|
||||
r++;
|
||||
if (*r != '\0') {
|
||||
if (m == NULL)
|
||||
m = htsmsg_create_map();
|
||||
htsmsg_add_bool(m, r, use);
|
||||
}
|
||||
r = strtok_r(NULL, ",;:", &saveptr);
|
||||
}
|
||||
free((char *)s);
|
||||
}
|
||||
return m;
|
||||
}
|
||||
|
||||
static struct strtab filtcmptab[] = {
|
||||
{ "gt", IC_GT },
|
||||
{ "lt", IC_LT },
|
||||
|
@ -62,12 +33,21 @@ static void
|
|||
api_idnode_grid_conf
|
||||
( htsmsg_t *args, api_idnode_grid_conf_t *conf )
|
||||
{
|
||||
htsmsg_field_t *f, *f2;
|
||||
htsmsg_field_t *f;
|
||||
htsmsg_t *filter, *e;
|
||||
const char *str;
|
||||
|
||||
conf->start = htsmsg_get_u32_or_default(args, "start", 0);
|
||||
conf->limit = htsmsg_get_u32_or_default(args, "limit", 50);
|
||||
/* Start */
|
||||
if ((str = htsmsg_get_str(args, "start")))
|
||||
conf->start = atoi(str);
|
||||
else
|
||||
conf->start = 0;
|
||||
|
||||
/* Limit */
|
||||
if ((str = htsmsg_get_str(args, "limit")))
|
||||
conf->limit = atoi(str);
|
||||
else
|
||||
conf->limit = 50;
|
||||
|
||||
/* Filter */
|
||||
if ((filter = htsmsg_get_list(args, "filter"))) {
|
||||
|
@ -80,20 +60,11 @@ api_idnode_grid_conf
|
|||
if ((v = htsmsg_get_str(e, "value")))
|
||||
idnode_filter_add_str(&conf->filter, k, v, IC_RE);
|
||||
} else if (!strcmp(t, "numeric")) {
|
||||
f2 = htsmsg_field_find(e, "value");
|
||||
if (f2) {
|
||||
int t = str2val(htsmsg_get_str(e, "comparison") ?: "", filtcmptab);
|
||||
if (f2->hmf_type == HMF_DBL) {
|
||||
double dbl;
|
||||
if (!htsmsg_field_get_dbl(f2, &dbl))
|
||||
idnode_filter_add_dbl(&conf->filter, k, dbl, t == -1 ? IC_EQ : t);
|
||||
} else {
|
||||
int64_t v;
|
||||
int64_t intsplit = 0;
|
||||
htsmsg_get_s64(e, "intsplit", &intsplit);
|
||||
if (!htsmsg_field_get_s64(f2, &v))
|
||||
idnode_filter_add_num(&conf->filter, k, v, t == -1 ? IC_EQ : t, intsplit);
|
||||
}
|
||||
uint32_t v;
|
||||
if (!htsmsg_get_u32(e, "value", &v)) {
|
||||
int t = str2val(htsmsg_get_str(e, "comparison") ?: "",
|
||||
filtcmptab);
|
||||
idnode_filter_add_num(&conf->filter, k, v, t == -1 ? IC_EQ : t);
|
||||
}
|
||||
} else if (!strcmp(t, "boolean")) {
|
||||
uint32_t v;
|
||||
|
@ -106,7 +77,7 @@ api_idnode_grid_conf
|
|||
/* Sort */
|
||||
if ((str = htsmsg_get_str(args, "sort"))) {
|
||||
conf->sort.key = str;
|
||||
if ((str = htsmsg_get_str(args, "dir")) && !strcasecmp(str, "DESC"))
|
||||
if ((str = htsmsg_get_str(args, "dir")) && !strcmp(str, "DESC"))
|
||||
conf->sort.dir = IS_DSC;
|
||||
else
|
||||
conf->sort.dir = IS_ASC;
|
||||
|
@ -116,11 +87,10 @@ api_idnode_grid_conf
|
|||
|
||||
int
|
||||
api_idnode_grid
|
||||
( access_t *perm, void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp )
|
||||
( void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp )
|
||||
{
|
||||
int i;
|
||||
htsmsg_t *list, *e;
|
||||
htsmsg_t *flist = api_idnode_flist_conf(args, "list");
|
||||
api_idnode_grid_conf_t conf = { 0 };
|
||||
idnode_set_t ins = { 0 };
|
||||
api_idnode_grid_callback_t cb = opaque;
|
||||
|
@ -130,7 +100,7 @@ api_idnode_grid
|
|||
|
||||
/* Create list */
|
||||
pthread_mutex_lock(&global_lock);
|
||||
cb(perm, &ins, &conf, args);
|
||||
cb(&ins, &conf, args);
|
||||
|
||||
/* Sort */
|
||||
if (conf.sort.key)
|
||||
|
@ -141,7 +111,7 @@ api_idnode_grid
|
|||
for (i = conf.start; i < ins.is_count && conf.limit != 0; i++) {
|
||||
e = htsmsg_create_map();
|
||||
htsmsg_add_str(e, "uuid", idnode_uuid_as_str(ins.is_array[i]));
|
||||
idnode_read0(ins.is_array[i], e, flist, 0);
|
||||
idnode_read0(ins.is_array[i], e, 0);
|
||||
htsmsg_add_msg(list, NULL, e);
|
||||
if (conf.limit > 0) conf.limit--;
|
||||
}
|
||||
|
@ -156,14 +126,13 @@ api_idnode_grid
|
|||
/* Cleanup */
|
||||
free(ins.is_array);
|
||||
idnode_filter_clear(&conf.filter);
|
||||
htsmsg_destroy(flist);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
api_idnode_load_by_class
|
||||
( access_t *perm, void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp )
|
||||
( void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp )
|
||||
{
|
||||
int i, _enum;
|
||||
const idclass_t *idc;
|
||||
|
@ -181,13 +150,10 @@ api_idnode_load_by_class
|
|||
assert(idc);
|
||||
|
||||
l = htsmsg_create_list();
|
||||
if ((is = idnode_find_all(idc, NULL))) {
|
||||
if ((is = idnode_find_all(idc))) {
|
||||
for (i = 0; i < is->is_count; i++) {
|
||||
in = is->is_array[i];
|
||||
|
||||
if (idnode_perm(in, perm, NULL))
|
||||
continue;
|
||||
|
||||
/* Name/UUID only */
|
||||
if (_enum) {
|
||||
e = htsmsg_create_map();
|
||||
|
@ -195,11 +161,8 @@ api_idnode_load_by_class
|
|||
htsmsg_add_str(e, "val", idnode_get_title(in));
|
||||
|
||||
/* Full record */
|
||||
} else {
|
||||
htsmsg_t *flist = api_idnode_flist_conf(args, "list");
|
||||
e = idnode_serialize0(in, flist, 0);
|
||||
htsmsg_destroy(flist);
|
||||
}
|
||||
} else
|
||||
e = idnode_serialize(in);
|
||||
|
||||
if (e)
|
||||
htsmsg_add_msg(l, NULL, e);
|
||||
|
@ -217,12 +180,11 @@ api_idnode_load_by_class
|
|||
|
||||
static int
|
||||
api_idnode_load
|
||||
( access_t *perm, void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp )
|
||||
( void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp )
|
||||
{
|
||||
int err = 0, meta, count = 0;
|
||||
int err = 0;
|
||||
idnode_t *in;
|
||||
htsmsg_t *uuids, *l = NULL, *m;
|
||||
htsmsg_t *flist;
|
||||
htsmsg_t *uuids, *l = NULL;
|
||||
htsmsg_field_t *f;
|
||||
const char *uuid, *class;
|
||||
|
||||
|
@ -235,7 +197,7 @@ api_idnode_load
|
|||
if (!idc)
|
||||
return EINVAL;
|
||||
// TODO: bit naff that 2 locks are required here
|
||||
return api_idnode_load_by_class(perm, (void*)idc, NULL, args, resp);
|
||||
return api_idnode_load_by_class((void*)idc, NULL, args, resp);
|
||||
}
|
||||
|
||||
/* UUIDs */
|
||||
|
@ -244,48 +206,25 @@ api_idnode_load
|
|||
if (!(uuids = htsmsg_field_get_list(f)))
|
||||
if (!(uuid = htsmsg_field_get_str(f)))
|
||||
return EINVAL;
|
||||
meta = htsmsg_get_s32_or_default(args, "meta", 0);
|
||||
|
||||
flist = api_idnode_flist_conf(args, "list");
|
||||
|
||||
pthread_mutex_lock(&global_lock);
|
||||
|
||||
/* Multiple */
|
||||
if (uuids) {
|
||||
const idnodes_rb_t *domain = NULL;
|
||||
l = htsmsg_create_list();
|
||||
HTSMSG_FOREACH(f, uuids) {
|
||||
if (!(uuid = htsmsg_field_get_str(f))) continue;
|
||||
if (!(in = idnode_find(uuid, NULL, domain))) continue;
|
||||
domain = in->in_domain;
|
||||
if (idnode_perm(in, perm, NULL)) {
|
||||
err = EPERM;
|
||||
continue;
|
||||
}
|
||||
m = idnode_serialize0(in, flist, 0);
|
||||
if (meta > 0)
|
||||
htsmsg_add_msg(m, "meta", idclass_serialize0(in->in_class, flist, 0));
|
||||
htsmsg_add_msg(l, NULL, m);
|
||||
count++;
|
||||
if (!(in = idnode_find(uuid, NULL))) continue;
|
||||
htsmsg_add_msg(l, NULL, idnode_serialize(in));
|
||||
}
|
||||
|
||||
if (count)
|
||||
err = 0;
|
||||
|
||||
/* Single */
|
||||
} else {
|
||||
if (!(in = idnode_find(uuid, NULL, NULL)))
|
||||
if (!(in = idnode_find(uuid, NULL)))
|
||||
err = ENOENT;
|
||||
else {
|
||||
if (idnode_perm(in, perm, NULL)) {
|
||||
err = EPERM;
|
||||
} else {
|
||||
l = htsmsg_create_list();
|
||||
m = idnode_serialize0(in, flist, 0);
|
||||
if (meta > 0)
|
||||
htsmsg_add_msg(m, "meta", idclass_serialize0(in->in_class, flist, 0));
|
||||
htsmsg_add_msg(l, NULL, m);
|
||||
}
|
||||
l = htsmsg_create_list();
|
||||
htsmsg_add_msg(l, NULL, idnode_serialize(in));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -296,21 +235,18 @@ api_idnode_load
|
|||
|
||||
pthread_mutex_unlock(&global_lock);
|
||||
|
||||
htsmsg_destroy(flist);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int
|
||||
api_idnode_save
|
||||
( access_t *perm, void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp )
|
||||
( void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp )
|
||||
{
|
||||
int err = EINVAL;
|
||||
idnode_t *in;
|
||||
htsmsg_t *msg, *conf;
|
||||
htsmsg_field_t *f;
|
||||
const char *uuid;
|
||||
int count = 0;
|
||||
|
||||
if (!(f = htsmsg_field_find(args, "node")))
|
||||
return EINVAL;
|
||||
|
@ -324,35 +260,23 @@ api_idnode_save
|
|||
if (!msg->hm_islist) {
|
||||
if (!(uuid = htsmsg_get_str(msg, "uuid")))
|
||||
goto exit;
|
||||
if (!(in = idnode_find(uuid, NULL, NULL)))
|
||||
if (!(in = idnode_find(uuid, NULL)))
|
||||
goto exit;
|
||||
if (idnode_perm(in, perm, msg)) {
|
||||
err = EPERM;
|
||||
goto exit;
|
||||
}
|
||||
idnode_update(in, msg);
|
||||
err = 0;
|
||||
|
||||
/* Multiple */
|
||||
} else {
|
||||
const idnodes_rb_t *domain = NULL;
|
||||
HTSMSG_FOREACH(f, msg) {
|
||||
if (!(conf = htsmsg_field_get_map(f)))
|
||||
continue;
|
||||
if (!(uuid = htsmsg_get_str(conf, "uuid")))
|
||||
continue;
|
||||
if (!(in = idnode_find(uuid, NULL, domain)))
|
||||
if (!(in = idnode_find(uuid, NULL)))
|
||||
continue;
|
||||
domain = in->in_domain;
|
||||
if (idnode_perm(in, perm, conf)) {
|
||||
err = EPERM;
|
||||
continue;
|
||||
}
|
||||
count++;
|
||||
idnode_update(in, conf);
|
||||
}
|
||||
if (count)
|
||||
err = 0;
|
||||
err = 0;
|
||||
}
|
||||
|
||||
// TODO: return updated UUIDs?
|
||||
|
@ -365,7 +289,7 @@ exit:
|
|||
|
||||
int
|
||||
api_idnode_tree
|
||||
( access_t *perm, void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp )
|
||||
( void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp )
|
||||
{
|
||||
const char *uuid;
|
||||
const char *root = NULL;
|
||||
|
@ -389,7 +313,7 @@ api_idnode_tree
|
|||
pthread_mutex_lock(&global_lock);
|
||||
|
||||
if (!isroot || root) {
|
||||
if (!(node = idnode_find(isroot ? root : uuid, NULL, NULL))) {
|
||||
if (!(node = idnode_find(isroot ? root : uuid, NULL))) {
|
||||
pthread_mutex_unlock(&global_lock);
|
||||
return EINVAL;
|
||||
}
|
||||
|
@ -405,7 +329,7 @@ api_idnode_tree
|
|||
|
||||
/* Children */
|
||||
} else {
|
||||
idnode_set_t *v = node ? idnode_get_childs(node) : rootfn(perm);
|
||||
idnode_set_t *v = node ? idnode_get_childs(node) : rootfn();
|
||||
if (v) {
|
||||
int i;
|
||||
idnode_set_sort_by_title(v);
|
||||
|
@ -424,12 +348,11 @@ api_idnode_tree
|
|||
|
||||
int
|
||||
api_idnode_class
|
||||
( access_t *perm, void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp )
|
||||
( void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp )
|
||||
{
|
||||
int err = EINVAL;
|
||||
const char *name;
|
||||
const idclass_t *idc;
|
||||
htsmsg_t *flist = api_idnode_flist_conf(args, "list");
|
||||
|
||||
pthread_mutex_lock(&global_lock);
|
||||
|
||||
|
@ -445,20 +368,17 @@ api_idnode_class
|
|||
}
|
||||
|
||||
err = 0;
|
||||
*resp = idclass_serialize0(idc, flist, 0);
|
||||
*resp = idclass_serialize(idc);
|
||||
|
||||
exit:
|
||||
pthread_mutex_unlock(&global_lock);
|
||||
|
||||
htsmsg_destroy(flist);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
int
|
||||
static int
|
||||
api_idnode_handler
|
||||
( access_t *perm, htsmsg_t *args, htsmsg_t **resp,
|
||||
void (*handler)(access_t *perm, idnode_t *in) )
|
||||
( htsmsg_t *args, htsmsg_t **resp, void (*handler)(idnode_t *in) )
|
||||
{
|
||||
int err = 0;
|
||||
idnode_t *in;
|
||||
|
@ -477,21 +397,19 @@ api_idnode_handler
|
|||
|
||||
/* Multiple */
|
||||
if (uuids) {
|
||||
const idnodes_rb_t *domain = NULL;
|
||||
HTSMSG_FOREACH(f, uuids) {
|
||||
if (!(uuid = htsmsg_field_get_string(f))) continue;
|
||||
if (!(in = idnode_find(uuid, NULL, domain))) continue;
|
||||
domain = in->in_domain;
|
||||
handler(perm, in);
|
||||
if (!(in = idnode_find(uuid, NULL))) continue;
|
||||
handler(in);
|
||||
}
|
||||
|
||||
/* Single */
|
||||
} else {
|
||||
uuid = htsmsg_field_get_string(f);
|
||||
if (!(in = idnode_find(uuid, NULL, NULL)))
|
||||
if (!(in = idnode_find(uuid, NULL)))
|
||||
err = ENOENT;
|
||||
else
|
||||
handler(perm, in);
|
||||
handler(in);
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&global_lock);
|
||||
|
@ -499,43 +417,25 @@ api_idnode_handler
|
|||
return err;
|
||||
}
|
||||
|
||||
static void
|
||||
api_idnode_delete_ (access_t *perm, idnode_t *in)
|
||||
{
|
||||
return idnode_delete(in);
|
||||
}
|
||||
|
||||
static int
|
||||
api_idnode_delete
|
||||
( access_t *perm, void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp )
|
||||
( void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp )
|
||||
{
|
||||
return api_idnode_handler(perm, args, resp, api_idnode_delete_);
|
||||
}
|
||||
|
||||
static void
|
||||
api_idnode_moveup_ (access_t *perm, idnode_t *in)
|
||||
{
|
||||
return idnode_moveup(in);
|
||||
return api_idnode_handler(args, resp, idnode_delete);
|
||||
}
|
||||
|
||||
static int
|
||||
api_idnode_moveup
|
||||
( access_t *perm, void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp )
|
||||
( void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp )
|
||||
{
|
||||
return api_idnode_handler(perm, args, resp, api_idnode_moveup_);
|
||||
}
|
||||
|
||||
static void
|
||||
api_idnode_movedown_ (access_t *perm, idnode_t *in)
|
||||
{
|
||||
return idnode_movedown(in);
|
||||
return api_idnode_handler(args, resp, idnode_moveup);
|
||||
}
|
||||
|
||||
static int
|
||||
api_idnode_movedown
|
||||
( access_t *perm, void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp )
|
||||
( void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp )
|
||||
{
|
||||
return api_idnode_handler(perm, args, resp, api_idnode_movedown_);
|
||||
return api_idnode_handler(args, resp, idnode_movedown);
|
||||
}
|
||||
|
||||
void api_idnode_init ( void )
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
|
||||
static int
|
||||
api_imagecache_load
|
||||
( access_t *perm, void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp )
|
||||
( void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp )
|
||||
{
|
||||
htsmsg_t *l;
|
||||
pthread_mutex_lock(&global_lock);
|
||||
|
@ -41,15 +41,11 @@ api_imagecache_load
|
|||
|
||||
static int
|
||||
api_imagecache_save
|
||||
( access_t *perm, void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp )
|
||||
( void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp )
|
||||
{
|
||||
int b;
|
||||
|
||||
pthread_mutex_lock(&global_lock);
|
||||
if (imagecache_set_config(args))
|
||||
imagecache_save();
|
||||
if (!htsmsg_get_bool(args, "clean", &b) && b)
|
||||
imagecache_clean();
|
||||
pthread_mutex_unlock(&global_lock);
|
||||
*resp = htsmsg_create_map();
|
||||
htsmsg_add_u32(*resp, "success", 1);
|
||||
|
|
|
@ -30,7 +30,7 @@ static idnode_set_t *
|
|||
api_input_hw_tree ( void )
|
||||
{
|
||||
tvh_hardware_t *th;
|
||||
idnode_set_t *is = idnode_set_create(0);
|
||||
idnode_set_t *is = idnode_set_create();
|
||||
TVH_HARDWARE_FOREACH(th)
|
||||
idnode_set_add(is, &th->th_id, NULL);
|
||||
return is;
|
||||
|
|
|
@ -27,22 +27,28 @@
|
|||
|
||||
static int
|
||||
api_intlconv_charset_enum
|
||||
( access_t *perm, void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp )
|
||||
( void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp )
|
||||
{
|
||||
const char **chrst;
|
||||
htsmsg_t *l, *e;
|
||||
|
||||
l = htsmsg_create_list();
|
||||
chrst = intlconv_charsets;
|
||||
while (*chrst) {
|
||||
e = htsmsg_create_map();
|
||||
htsmsg_add_str(e, "key", *chrst);
|
||||
htsmsg_add_str(e, "val", *chrst);
|
||||
htsmsg_add_msg(l, NULL, e);
|
||||
chrst++;
|
||||
int _enum = htsmsg_get_bool_or_default(args, "enum", 0);
|
||||
|
||||
if (_enum) {
|
||||
l = htsmsg_create_list();
|
||||
chrst = intlconv_charsets;
|
||||
while (*chrst) {
|
||||
e = htsmsg_create_map();
|
||||
htsmsg_add_str(e, "key", *chrst);
|
||||
htsmsg_add_str(e, "val", *chrst);
|
||||
htsmsg_add_msg(l, NULL, e);
|
||||
chrst++;
|
||||
}
|
||||
*resp = htsmsg_create_map();
|
||||
htsmsg_add_msg(*resp, "entries", l);
|
||||
} else {
|
||||
// TODO: support full listing v enum
|
||||
}
|
||||
*resp = htsmsg_create_map();
|
||||
htsmsg_add_msg(*resp, "entries", l);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
*/
|
||||
static int
|
||||
api_mpegts_input_network_list
|
||||
( access_t *perm, void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp )
|
||||
( void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp )
|
||||
{
|
||||
int i, err = EINVAL;
|
||||
const char *uuid;
|
||||
|
@ -49,8 +49,6 @@ api_mpegts_input_network_list
|
|||
if (!mi)
|
||||
goto exit;
|
||||
|
||||
tvhtrace("mpegts", "network-list: found input '%s'", mi->mi_name ?: "");
|
||||
|
||||
htsmsg_t *l = htsmsg_create_list();
|
||||
if ((is = mi->mi_network_list(mi))) {
|
||||
for (i = 0; i < is->is_count; i++) {
|
||||
|
@ -79,7 +77,7 @@ exit:
|
|||
*/
|
||||
static void
|
||||
api_mpegts_network_grid
|
||||
( access_t *perm, idnode_set_t *ins, api_idnode_grid_conf_t *conf, htsmsg_t *args )
|
||||
( idnode_set_t *ins, api_idnode_grid_conf_t *conf, htsmsg_t *args )
|
||||
{
|
||||
mpegts_network_t *mn;
|
||||
|
||||
|
@ -90,7 +88,7 @@ api_mpegts_network_grid
|
|||
|
||||
static int
|
||||
api_mpegts_network_builders
|
||||
( access_t *perm, void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp )
|
||||
( void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp )
|
||||
{
|
||||
mpegts_network_builder_t *mnb;
|
||||
htsmsg_t *l, *e;
|
||||
|
@ -110,7 +108,7 @@ api_mpegts_network_builders
|
|||
|
||||
static int
|
||||
api_mpegts_network_create
|
||||
( access_t *perm, void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp )
|
||||
( void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp )
|
||||
{
|
||||
int err;
|
||||
const char *class;
|
||||
|
@ -136,46 +134,9 @@ api_mpegts_network_create
|
|||
return err;
|
||||
}
|
||||
|
||||
static int
|
||||
api_mpegts_network_scan
|
||||
( access_t *perm, void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp )
|
||||
{
|
||||
htsmsg_field_t *f;
|
||||
htsmsg_t *uuids;
|
||||
mpegts_network_t *mn;
|
||||
const char *uuid;
|
||||
|
||||
if (!(f = htsmsg_field_find(args, "uuid")))
|
||||
return -EINVAL;
|
||||
if ((uuids = htsmsg_field_get_list(f))) {
|
||||
HTSMSG_FOREACH(f, uuids) {
|
||||
if (!(uuid = htsmsg_field_get_str(f))) continue;
|
||||
mn = mpegts_network_find(uuid);
|
||||
if (mn) {
|
||||
pthread_mutex_lock(&global_lock);
|
||||
mpegts_network_scan(mn);
|
||||
pthread_mutex_unlock(&global_lock);
|
||||
}
|
||||
}
|
||||
} else if ((uuid = htsmsg_field_get_str(f))) {
|
||||
mn = mpegts_network_find(uuid);
|
||||
if (mn) {
|
||||
pthread_mutex_lock(&global_lock);
|
||||
mpegts_network_scan(mn);
|
||||
pthread_mutex_unlock(&global_lock);
|
||||
}
|
||||
else
|
||||
return -ENOENT;
|
||||
} else {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
api_mpegts_network_muxclass
|
||||
( access_t *perm, void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp )
|
||||
( void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp )
|
||||
{
|
||||
int err = EINVAL;
|
||||
const idclass_t *idc;
|
||||
|
@ -203,7 +164,7 @@ exit:
|
|||
|
||||
static int
|
||||
api_mpegts_network_muxcreate
|
||||
( access_t *perm, void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp )
|
||||
( void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp )
|
||||
{
|
||||
int err = EINVAL;
|
||||
mpegts_network_t *mn;
|
||||
|
@ -237,7 +198,7 @@ exit:
|
|||
*/
|
||||
static void
|
||||
api_mpegts_mux_grid
|
||||
( access_t *perm, idnode_set_t *ins, api_idnode_grid_conf_t *conf, htsmsg_t *args )
|
||||
( idnode_set_t *ins, api_idnode_grid_conf_t *conf, htsmsg_t *args )
|
||||
{
|
||||
mpegts_network_t *mn;
|
||||
mpegts_mux_t *mm;
|
||||
|
@ -264,7 +225,7 @@ api_mpegts_mux_grid
|
|||
*/
|
||||
static void
|
||||
api_mpegts_service_grid
|
||||
( access_t *perm, idnode_set_t *ins, api_idnode_grid_conf_t *conf, htsmsg_t *args )
|
||||
( idnode_set_t *ins, api_idnode_grid_conf_t *conf, htsmsg_t *args )
|
||||
{
|
||||
mpegts_network_t *mn;
|
||||
mpegts_mux_t *mm;
|
||||
|
@ -283,7 +244,7 @@ api_mpegts_service_grid
|
|||
LIST_FOREACH(mm, &mn->mn_muxes, mm_network_link) {
|
||||
if (hide && !mm->mm_is_enabled(mm)) continue;
|
||||
LIST_FOREACH(ms, &mm->mm_services, s_dvb_mux_link) {
|
||||
if (hide == 2 && !ms->s_is_enabled((service_t*)ms, 0)) continue;
|
||||
if (hide == 2 && !ms->s_is_enabled((service_t*)ms)) continue;
|
||||
idnode_set_add(ins, (idnode_t*)ms, &conf->filter);
|
||||
}
|
||||
}
|
||||
|
@ -295,7 +256,7 @@ api_mpegts_service_grid
|
|||
*/
|
||||
static void
|
||||
api_mpegts_mux_sched_grid
|
||||
( access_t *perm, idnode_set_t *ins, api_idnode_grid_conf_t *conf, htsmsg_t *args )
|
||||
( idnode_set_t *ins, api_idnode_grid_conf_t *conf, htsmsg_t *args )
|
||||
{
|
||||
mpegts_mux_sched_t *mms;
|
||||
LIST_FOREACH(mms, &mpegts_mux_sched_all, mms_link)
|
||||
|
@ -304,7 +265,7 @@ api_mpegts_mux_sched_grid
|
|||
|
||||
static int
|
||||
api_mpegts_mux_sched_create
|
||||
( access_t *perm, void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp )
|
||||
( void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp )
|
||||
{
|
||||
int err;
|
||||
htsmsg_t *conf;
|
||||
|
@ -327,51 +288,13 @@ api_mpegts_mux_sched_create
|
|||
return err;
|
||||
}
|
||||
|
||||
#if ENABLE_MPEGTS_DVB
|
||||
static int
|
||||
api_dvb_orbitalpos_list
|
||||
( access_t *perm, void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp )
|
||||
{
|
||||
htsmsg_t *l, *e, *c;
|
||||
htsmsg_field_t *f;
|
||||
const char *s;
|
||||
int satpos, i;
|
||||
char buf[128];
|
||||
|
||||
if (!satellites)
|
||||
return 0;
|
||||
|
||||
l = htsmsg_create_list();
|
||||
HTSMSG_FOREACH(f, satellites) {
|
||||
if((c = htsmsg_get_map_by_field(f)) == NULL)
|
||||
continue;
|
||||
if(htsmsg_get_s32(c, "pos", &satpos))
|
||||
continue;
|
||||
if((s = htsmsg_get_str(c, "name")) == NULL)
|
||||
continue;
|
||||
e = htsmsg_create_map();
|
||||
dvb_sat_position_to_str(satpos, buf, sizeof(buf));
|
||||
htsmsg_add_str(e, "key", buf);
|
||||
i = strlen(buf);
|
||||
snprintf(buf + i, sizeof(buf) - i, " : %s", s);
|
||||
htsmsg_add_str(e, "val", buf);
|
||||
htsmsg_add_msg(l, NULL, e);
|
||||
}
|
||||
*resp = htsmsg_create_map();
|
||||
htsmsg_add_msg(*resp, "entries", l);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ENABLE_MPEGTS_DVB
|
||||
static int
|
||||
api_dvb_scanfile_list
|
||||
( access_t *perm, void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp )
|
||||
( void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp )
|
||||
{
|
||||
char buf[512];
|
||||
const char *type = htsmsg_get_str(args, "type");
|
||||
int satpos = htsmsg_get_s32_or_default(args, "satpos", INT_MAX);
|
||||
scanfile_region_list_t *list = NULL;
|
||||
htsmsg_t *l, *e;
|
||||
scanfile_region_t *r;
|
||||
|
@ -394,7 +317,6 @@ api_dvb_scanfile_list
|
|||
l = htsmsg_create_list();
|
||||
LIST_FOREACH(r, list, sfr_link) {
|
||||
LIST_FOREACH(n, &r->sfr_networks, sfn_link) {
|
||||
if (satpos != INT_MAX && n->sfn_satpos != satpos) continue;
|
||||
e = htsmsg_create_map();
|
||||
sprintf(buf, "%s/%s/%s", type, r->sfr_id, n->sfn_id);
|
||||
htsmsg_add_str(e, "key", buf);
|
||||
|
@ -425,24 +347,22 @@ api_mpegts_init ( void )
|
|||
extern const idclass_t mpegts_service_class;
|
||||
|
||||
static api_hook_t ah[] = {
|
||||
{ "mpegts/input/network_list", ACCESS_ADMIN, api_mpegts_input_network_list, NULL },
|
||||
{ "mpegts/network/grid", ACCESS_ADMIN, api_idnode_grid, api_mpegts_network_grid },
|
||||
{ "mpegts/network/class", ACCESS_ADMIN, api_idnode_class, (void*)&mpegts_network_class },
|
||||
{ "mpegts/network/builders", ACCESS_ADMIN, api_mpegts_network_builders, NULL },
|
||||
{ "mpegts/network/create", ACCESS_ADMIN, api_mpegts_network_create, NULL },
|
||||
{ "mpegts/network/mux_class", ACCESS_ADMIN, api_mpegts_network_muxclass, NULL },
|
||||
{ "mpegts/network/mux_create", ACCESS_ADMIN, api_mpegts_network_muxcreate, NULL },
|
||||
{ "mpegts/network/scan", ACCESS_ADMIN, api_mpegts_network_scan, NULL },
|
||||
{ "mpegts/mux/grid", ACCESS_ADMIN, api_idnode_grid, api_mpegts_mux_grid },
|
||||
{ "mpegts/mux/class", ACCESS_ADMIN, api_idnode_class, (void*)&mpegts_mux_class },
|
||||
{ "mpegts/service/grid", ACCESS_ADMIN, api_idnode_grid, api_mpegts_service_grid },
|
||||
{ "mpegts/service/class", ACCESS_ADMIN, api_idnode_class, (void*)&mpegts_service_class },
|
||||
{ "mpegts/mux_sched/class", ACCESS_ADMIN, api_idnode_class, (void*)&mpegts_mux_sched_class },
|
||||
{ "mpegts/mux_sched/grid", ACCESS_ADMIN, api_idnode_grid, api_mpegts_mux_sched_grid },
|
||||
{ "mpegts/mux_sched/create", ACCESS_ADMIN, api_mpegts_mux_sched_create, NULL },
|
||||
{ "mpegts/input/network_list", ACCESS_ANONYMOUS, api_mpegts_input_network_list, NULL },
|
||||
{ "mpegts/network/grid", ACCESS_ANONYMOUS, api_idnode_grid, api_mpegts_network_grid },
|
||||
{ "mpegts/network/class", ACCESS_ANONYMOUS, api_idnode_class, (void*)&mpegts_network_class },
|
||||
{ "mpegts/network/builders", ACCESS_ANONYMOUS, api_mpegts_network_builders, NULL },
|
||||
{ "mpegts/network/create", ACCESS_ANONYMOUS, api_mpegts_network_create, NULL },
|
||||
{ "mpegts/network/mux_class", ACCESS_ANONYMOUS, api_mpegts_network_muxclass, NULL },
|
||||
{ "mpegts/network/mux_create", ACCESS_ANONYMOUS, api_mpegts_network_muxcreate, NULL },
|
||||
{ "mpegts/mux/grid", ACCESS_ANONYMOUS, api_idnode_grid, api_mpegts_mux_grid },
|
||||
{ "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 },
|
||||
{ "mpegts/mux_sched/class", ACCESS_ANONYMOUS, api_idnode_class, (void*)&mpegts_mux_sched_class },
|
||||
{ "mpegts/mux_sched/grid", ACCESS_ANONYMOUS, api_idnode_grid, api_mpegts_mux_sched_grid },
|
||||
{ "mpegts/mux_sched/create", ACCESS_ANONYMOUS, api_mpegts_mux_sched_create, NULL },
|
||||
#if ENABLE_MPEGTS_DVB
|
||||
{ "dvb/orbitalpos/list", ACCESS_ADMIN, api_dvb_orbitalpos_list, NULL },
|
||||
{ "dvb/scanfile/list", ACCESS_ADMIN, api_dvb_scanfile_list, NULL },
|
||||
{ "dvb/scanfile/list", ACCESS_ANONYMOUS, api_dvb_scanfile_list, NULL },
|
||||
#endif
|
||||
{ NULL },
|
||||
};
|
||||
|
|
|
@ -1,110 +0,0 @@
|
|||
/*
|
||||
* tvheadend - API access to Stream Profile
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
#include "tvheadend.h"
|
||||
#include "access.h"
|
||||
#include "htsmsg.h"
|
||||
#include "api.h"
|
||||
#include "profile.h"
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
static int
|
||||
api_profile_list
|
||||
( access_t *perm, void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp )
|
||||
{
|
||||
profile_t *pro;
|
||||
htsmsg_t *l, *e;
|
||||
|
||||
l = htsmsg_create_list();
|
||||
pthread_mutex_lock(&global_lock);
|
||||
TAILQ_FOREACH(pro, &profiles, pro_link) {
|
||||
e = htsmsg_create_map();
|
||||
htsmsg_add_str(e, "key", idnode_uuid_as_str(&pro->pro_id));
|
||||
htsmsg_add_str(e, "val", profile_get_name(pro));
|
||||
htsmsg_add_msg(l, NULL, e);
|
||||
}
|
||||
pthread_mutex_unlock(&global_lock);
|
||||
*resp = htsmsg_create_map();
|
||||
htsmsg_add_msg(*resp, "entries", l);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
api_profile_builders
|
||||
( access_t *perm, void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp )
|
||||
{
|
||||
profile_build_t *pb;
|
||||
htsmsg_t *l, *e;
|
||||
|
||||
l = htsmsg_create_list();
|
||||
|
||||
pthread_mutex_lock(&global_lock);
|
||||
/* List of available builder classes */
|
||||
LIST_FOREACH(pb, &profile_builders, link)
|
||||
if ((e = idclass_serialize(pb->clazz)))
|
||||
htsmsg_add_msg(l, NULL, e);
|
||||
pthread_mutex_unlock(&global_lock);
|
||||
|
||||
/* Output */
|
||||
*resp = htsmsg_create_map();
|
||||
htsmsg_add_msg(*resp, "entries", l);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
api_profile_create
|
||||
( access_t *perm, void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp )
|
||||
{
|
||||
int err = 0;
|
||||
const char *clazz;
|
||||
htsmsg_t *conf;
|
||||
|
||||
if (!(clazz = htsmsg_get_str(args, "class")))
|
||||
return EINVAL;
|
||||
if (!(conf = htsmsg_get_map(args, "conf")))
|
||||
return EINVAL;
|
||||
htsmsg_set_str(conf, "class", clazz);
|
||||
|
||||
pthread_mutex_lock(&global_lock);
|
||||
if (profile_create(NULL, conf, 1) == NULL)
|
||||
err = -EINVAL;
|
||||
pthread_mutex_unlock(&global_lock);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/*
|
||||
* Init
|
||||
*/
|
||||
void
|
||||
api_profile_init ( void )
|
||||
{
|
||||
static api_hook_t ah[] = {
|
||||
{ "profile/list", ACCESS_ANONYMOUS, api_profile_list, NULL },
|
||||
{ "profile/class", ACCESS_ADMIN, api_idnode_class, (void*)&profile_class },
|
||||
{ "profile/builders", ACCESS_ADMIN, api_profile_builders, NULL },
|
||||
{ "profile/create", ACCESS_ADMIN, api_profile_create, NULL },
|
||||
{ NULL },
|
||||
};
|
||||
|
||||
api_register_all(ah);
|
||||
}
|
|
@ -29,7 +29,7 @@
|
|||
|
||||
static int
|
||||
api_mapper_start
|
||||
( access_t *perm, void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp )
|
||||
( void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp )
|
||||
{
|
||||
service_mapper_conf_t conf = { 0 };
|
||||
htsmsg_t *uuids;
|
||||
|
@ -52,7 +52,7 @@ api_mapper_start
|
|||
|
||||
static int
|
||||
api_mapper_stop
|
||||
( access_t *perm, void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp )
|
||||
( void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp )
|
||||
{
|
||||
pthread_mutex_lock(&global_lock);
|
||||
service_mapper_stop();
|
||||
|
@ -78,7 +78,7 @@ api_mapper_status_msg ( void )
|
|||
|
||||
static int
|
||||
api_mapper_status
|
||||
( access_t *perm, void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp )
|
||||
( void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp )
|
||||
{
|
||||
pthread_mutex_lock(&global_lock);
|
||||
*resp = api_mapper_status_msg();
|
||||
|
@ -129,7 +129,7 @@ api_service_streams_get_one ( elementary_stream_t *es, int use_filter )
|
|||
|
||||
static int
|
||||
api_service_streams
|
||||
( access_t *perm, void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp )
|
||||
( void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp )
|
||||
{
|
||||
const char *uuid;
|
||||
htsmsg_t *e, *st, *stf;
|
||||
|
@ -189,9 +189,9 @@ void api_service_init ( void )
|
|||
{ "service/mapper/start", ACCESS_ADMIN, api_mapper_start, NULL },
|
||||
{ "service/mapper/stop", ACCESS_ADMIN, api_mapper_stop, NULL },
|
||||
{ "service/mapper/status", ACCESS_ADMIN, api_mapper_status, NULL },
|
||||
{ "service/list", ACCESS_ADMIN, api_idnode_load_by_class,
|
||||
{ "service/list", ACCESS_ANONYMOUS, api_idnode_load_by_class,
|
||||
(void*)&service_class },
|
||||
{ "service/streams", ACCESS_ADMIN, api_service_streams, NULL },
|
||||
{ "service/streams", ACCESS_ANONYMOUS, api_service_streams, NULL },
|
||||
{ NULL },
|
||||
};
|
||||
|
||||
|
@ -199,4 +199,4 @@ void api_service_init ( void )
|
|||
}
|
||||
|
||||
|
||||
#endif /* __TVH_API_SERVICE_H__ */
|
||||
#endif /* __TVH_API_IDNODE_H__ */
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
|
||||
static int
|
||||
api_status_inputs
|
||||
( access_t *perm, void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp )
|
||||
( void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp )
|
||||
{
|
||||
int c = 0;
|
||||
htsmsg_t *l, *e;
|
||||
|
@ -37,10 +37,8 @@ api_status_inputs
|
|||
tvh_input_stream_t *st;
|
||||
tvh_input_stream_list_t stl = { 0 };
|
||||
|
||||
pthread_mutex_lock(&global_lock);
|
||||
TVH_INPUT_FOREACH(ti)
|
||||
ti->ti_get_streams(ti, &stl);
|
||||
pthread_mutex_unlock(&global_lock);
|
||||
|
||||
l = htsmsg_create_list();
|
||||
while ((st = LIST_FIRST(&stl))) {
|
||||
|
@ -61,7 +59,7 @@ api_status_inputs
|
|||
|
||||
static int
|
||||
api_status_subscriptions
|
||||
( access_t *perm, void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp )
|
||||
( void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp )
|
||||
{
|
||||
int c;
|
||||
htsmsg_t *l, *e;
|
||||
|
@ -69,13 +67,11 @@ api_status_subscriptions
|
|||
|
||||
l = htsmsg_create_list();
|
||||
c = 0;
|
||||
pthread_mutex_lock(&global_lock);
|
||||
LIST_FOREACH(ths, &subscriptions, ths_global_link) {
|
||||
e = subscription_create_msg(ths);
|
||||
htsmsg_add_msg(l, NULL, e);
|
||||
c++;
|
||||
}
|
||||
pthread_mutex_unlock(&global_lock);
|
||||
|
||||
*resp = htsmsg_create_map();
|
||||
htsmsg_add_msg(*resp, "entries", l);
|
||||
|
@ -86,7 +82,7 @@ api_status_subscriptions
|
|||
|
||||
static int
|
||||
api_status_connections
|
||||
( access_t *perm, void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp )
|
||||
( void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp )
|
||||
{
|
||||
pthread_mutex_lock(&global_lock);
|
||||
*resp = tcp_server_connections();
|
||||
|
@ -94,79 +90,12 @@ api_status_connections
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
api_connections_cancel
|
||||
( access_t *perm, void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp )
|
||||
{
|
||||
htsmsg_field_t *f;
|
||||
htsmsg_t *ids;
|
||||
uint32_t id;
|
||||
|
||||
if (!(f = htsmsg_field_find(args, "id")))
|
||||
return EINVAL;
|
||||
if (!(ids = htsmsg_field_get_list(f)))
|
||||
if (htsmsg_field_get_u32(f, &id))
|
||||
return EINVAL;
|
||||
|
||||
if (ids) {
|
||||
HTSMSG_FOREACH(f, ids) {
|
||||
if (htsmsg_field_get_u32(f, &id)) continue;
|
||||
if (!id) continue;
|
||||
pthread_mutex_lock(&global_lock);
|
||||
tcp_connection_cancel(id);
|
||||
pthread_mutex_unlock(&global_lock);
|
||||
}
|
||||
} else {
|
||||
pthread_mutex_lock(&global_lock);
|
||||
tcp_connection_cancel(id);
|
||||
pthread_mutex_unlock(&global_lock);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
input_clear_stats(const char *uuid)
|
||||
{
|
||||
tvh_input_instance_t *tii;
|
||||
|
||||
pthread_mutex_lock(&global_lock);
|
||||
if ((tii = tvh_input_instance_find_by_uuid(uuid)) != NULL)
|
||||
if (tii->tii_clear_stats)
|
||||
tii->tii_clear_stats(tii);
|
||||
pthread_mutex_unlock(&global_lock);
|
||||
}
|
||||
|
||||
static int
|
||||
api_status_input_clear_stats
|
||||
( access_t *perm, void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp )
|
||||
{
|
||||
htsmsg_field_t *f;
|
||||
htsmsg_t *ids;
|
||||
const char *uuid;
|
||||
|
||||
if (!(f = htsmsg_field_find(args, "uuid")))
|
||||
return EINVAL;
|
||||
if (!(ids = htsmsg_field_get_list(f))) {
|
||||
if ((uuid = htsmsg_field_get_str(f)) == NULL)
|
||||
return EINVAL;
|
||||
input_clear_stats(uuid);
|
||||
} else {
|
||||
HTSMSG_FOREACH(f, ids) {
|
||||
if ((uuid = htsmsg_field_get_str(f)) == NULL) continue;
|
||||
input_clear_stats(uuid);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void api_status_init ( void )
|
||||
{
|
||||
static api_hook_t ah[] = {
|
||||
{ "status/connections", ACCESS_ADMIN, api_status_connections, NULL },
|
||||
{ "status/subscriptions", ACCESS_ADMIN, api_status_subscriptions, NULL },
|
||||
{ "status/inputs", ACCESS_ADMIN, api_status_inputs, NULL },
|
||||
{ "status/inputclrstats", ACCESS_ADMIN, api_status_input_clear_stats, NULL },
|
||||
{ "connections/cancel", ACCESS_ADMIN, api_connections_cancel, NULL },
|
||||
{ NULL },
|
||||
};
|
||||
|
||||
|
|
|
@ -24,12 +24,6 @@ atomic_add(volatile int *ptr, int incr)
|
|||
return __sync_fetch_and_add(ptr, incr);
|
||||
}
|
||||
|
||||
static inline int
|
||||
atomic_dec(volatile int *ptr, int decr)
|
||||
{
|
||||
return __sync_fetch_and_sub(ptr, decr);
|
||||
}
|
||||
|
||||
static inline int
|
||||
atomic_exchange(volatile int *ptr, int new)
|
||||
{
|
||||
|
|
22
src/avahi.c
|
@ -56,7 +56,6 @@
|
|||
static AvahiEntryGroup *group = NULL;
|
||||
static char *name = NULL;
|
||||
static AvahiSimplePoll *avahi_asp = NULL;
|
||||
static const AvahiPoll *avahi_poll = NULL;
|
||||
|
||||
static void create_services(AvahiClient *c);
|
||||
|
||||
|
@ -113,7 +112,7 @@ static void
|
|||
create_services(AvahiClient *c)
|
||||
{
|
||||
char *n;
|
||||
char *path = NULL;
|
||||
char *path;
|
||||
int ret;
|
||||
assert(c);
|
||||
|
||||
|
@ -163,6 +162,8 @@ create_services(AvahiClient *c)
|
|||
path,
|
||||
NULL)) < 0) {
|
||||
|
||||
free(path);
|
||||
|
||||
if (ret == AVAHI_ERR_COLLISION)
|
||||
goto collision;
|
||||
|
||||
|
@ -181,7 +182,6 @@ create_services(AvahiClient *c)
|
|||
}
|
||||
}
|
||||
|
||||
free(path);
|
||||
return;
|
||||
|
||||
collision:
|
||||
|
@ -201,7 +201,7 @@ create_services(AvahiClient *c)
|
|||
return;
|
||||
|
||||
fail:
|
||||
free(path);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
@ -258,20 +258,14 @@ client_callback(AvahiClient *c, AvahiClientState state, void *userdata)
|
|||
static void *
|
||||
avahi_thread(void *aux)
|
||||
{
|
||||
AvahiClient *ac;
|
||||
char *name2;
|
||||
const AvahiPoll *ap = avahi_simple_poll_get(avahi_asp);
|
||||
|
||||
name = name2 = avahi_strdup("Tvheadend");
|
||||
name = avahi_strdup("Tvheadend");
|
||||
|
||||
ac = avahi_client_new(avahi_poll, AVAHI_CLIENT_NO_FAIL, client_callback, NULL, NULL);
|
||||
avahi_client_new(ap, AVAHI_CLIENT_NO_FAIL, client_callback, NULL, NULL);
|
||||
|
||||
while(avahi_simple_poll_iterate(avahi_asp, -1) == 0);
|
||||
|
||||
avahi_client_free(ac);
|
||||
|
||||
name = NULL;
|
||||
free(name2);
|
||||
|
||||
return NULL;
|
||||
|
||||
|
||||
|
@ -286,7 +280,6 @@ void
|
|||
avahi_init(void)
|
||||
{
|
||||
avahi_asp = avahi_simple_poll_new();
|
||||
avahi_poll = avahi_simple_poll_get(avahi_asp);
|
||||
tvhthread_create(&avahi_tid, NULL, avahi_thread, NULL);
|
||||
}
|
||||
|
||||
|
@ -296,5 +289,4 @@ avahi_done(void)
|
|||
avahi_simple_poll_quit(avahi_asp);
|
||||
pthread_kill(avahi_tid, SIGTERM);
|
||||
pthread_join(avahi_tid, NULL);
|
||||
avahi_simple_poll_free((AvahiSimplePoll *)avahi_poll);
|
||||
}
|
||||
|
|
973
src/bouquet.c
|
@ -1,973 +0,0 @@
|
|||
/*
|
||||
* tvheadend, bouquets
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
#include "tvheadend.h"
|
||||
#include "settings.h"
|
||||
#include "access.h"
|
||||
#include "bouquet.h"
|
||||
#include "service.h"
|
||||
#include "channels.h"
|
||||
#include "service_mapper.h"
|
||||
|
||||
bouquet_tree_t bouquets;
|
||||
|
||||
static uint64_t bouquet_get_channel_number0(bouquet_t *bq, service_t *t);
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
static int
|
||||
_bq_cmp(const void *a, const void *b)
|
||||
{
|
||||
return strcmp(((bouquet_t *)a)->bq_src ?: "", ((bouquet_t *)b)->bq_src ?: "");
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
bouquet_t *
|
||||
bouquet_create(const char *uuid, htsmsg_t *conf,
|
||||
const char *name, const char *src)
|
||||
{
|
||||
bouquet_t *bq, *bq2;
|
||||
int i;
|
||||
|
||||
lock_assert(&global_lock);
|
||||
|
||||
bq = calloc(1, sizeof(bouquet_t));
|
||||
bq->bq_services = idnode_set_create(1);
|
||||
bq->bq_active_services = idnode_set_create(1);
|
||||
|
||||
if (idnode_insert(&bq->bq_id, uuid, &bouquet_class, 0)) {
|
||||
if (uuid)
|
||||
tvherror("bouquet", "invalid uuid '%s'", uuid);
|
||||
free(bq);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (conf) {
|
||||
bq->bq_in_load = 1;
|
||||
idnode_load(&bq->bq_id, conf);
|
||||
bq->bq_in_load = 0;
|
||||
if (!htsmsg_get_bool(conf, "shield", &i) && i)
|
||||
bq->bq_shield = 1;
|
||||
}
|
||||
|
||||
if (name) {
|
||||
free(bq->bq_name);
|
||||
bq->bq_name = strdup(name);
|
||||
}
|
||||
|
||||
if (src) {
|
||||
free(bq->bq_src);
|
||||
bq->bq_src = strdup(src);
|
||||
}
|
||||
|
||||
bq2 = RB_INSERT_SORTED(&bouquets, bq, bq_link, _bq_cmp);
|
||||
assert(bq2 == NULL);
|
||||
|
||||
bq->bq_saveflag = 1;
|
||||
|
||||
return bq;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
static void
|
||||
bouquet_destroy(bouquet_t *bq)
|
||||
{
|
||||
if (!bq)
|
||||
return;
|
||||
|
||||
RB_REMOVE(&bouquets, bq, bq_link);
|
||||
idnode_unlink(&bq->bq_id);
|
||||
|
||||
idnode_set_free(bq->bq_active_services);
|
||||
idnode_set_free(bq->bq_services);
|
||||
assert(bq->bq_services_waiting == NULL);
|
||||
free((char *)bq->bq_chtag_waiting);
|
||||
free(bq->bq_name);
|
||||
free(bq->bq_src);
|
||||
free(bq->bq_comment);
|
||||
free(bq);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
void
|
||||
bouquet_destroy_by_service(service_t *t)
|
||||
{
|
||||
bouquet_t *bq;
|
||||
service_lcn_t *sl;
|
||||
|
||||
lock_assert(&global_lock);
|
||||
|
||||
RB_FOREACH(bq, &bouquets, bq_link)
|
||||
if (idnode_set_exists(bq->bq_services, &t->s_id))
|
||||
idnode_set_remove(bq->bq_services, &t->s_id);
|
||||
while ((sl = LIST_FIRST(&t->s_lcns)) != NULL) {
|
||||
LIST_REMOVE(sl, sl_link);
|
||||
free(sl);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
void
|
||||
bouquet_destroy_by_channel_tag(channel_tag_t *ct)
|
||||
{
|
||||
bouquet_t *bq;
|
||||
|
||||
lock_assert(&global_lock);
|
||||
|
||||
RB_FOREACH(bq, &bouquets, bq_link)
|
||||
if (bq->bq_chtag_ptr == ct)
|
||||
bq->bq_chtag_ptr = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
bouquet_t *
|
||||
bouquet_find_by_source(const char *name, const char *src, int create)
|
||||
{
|
||||
bouquet_t *bq;
|
||||
bouquet_t bqs;
|
||||
|
||||
assert(src);
|
||||
|
||||
lock_assert(&global_lock);
|
||||
|
||||
bqs.bq_src = (char *)src;
|
||||
bq = RB_FIND(&bouquets, &bqs, bq_link, _bq_cmp);
|
||||
if (bq) {
|
||||
if (name && *name && strcmp(name, bq->bq_name)) {
|
||||
tvhwarn("bouquet", "bouquet name '%s' changed to '%s'", bq->bq_name ?: "", name);
|
||||
free(bq->bq_name);
|
||||
bq->bq_name = strdup(name);
|
||||
bouquet_save(bq, 1);
|
||||
}
|
||||
return bq;
|
||||
}
|
||||
if (create && name) {
|
||||
bq = bouquet_create(NULL, NULL, name, src);
|
||||
tvhinfo("bouquet", "new bouquet '%s'", name);
|
||||
return bq;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
static channel_tag_t *
|
||||
bouquet_tag(bouquet_t *bq, int create)
|
||||
{
|
||||
channel_tag_t *ct;
|
||||
char buf[128];
|
||||
|
||||
assert(!bq->bq_in_load);
|
||||
if (bq->bq_chtag_waiting) {
|
||||
bq->bq_chtag_ptr = channel_tag_find_by_uuid(bq->bq_chtag_waiting);
|
||||
free((char *)bq->bq_chtag_waiting);
|
||||
bq->bq_chtag_waiting = NULL;
|
||||
}
|
||||
if (bq->bq_chtag_ptr)
|
||||
return bq->bq_chtag_ptr;
|
||||
snprintf(buf, sizeof(buf), "*** %s", bq->bq_name ?: "???");
|
||||
ct = channel_tag_find_by_name(buf, create);
|
||||
if (ct) {
|
||||
bq->bq_chtag_ptr = ct;
|
||||
bouquet_save(bq, 0);
|
||||
}
|
||||
return ct;
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
static int
|
||||
noname(const char *s)
|
||||
{
|
||||
if (!s)
|
||||
return 1;
|
||||
while (*s) {
|
||||
if (*s > ' ')
|
||||
return 0;
|
||||
s++;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
static void
|
||||
bouquet_map_channel(bouquet_t *bq, service_t *t)
|
||||
{
|
||||
channel_t *ch = NULL;
|
||||
channel_service_mapping_t *csm;
|
||||
|
||||
if (!t->s_enabled)
|
||||
return;
|
||||
if (!bq->bq_mapradio && service_is_radio(t))
|
||||
return;
|
||||
if (!bq->bq_mapnolcn &&
|
||||
(bq->bq_only_bq_lcn || service_get_channel_number(t) <= 0) &&
|
||||
bouquet_get_channel_number0(bq, t) <= 0)
|
||||
return;
|
||||
if (!bq->bq_mapnoname && noname(service_get_channel_name(t)))
|
||||
return;
|
||||
LIST_FOREACH(csm, &t->s_channels, csm_svc_link)
|
||||
if (csm->csm_chn->ch_bouquet == bq)
|
||||
break;
|
||||
if (!csm)
|
||||
ch = service_mapper_process(t, bq);
|
||||
else
|
||||
ch = csm->csm_chn;
|
||||
if (ch && bq->bq_chtag)
|
||||
channel_tag_map(ch, bouquet_tag(bq, 1));
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
void
|
||||
bouquet_add_service(bouquet_t *bq, service_t *s, uint64_t lcn, uint32_t tag)
|
||||
{
|
||||
service_lcn_t *tl;
|
||||
channel_service_mapping_t *csm;
|
||||
|
||||
lock_assert(&global_lock);
|
||||
|
||||
if (!bq->bq_enabled)
|
||||
return;
|
||||
|
||||
if (!idnode_set_exists(bq->bq_services, &s->s_id)) {
|
||||
tvhtrace("bouquet", "add service %s to %s", s->s_nicename, bq->bq_name ?: "<unknown>");
|
||||
idnode_set_add(bq->bq_services, &s->s_id, NULL);
|
||||
bq->bq_saveflag = 1;
|
||||
}
|
||||
|
||||
LIST_FOREACH(tl, &s->s_lcns, sl_link)
|
||||
if (tl->sl_bouquet == bq)
|
||||
break;
|
||||
|
||||
if (!tl) {
|
||||
tl = calloc(1, sizeof(*tl));
|
||||
tl->sl_bouquet = bq;
|
||||
LIST_INSERT_HEAD(&s->s_lcns, tl, sl_link);
|
||||
bq->bq_saveflag = 1;
|
||||
} else {
|
||||
if (tl->sl_lcn != lcn)
|
||||
bq->bq_saveflag = 1;
|
||||
}
|
||||
if (lcn != tl->sl_lcn) {
|
||||
tl->sl_lcn = lcn;
|
||||
LIST_FOREACH(csm, &s->s_channels, csm_svc_link)
|
||||
idnode_notify_simple(&csm->csm_chn->ch_id);
|
||||
}
|
||||
tl->sl_seen = 1;
|
||||
|
||||
if (lcn) {
|
||||
bq->bq_only_bq_lcn = 1;
|
||||
if (bq->bq_last_lcn < lcn)
|
||||
bq->bq_last_lcn = lcn;
|
||||
}
|
||||
|
||||
if (bq->bq_enabled && bq->bq_maptoch)
|
||||
bouquet_map_channel(bq, s);
|
||||
|
||||
if (!bq->bq_in_load &&
|
||||
!idnode_set_exists(bq->bq_active_services, &s->s_id))
|
||||
idnode_set_add(bq->bq_active_services, &s->s_id, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
static void
|
||||
bouquet_unmap_channel(bouquet_t *bq, service_t *t)
|
||||
{
|
||||
channel_service_mapping_t *csm, *csm_next;
|
||||
|
||||
csm = LIST_FIRST(&t->s_channels);
|
||||
while (csm) {
|
||||
csm_next = LIST_NEXT(csm, csm_svc_link);
|
||||
if (csm->csm_chn->ch_bouquet == bq) {
|
||||
tvhinfo("bouquet", "%s / %s: unmapped from %s",
|
||||
channel_get_name(csm->csm_chn), t->s_nicename,
|
||||
bq->bq_name ?: "<unknown>");
|
||||
channel_delete(csm->csm_chn, 1);
|
||||
}
|
||||
csm = csm_next;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
void
|
||||
bouquet_notify_service_enabled(service_t *t)
|
||||
{
|
||||
bouquet_t *bq;
|
||||
|
||||
lock_assert(&global_lock);
|
||||
|
||||
RB_FOREACH(bq, &bouquets, bq_link)
|
||||
if (idnode_set_exists(bq->bq_services, &t->s_id)) {
|
||||
if (!t->s_enabled)
|
||||
bouquet_unmap_channel(bq, t);
|
||||
else if (bq->bq_enabled && bq->bq_maptoch)
|
||||
bouquet_map_channel(bq, t);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
static void
|
||||
bouquet_remove_service(bouquet_t *bq, service_t *s)
|
||||
{
|
||||
tvhtrace("bouquet", "remove service %s from %s",
|
||||
s->s_nicename, bq->bq_name ?: "<unknown>");
|
||||
idnode_set_remove(bq->bq_services, &s->s_id);
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
void
|
||||
bouquet_completed(bouquet_t *bq, uint32_t seen)
|
||||
{
|
||||
idnode_set_t *remove;
|
||||
service_t *s;
|
||||
service_lcn_t *lcn, *lcn_next;
|
||||
size_t z;
|
||||
|
||||
if (!bq)
|
||||
return;
|
||||
|
||||
if (seen != bq->bq_services_seen) {
|
||||
bq->bq_services_seen = seen;
|
||||
bq->bq_saveflag = 1;
|
||||
}
|
||||
|
||||
tvhtrace("bouquet", "%s: completed: enabled=%d active=%zi old=%zi seen=%u",
|
||||
bq->bq_name ?: "", bq->bq_enabled, bq->bq_active_services->is_count,
|
||||
bq->bq_services->is_count, seen);
|
||||
|
||||
if (!bq->bq_enabled)
|
||||
goto save;
|
||||
|
||||
/* Add/Remove services */
|
||||
remove = idnode_set_create(0);
|
||||
for (z = 0; z < bq->bq_services->is_count; z++)
|
||||
if (!idnode_set_exists(bq->bq_active_services, bq->bq_services->is_array[z]))
|
||||
idnode_set_add(remove, bq->bq_services->is_array[z], NULL);
|
||||
for (z = 0; z < remove->is_count; z++)
|
||||
bouquet_remove_service(bq, (service_t *)remove->is_array[z]);
|
||||
idnode_set_free(remove);
|
||||
|
||||
/* Remove no longer used LCNs */
|
||||
for (z = 0; z < bq->bq_services->is_count; z++) {
|
||||
s = (service_t *)bq->bq_services->is_array[z];
|
||||
for (lcn = LIST_FIRST(&s->s_lcns); lcn; lcn = lcn_next) {
|
||||
lcn_next = LIST_NEXT(lcn, sl_link);
|
||||
if (lcn->sl_bouquet != bq) continue;
|
||||
if (!lcn->sl_seen) {
|
||||
LIST_REMOVE(lcn, sl_link);
|
||||
free(lcn);
|
||||
} else {
|
||||
lcn->sl_seen = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
idnode_set_free(bq->bq_active_services);
|
||||
bq->bq_active_services = idnode_set_create(1);
|
||||
|
||||
save:
|
||||
if (bq->bq_saveflag)
|
||||
bouquet_save(bq, 1);
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
void
|
||||
bouquet_map_to_channels(bouquet_t *bq)
|
||||
{
|
||||
service_t *t;
|
||||
size_t z;
|
||||
|
||||
for (z = 0; z < bq->bq_services->is_count; z++) {
|
||||
t = (service_t *)bq->bq_services->is_array[z];
|
||||
if (bq->bq_enabled && bq->bq_maptoch) {
|
||||
bouquet_map_channel(bq, t);
|
||||
} else {
|
||||
bouquet_unmap_channel(bq, t);
|
||||
}
|
||||
}
|
||||
|
||||
if (!bq->bq_enabled) {
|
||||
if (bq->bq_services->is_count) {
|
||||
idnode_set_free(bq->bq_services);
|
||||
bq->bq_services = idnode_set_create(1);
|
||||
bq->bq_saveflag = 1;
|
||||
}
|
||||
if (bq->bq_active_services->is_count) {
|
||||
idnode_set_free(bq->bq_active_services);
|
||||
bq->bq_active_services = idnode_set_create(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
void
|
||||
bouquet_notify_channels(bouquet_t *bq)
|
||||
{
|
||||
channel_service_mapping_t *csm;
|
||||
service_t *t;
|
||||
size_t z;
|
||||
|
||||
for (z = 0; z < bq->bq_services->is_count; z++) {
|
||||
t = (service_t *)bq->bq_services->is_array[z];
|
||||
LIST_FOREACH(csm, &t->s_channels, csm_svc_link)
|
||||
if (csm->csm_chn->ch_bouquet == bq)
|
||||
idnode_notify_simple(&csm->csm_chn->ch_id);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
static uint64_t
|
||||
bouquet_get_channel_number0(bouquet_t *bq, service_t *t)
|
||||
{
|
||||
service_lcn_t *tl;
|
||||
|
||||
LIST_FOREACH(tl, &t->s_lcns, sl_link)
|
||||
if (tl->sl_bouquet == bq)
|
||||
return (int64_t)tl->sl_lcn;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
uint64_t
|
||||
bouquet_get_channel_number(bouquet_t *bq, service_t *t)
|
||||
{
|
||||
int64_t r = bouquet_get_channel_number0(bq, t);
|
||||
if (r)
|
||||
return r;
|
||||
if (bq->bq_only_bq_lcn)
|
||||
return bq->bq_last_lcn + 10 * CHANNEL_SPLIT;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
static uint32_t
|
||||
bouquet_get_tag_number(bouquet_t *bq, service_t *t)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
void
|
||||
bouquet_save(bouquet_t *bq, int notify)
|
||||
{
|
||||
htsmsg_t *c = htsmsg_create_map();
|
||||
idnode_save(&bq->bq_id, c);
|
||||
hts_settings_save(c, "bouquet/%s", idnode_uuid_as_str(&bq->bq_id));
|
||||
if (bq->bq_shield)
|
||||
htsmsg_add_bool(c, "shield", 1);
|
||||
htsmsg_destroy(c);
|
||||
bq->bq_saveflag = 0;
|
||||
if (notify)
|
||||
idnode_notify_simple(&bq->bq_id);
|
||||
}
|
||||
|
||||
/* **************************************************************************
|
||||
* Class definition
|
||||
* **************************************************************************/
|
||||
|
||||
static void
|
||||
bouquet_class_save(idnode_t *self)
|
||||
{
|
||||
bouquet_save((bouquet_t *)self, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
bouquet_class_delete(idnode_t *self)
|
||||
{
|
||||
bouquet_t *bq = (bouquet_t *)self;
|
||||
|
||||
bq->bq_enabled = 0;
|
||||
bouquet_map_to_channels(bq);
|
||||
if (!bq->bq_shield) {
|
||||
hts_settings_remove("bouquet/%s", idnode_uuid_as_str(&bq->bq_id));
|
||||
bouquet_destroy(bq);
|
||||
} else {
|
||||
idnode_set_free(bq->bq_services);
|
||||
bq->bq_services = idnode_set_create(1);
|
||||
bouquet_save(bq, 1);
|
||||
}
|
||||
}
|
||||
|
||||
static const char *
|
||||
bouquet_class_get_title (idnode_t *self)
|
||||
{
|
||||
bouquet_t *bq = (bouquet_t *)self;
|
||||
|
||||
if (bq->bq_comment && bq->bq_comment[0] != '\0')
|
||||
return bq->bq_comment;
|
||||
return bq->bq_name ?: "";
|
||||
}
|
||||
|
||||
/* exported for others */
|
||||
htsmsg_t *
|
||||
bouquet_class_get_list(void *o)
|
||||
{
|
||||
htsmsg_t *m = htsmsg_create_map();
|
||||
htsmsg_add_str(m, "type", "api");
|
||||
htsmsg_add_str(m, "uri", "bouquet/list");
|
||||
htsmsg_add_str(m, "event", "bouquet");
|
||||
return m;
|
||||
}
|
||||
|
||||
static void
|
||||
bouquet_class_rescan_notify0 ( bouquet_t *bq )
|
||||
{
|
||||
void mpegts_mux_bouquet_rescan ( const char *src, const char *extra );
|
||||
mpegts_mux_bouquet_rescan(bq->bq_src, bq->bq_comment);
|
||||
bq->bq_rescan = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
bouquet_class_rescan_notify ( void *obj )
|
||||
{
|
||||
bouquet_t *bq = obj;
|
||||
|
||||
if (bq->bq_rescan)
|
||||
bouquet_class_rescan_notify0(bq);
|
||||
}
|
||||
|
||||
static void
|
||||
bouquet_class_enabled_notify ( void *obj )
|
||||
{
|
||||
bouquet_t *bq = obj;
|
||||
|
||||
if (bq->bq_enabled)
|
||||
bouquet_class_rescan_notify0(bq);
|
||||
bouquet_map_to_channels(bq);
|
||||
}
|
||||
|
||||
static void
|
||||
bouquet_class_maptoch_notify ( void *obj )
|
||||
{
|
||||
bouquet_map_to_channels((bouquet_t *)obj);
|
||||
}
|
||||
|
||||
static void
|
||||
bouquet_class_mapnolcn_notify ( void *obj )
|
||||
{
|
||||
bouquet_t *bq = obj;
|
||||
service_t *t;
|
||||
size_t z;
|
||||
|
||||
if (bq->bq_in_load)
|
||||
return;
|
||||
if (!bq->bq_mapnolcn && bq->bq_enabled && bq->bq_maptoch) {
|
||||
for (z = 0; z < bq->bq_services->is_count; z++) {
|
||||
t = (service_t *)bq->bq_services->is_array[z];
|
||||
if ((bq->bq_only_bq_lcn || service_get_channel_number(t) <= 0) &&
|
||||
bouquet_get_channel_number0(bq, t) <= 0)
|
||||
bouquet_unmap_channel(bq, t);
|
||||
}
|
||||
} else {
|
||||
bouquet_map_to_channels(bq);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
bouquet_class_mapnoname_notify ( void *obj )
|
||||
{
|
||||
bouquet_t *bq = obj;
|
||||
service_t *t;
|
||||
size_t z;
|
||||
|
||||
if (bq->bq_in_load)
|
||||
return;
|
||||
if (!bq->bq_mapnoname && bq->bq_enabled && bq->bq_maptoch) {
|
||||
for (z = 0; z < bq->bq_services->is_count; z++) {
|
||||
t = (service_t *)bq->bq_services->is_array[z];
|
||||
if (noname(service_get_channel_name(t)))
|
||||
bouquet_unmap_channel(bq, t);
|
||||
}
|
||||
} else {
|
||||
bouquet_map_to_channels(bq);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
bouquet_class_mapradio_notify ( void *obj )
|
||||
{
|
||||
bouquet_t *bq = obj;
|
||||
service_t *t;
|
||||
size_t z;
|
||||
|
||||
if (bq->bq_in_load)
|
||||
return;
|
||||
if (!bq->bq_mapradio && bq->bq_enabled && bq->bq_maptoch) {
|
||||
for (z = 0; z < bq->bq_services->is_count; z++) {
|
||||
t = (service_t *)bq->bq_services->is_array[z];
|
||||
if (service_is_radio(t))
|
||||
bouquet_unmap_channel(bq, t);
|
||||
}
|
||||
} else {
|
||||
bouquet_map_to_channels(bq);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
bouquet_class_chtag_notify ( void *obj )
|
||||
{
|
||||
bouquet_t *bq = obj;
|
||||
service_t *t;
|
||||
channel_service_mapping_t *csm;
|
||||
channel_tag_t *ct;
|
||||
size_t z;
|
||||
|
||||
if (bq->bq_in_load)
|
||||
return;
|
||||
if (!bq->bq_chtag && bq->bq_enabled && bq->bq_maptoch) {
|
||||
ct = bouquet_tag(bq, 0);
|
||||
if (!ct)
|
||||
return;
|
||||
for (z = 0; z < bq->bq_services->is_count; z++) {
|
||||
t = (service_t *)bq->bq_services->is_array[z];
|
||||
LIST_FOREACH(csm, &t->s_channels, csm_svc_link)
|
||||
if (csm->csm_chn->ch_bouquet == bq)
|
||||
break;
|
||||
if (csm)
|
||||
channel_tag_unmap(csm->csm_chn, ct);
|
||||
}
|
||||
} else {
|
||||
bouquet_map_to_channels(bq);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
bouquet_class_lcn_offset_notify ( void *obj )
|
||||
{
|
||||
if (((bouquet_t *)obj)->bq_in_load)
|
||||
return;
|
||||
bouquet_notify_channels((bouquet_t *)obj);
|
||||
}
|
||||
|
||||
static const void *
|
||||
bouquet_class_chtag_ref_get ( void *obj )
|
||||
{
|
||||
static const char *buf;
|
||||
bouquet_t *bq = obj;
|
||||
|
||||
if (bq->bq_chtag_ptr)
|
||||
buf = idnode_uuid_as_str(&bq->bq_chtag_ptr->ct_id);
|
||||
else
|
||||
buf = "";
|
||||
return &buf;
|
||||
}
|
||||
|
||||
static char *
|
||||
bouquet_class_chtag_ref_rend ( void *obj )
|
||||
{
|
||||
bouquet_t *bq = obj;
|
||||
if (bq->bq_chtag_ptr)
|
||||
return strdup(bq->bq_chtag_ptr->ct_name ?: "");
|
||||
else
|
||||
return strdup("");
|
||||
}
|
||||
|
||||
static int
|
||||
bouquet_class_chtag_ref_set ( void *obj, const void *p )
|
||||
{
|
||||
bouquet_t *bq = obj;
|
||||
|
||||
free((char *)bq->bq_chtag_waiting);
|
||||
bq->bq_chtag_waiting = NULL;
|
||||
if (bq->bq_in_load)
|
||||
bq->bq_chtag_waiting = strdup((const char *)p);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const void *
|
||||
bouquet_class_services_get ( void *obj )
|
||||
{
|
||||
htsmsg_t *m = htsmsg_create_map(), *e;
|
||||
bouquet_t *bq = obj;
|
||||
service_t *t;
|
||||
int64_t lcn;
|
||||
uint32_t tag;
|
||||
size_t z;
|
||||
|
||||
/* Add all */
|
||||
for (z = 0; z < bq->bq_services->is_count; z++) {
|
||||
t = (service_t *)bq->bq_services->is_array[z];
|
||||
e = htsmsg_create_map();
|
||||
if ((lcn = bouquet_get_channel_number0(bq, t)) != 0)
|
||||
htsmsg_add_s64(e, "lcn", lcn);
|
||||
if ((tag = bouquet_get_tag_number(bq, t)) != 0)
|
||||
htsmsg_add_s64(e, "tag", lcn);
|
||||
htsmsg_add_msg(m, idnode_uuid_as_str(&t->s_id), e);
|
||||
}
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
static char *
|
||||
bouquet_class_services_rend ( void *obj )
|
||||
{
|
||||
bouquet_t *bq = obj;
|
||||
char buf[32];
|
||||
snprintf(buf, sizeof(buf), "Services Count %zi", bq->bq_services->is_count);
|
||||
return strdup(buf);
|
||||
}
|
||||
|
||||
static int
|
||||
bouquet_class_services_set ( void *obj, const void *p )
|
||||
{
|
||||
bouquet_t *bq = obj;
|
||||
|
||||
if (bq->bq_services_waiting)
|
||||
htsmsg_destroy(bq->bq_services_waiting);
|
||||
bq->bq_services_waiting = NULL;
|
||||
if (bq->bq_in_load)
|
||||
bq->bq_services_waiting = htsmsg_copy((htsmsg_t *)p);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const void *
|
||||
bouquet_class_services_count_get ( void *obj )
|
||||
{
|
||||
static uint32_t u32;
|
||||
bouquet_t *bq = obj;
|
||||
|
||||
u32 = bq->bq_services->is_count;
|
||||
return &u32;
|
||||
}
|
||||
|
||||
const idclass_t bouquet_class = {
|
||||
.ic_class = "bouquet",
|
||||
.ic_caption = "Bouquet",
|
||||
.ic_event = "bouquet",
|
||||
.ic_perm_def = ACCESS_ADMIN,
|
||||
.ic_save = bouquet_class_save,
|
||||
.ic_get_title = bouquet_class_get_title,
|
||||
.ic_delete = bouquet_class_delete,
|
||||
.ic_properties = (const property_t[]){
|
||||
{
|
||||
.type = PT_BOOL,
|
||||
.id = "enabled",
|
||||
.name = "Enabled",
|
||||
.off = offsetof(bouquet_t, bq_enabled),
|
||||
.notify = bouquet_class_enabled_notify,
|
||||
},
|
||||
{
|
||||
.type = PT_BOOL,
|
||||
.id = "rescan",
|
||||
.name = "Rescan",
|
||||
.off = offsetof(bouquet_t, bq_rescan),
|
||||
.notify = bouquet_class_rescan_notify,
|
||||
.opts = PO_NOSAVE,
|
||||
},
|
||||
{
|
||||
.type = PT_BOOL,
|
||||
.id = "maptoch",
|
||||
.name = "Auto-Map to Channels",
|
||||
.off = offsetof(bouquet_t, bq_maptoch),
|
||||
.notify = bouquet_class_maptoch_notify,
|
||||
},
|
||||
{
|
||||
.type = PT_BOOL,
|
||||
.id = "mapnolcn",
|
||||
.name = "Map Zero Numbers",
|
||||
.off = offsetof(bouquet_t, bq_mapnolcn),
|
||||
.notify = bouquet_class_mapnolcn_notify,
|
||||
},
|
||||
{
|
||||
.type = PT_BOOL,
|
||||
.id = "mapnoname",
|
||||
.name = "Map No Name",
|
||||
.off = offsetof(bouquet_t, bq_mapnoname),
|
||||
.notify = bouquet_class_mapnoname_notify,
|
||||
},
|
||||
{
|
||||
.type = PT_BOOL,
|
||||
.id = "mapradio",
|
||||
.name = "Map Radio",
|
||||
.off = offsetof(bouquet_t, bq_mapradio),
|
||||
.notify = bouquet_class_mapradio_notify,
|
||||
},
|
||||
{
|
||||
.type = PT_BOOL,
|
||||
.id = "chtag",
|
||||
.name = "Create Tag",
|
||||
.off = offsetof(bouquet_t, bq_chtag),
|
||||
.notify = bouquet_class_chtag_notify,
|
||||
},
|
||||
{
|
||||
.type = PT_STR,
|
||||
.id = "chtag_ref",
|
||||
.name = "Channel Tag Reference",
|
||||
.get = bouquet_class_chtag_ref_get,
|
||||
.set = bouquet_class_chtag_ref_set,
|
||||
.rend = bouquet_class_chtag_ref_rend,
|
||||
.opts = PO_RDONLY | PO_HIDDEN,
|
||||
},
|
||||
{
|
||||
.type = PT_STR,
|
||||
.id = "name",
|
||||
.name = "Name",
|
||||
.off = offsetof(bouquet_t, bq_name),
|
||||
},
|
||||
{
|
||||
.type = PT_STR,
|
||||
.id = "source",
|
||||
.name = "Source",
|
||||
.off = offsetof(bouquet_t, bq_src),
|
||||
.opts = PO_RDONLY,
|
||||
},
|
||||
{
|
||||
.type = PT_STR,
|
||||
.islist = 1,
|
||||
.id = "services",
|
||||
.name = "Services",
|
||||
.get = bouquet_class_services_get,
|
||||
.set = bouquet_class_services_set,
|
||||
.rend = bouquet_class_services_rend,
|
||||
.opts = PO_RDONLY | PO_HIDDEN,
|
||||
},
|
||||
{
|
||||
.type = PT_U32,
|
||||
.id = "services_seen",
|
||||
.name = "# Seen Services",
|
||||
.off = offsetof(bouquet_t, bq_services_seen),
|
||||
.opts = PO_RDONLY,
|
||||
},
|
||||
{
|
||||
.type = PT_U32,
|
||||
.id = "services_count",
|
||||
.name = "# Services",
|
||||
.get = bouquet_class_services_count_get,
|
||||
.opts = PO_RDONLY | PO_NOSAVE,
|
||||
},
|
||||
{
|
||||
.type = PT_STR,
|
||||
.id = "comment",
|
||||
.name = "Comment",
|
||||
.off = offsetof(bouquet_t, bq_comment),
|
||||
},
|
||||
{
|
||||
.type = PT_U32,
|
||||
.id = "lcn_off",
|
||||
.name = "Channel Number Offset",
|
||||
.off = offsetof(bouquet_t, bq_lcn_offset),
|
||||
.notify = bouquet_class_lcn_offset_notify,
|
||||
},
|
||||
{}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
void
|
||||
bouquet_init(void)
|
||||
{
|
||||
htsmsg_t *c, *m;
|
||||
htsmsg_field_t *f;
|
||||
bouquet_t *bq;
|
||||
|
||||
RB_INIT(&bouquets);
|
||||
|
||||
/* Load */
|
||||
if ((c = hts_settings_load("bouquet")) != NULL) {
|
||||
HTSMSG_FOREACH(f, c) {
|
||||
if (!(m = htsmsg_field_get_map(f))) continue;
|
||||
bq = bouquet_create(f->hmf_name, m, NULL, NULL);
|
||||
bq->bq_saveflag = 0;
|
||||
}
|
||||
htsmsg_destroy(c);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
bouquet_service_resolve(void)
|
||||
{
|
||||
bouquet_t *bq;
|
||||
htsmsg_t *e;
|
||||
htsmsg_field_t *f;
|
||||
service_t *s;
|
||||
int64_t lcn;
|
||||
uint32_t tag;
|
||||
int saveflag;
|
||||
|
||||
lock_assert(&global_lock);
|
||||
|
||||
RB_FOREACH(bq, &bouquets, bq_link) {
|
||||
if (!bq->bq_services_waiting)
|
||||
continue;
|
||||
saveflag = bq->bq_saveflag;
|
||||
if (bq->bq_enabled) {
|
||||
HTSMSG_FOREACH(f, bq->bq_services_waiting) {
|
||||
if ((e = htsmsg_field_get_map(f)) == NULL) continue;
|
||||
lcn = htsmsg_get_s64_or_default(e, "lcn", 0);
|
||||
tag = htsmsg_get_u32_or_default(e, "tag", 0);
|
||||
s = service_find_by_identifier(f->hmf_name);
|
||||
if (s)
|
||||
bouquet_add_service(bq, s, lcn, tag);
|
||||
}
|
||||
}
|
||||
htsmsg_destroy(bq->bq_services_waiting);
|
||||
bq->bq_services_waiting = NULL;
|
||||
bq->bq_saveflag = saveflag;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
bouquet_done(void)
|
||||
{
|
||||
bouquet_t *bq;
|
||||
|
||||
pthread_mutex_lock(&global_lock);
|
||||
while ((bq = RB_FIRST(&bouquets)) != NULL)
|
||||
bouquet_destroy(bq);
|
||||
pthread_mutex_unlock(&global_lock);
|
||||
}
|
101
src/bouquet.h
|
@ -1,101 +0,0 @@
|
|||
/*
|
||||
* TV headend - Bouquets
|
||||
* 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 BOUQUET_H_
|
||||
#define BOUQUET_H_
|
||||
|
||||
#include "idnode.h"
|
||||
#include "htsmsg.h"
|
||||
#include "service.h"
|
||||
#include "channels.h"
|
||||
|
||||
typedef struct bouquet {
|
||||
idnode_t bq_id;
|
||||
RB_ENTRY(bouquet) bq_link;
|
||||
|
||||
int bq_saveflag;
|
||||
int bq_in_load;
|
||||
int bq_only_bq_lcn;
|
||||
time_t bq_updated;
|
||||
|
||||
int bq_shield;
|
||||
int bq_enabled;
|
||||
int bq_rescan;
|
||||
int bq_maptoch;
|
||||
int bq_mapnolcn;
|
||||
int bq_mapnoname;
|
||||
int bq_mapradio;
|
||||
int bq_chtag;
|
||||
channel_tag_t*bq_chtag_ptr;
|
||||
const char *bq_chtag_waiting;
|
||||
char *bq_name;
|
||||
char *bq_src;
|
||||
char *bq_comment;
|
||||
idnode_set_t *bq_services;
|
||||
idnode_set_t *bq_active_services;
|
||||
htsmsg_t *bq_services_waiting;
|
||||
uint32_t bq_services_seen;
|
||||
uint32_t bq_lcn_offset;
|
||||
uint64_t bq_last_lcn;
|
||||
|
||||
} bouquet_t;
|
||||
|
||||
typedef RB_HEAD(,bouquet) bouquet_tree_t;
|
||||
|
||||
extern bouquet_tree_t bouquets;
|
||||
|
||||
extern const idclass_t bouquet_class;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
||||
htsmsg_t * bouquet_class_get_list(void *o);
|
||||
|
||||
bouquet_t * bouquet_create(const char *uuid, htsmsg_t *conf,
|
||||
const char *name, const char *src);
|
||||
|
||||
void bouquet_destroy_by_service(service_t *t);
|
||||
void bouquet_destroy_by_channel_tag(channel_tag_t *ct);
|
||||
|
||||
void bouquet_notify_service_enabled(service_t *t);
|
||||
|
||||
static inline bouquet_t *
|
||||
bouquet_find_by_uuid(const char *uuid)
|
||||
{ return (bouquet_t *)idnode_find(uuid, &bouquet_class, NULL); }
|
||||
|
||||
bouquet_t * bouquet_find_by_source(const char *name, const char *src, int create);
|
||||
|
||||
void bouquet_map_to_channels(bouquet_t *bq);
|
||||
void bouquet_notify_channels(bouquet_t *bq);
|
||||
void bouquet_add_service(bouquet_t *bq, service_t *s, uint64_t lcn, uint32_t tag);
|
||||
void bouquet_completed(bouquet_t *bq, uint32_t seen);
|
||||
|
||||
uint64_t bouquet_get_channel_number(bouquet_t *bq, service_t *t);
|
||||
|
||||
void bouquet_save(bouquet_t *bq, int notify);
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
||||
void bouquet_init(void);
|
||||
void bouquet_service_resolve(void);
|
||||
void bouquet_done(void);
|
||||
|
||||
#endif /* BOUQUET_H_ */
|
792
src/channels.c
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* tvheadend, channel functions
|
||||
* Copyright (C) 2007 Andreas Öman
|
||||
* Copyright (C) 2007 Andreas Öman
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
@ -22,9 +22,6 @@
|
|||
#include "epg.h"
|
||||
#include "idnode.h"
|
||||
|
||||
struct access;
|
||||
struct bouquet;
|
||||
|
||||
RB_HEAD(channel_tree, channel);
|
||||
|
||||
LIST_HEAD(channel_tag_mapping_list, channel_tag_mapping);
|
||||
|
@ -43,18 +40,15 @@ typedef struct channel
|
|||
idnode_t ch_id;
|
||||
|
||||
RB_ENTRY(channel) ch_link;
|
||||
|
||||
|
||||
int ch_refcount;
|
||||
int ch_zombie;
|
||||
int ch_load;
|
||||
|
||||
/* Channel info */
|
||||
int ch_enabled;
|
||||
char *ch_name; // Note: do not access directly!
|
||||
int64_t ch_number;
|
||||
char *ch_icon;
|
||||
struct channel_tag_mapping_list ch_ctms;
|
||||
struct bouquet *ch_bouquet;
|
||||
char *ch_name; // Note: do not access directly!
|
||||
int ch_number;
|
||||
char *ch_icon;
|
||||
struct channel_tag_mapping_list ch_ctms;
|
||||
|
||||
/* Service/subscriptions */
|
||||
LIST_HEAD(, channel_service_mapping) ch_services;
|
||||
|
@ -68,7 +62,6 @@ typedef struct channel
|
|||
gtimer_t ch_epg_timer_head;
|
||||
gtimer_t ch_epg_timer_current;
|
||||
|
||||
int ch_epgauto;
|
||||
LIST_HEAD(,epggrab_channel_link) ch_epggrab;
|
||||
|
||||
/* DVR */
|
||||
|
@ -76,7 +69,6 @@ typedef struct channel
|
|||
int ch_dvr_extra_time_post;
|
||||
struct dvr_entry_list ch_dvrs;
|
||||
struct dvr_autorec_entry_list ch_autorecs;
|
||||
struct dvr_timerec_entry_list ch_timerecs;
|
||||
|
||||
} channel_t;
|
||||
|
||||
|
@ -85,28 +77,17 @@ typedef struct channel
|
|||
* Channel tag
|
||||
*/
|
||||
typedef struct channel_tag {
|
||||
|
||||
idnode_t ct_id;
|
||||
|
||||
TAILQ_ENTRY(channel_tag) ct_link;
|
||||
|
||||
int ct_enabled;
|
||||
uint32_t ct_index;
|
||||
int ct_internal;
|
||||
int ct_private;
|
||||
int ct_titled_icon;
|
||||
int ct_identifier;
|
||||
char *ct_name;
|
||||
char *ct_comment;
|
||||
char *ct_icon;
|
||||
|
||||
struct channel_tag_mapping_list ct_ctms;
|
||||
|
||||
struct dvr_autorec_entry_list ct_autorecs;
|
||||
|
||||
struct access_entry_list ct_accesses;
|
||||
|
||||
int ct_htsp_id;
|
||||
|
||||
} channel_tag_t;
|
||||
|
||||
/**
|
||||
|
@ -137,7 +118,6 @@ typedef struct channel_service_mapping {
|
|||
} channel_service_mapping_t;
|
||||
|
||||
extern const idclass_t channel_class;
|
||||
extern const idclass_t channel_tag_class;
|
||||
|
||||
void channel_init(void);
|
||||
void channel_done(void);
|
||||
|
@ -152,53 +132,29 @@ void channel_delete(channel_t *ch, int delconf);
|
|||
|
||||
channel_t *channel_find_by_name(const char *name);
|
||||
#define channel_find_by_uuid(u)\
|
||||
(channel_t*)idnode_find(u, &channel_class, NULL)
|
||||
(channel_t*)idnode_find(u, &channel_class)
|
||||
|
||||
channel_t *channel_find_by_id(uint32_t id);
|
||||
|
||||
channel_t *channel_find_by_number(const char *no);
|
||||
channel_t *channel_find_by_number(int no);
|
||||
|
||||
#define channel_find channel_find_by_uuid
|
||||
|
||||
htsmsg_t * channel_class_get_list(void *o);
|
||||
|
||||
int channel_set_tags_by_list ( channel_t *ch, htsmsg_t *tags );
|
||||
int channel_set_services_by_list ( channel_t *ch, htsmsg_t *svcs );
|
||||
|
||||
channel_tag_t *channel_tag_create(const char *uuid, htsmsg_t *conf);
|
||||
|
||||
channel_tag_t *channel_tag_find_by_name(const char *name, int create);
|
||||
|
||||
channel_tag_t *channel_tag_find_by_identifier(uint32_t id);
|
||||
|
||||
static inline channel_tag_t *channel_tag_find_by_uuid(const char *uuid)
|
||||
{ return (channel_tag_t*)idnode_find(uuid, &channel_tag_class, NULL); }
|
||||
|
||||
void channel_tag_save(channel_tag_t *ct);
|
||||
|
||||
htsmsg_t * channel_tag_class_get_list(void *o);
|
||||
|
||||
const char * channel_tag_get_icon(channel_tag_t *ct);
|
||||
|
||||
int channel_access(channel_t *ch, struct access *a, int disabled);
|
||||
|
||||
int channel_tag_map(channel_t *ch, channel_tag_t *ct);
|
||||
void channel_tag_unmap(channel_t *ch, channel_tag_t *ct);
|
||||
|
||||
int channel_tag_access(channel_tag_t *ct, struct access *a, int disabled);
|
||||
|
||||
void channel_save(channel_t *ch);
|
||||
|
||||
const char *channel_get_name ( channel_t *ch );
|
||||
int channel_set_name ( channel_t *ch, const char *name );
|
||||
int channel_set_name ( channel_t *ch, const char *s );
|
||||
|
||||
#define CHANNEL_SPLIT 1000000
|
||||
|
||||
static inline uint32_t channel_get_major ( int64_t chnum ) { return chnum / CHANNEL_SPLIT; }
|
||||
static inline uint32_t channel_get_minor ( int64_t chnum ) { return chnum % CHANNEL_SPLIT; }
|
||||
|
||||
int64_t channel_get_number ( channel_t *ch );
|
||||
int channel_set_number ( channel_t *ch, uint32_t major, uint32_t minor );
|
||||
int channel_get_number ( channel_t *ch );
|
||||
|
||||
const char *channel_get_icon ( channel_t *ch );
|
||||
int channel_set_icon ( channel_t *ch, const char *icon );
|
||||
|
|
862
src/config.c
|
@ -16,26 +16,19 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "tvheadend.h"
|
||||
#include "settings.h"
|
||||
#include "config.h"
|
||||
#include "uuid.h"
|
||||
#include "htsbuf.h"
|
||||
#include "spawn.h"
|
||||
#include "lock.h"
|
||||
#include "profile.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
/* *************************************************************************
|
||||
* Global data
|
||||
* ************************************************************************/
|
||||
|
||||
static htsmsg_t *config;
|
||||
static char config_lock[PATH_MAX];
|
||||
static int config_lock_fd;
|
||||
|
||||
/* *************************************************************************
|
||||
* Config migration
|
||||
|
@ -583,7 +576,6 @@ config_migrate_v6 ( void )
|
|||
if (!m) {
|
||||
m = htsmsg_create_map();
|
||||
htsmsg_add_msg(c, "mod_enabled", m);
|
||||
m = htsmsg_get_map(c, "mod_enabled");
|
||||
}
|
||||
htsmsg_add_u32(m, "eit", 1);
|
||||
htsmsg_add_u32(m, "uk_freesat", 1);
|
||||
|
@ -603,7 +595,7 @@ config_migrate_v6 ( void )
|
|||
htsmsg_t *xc, *ch;
|
||||
htsmsg_t *xchs = hts_settings_load("xmltv/channels");
|
||||
htsmsg_t *chs = hts_settings_load_r(1, "channel");
|
||||
if (chs) {
|
||||
if (xchs) {
|
||||
HTSMSG_FOREACH(f, chs) {
|
||||
if ((ch = htsmsg_get_map_by_field(f))) {
|
||||
if ((str = htsmsg_get_str(ch, "xmltv-channel"))) {
|
||||
|
@ -613,8 +605,6 @@ config_migrate_v6 ( void )
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (xchs) {
|
||||
HTSMSG_FOREACH(f, xchs) {
|
||||
if ((xc = htsmsg_get_map_by_field(f))) {
|
||||
hts_settings_save(xc, "epggrab/xmltv/channels/%s", f->hmf_name);
|
||||
|
@ -625,658 +615,6 @@ config_migrate_v6 ( void )
|
|||
htsmsg_destroy(c);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* v6 -> v7 : acesscontrol changes
|
||||
*/
|
||||
static void
|
||||
config_migrate_simple ( const char *dir, htsmsg_t *list,
|
||||
void (*modify)(htsmsg_t *record,
|
||||
uint32_t id,
|
||||
const char *uuid,
|
||||
const void *aux),
|
||||
const void *aux )
|
||||
{
|
||||
htsmsg_t *c, *e;
|
||||
htsmsg_field_t *f;
|
||||
tvh_uuid_t u;
|
||||
uint32_t index = 1, id;
|
||||
|
||||
if (!(c = hts_settings_load(dir)))
|
||||
return;
|
||||
|
||||
HTSMSG_FOREACH(f, c) {
|
||||
if (!(e = htsmsg_field_get_map(f))) continue;
|
||||
uuid_init_hex(&u, NULL);
|
||||
if (htsmsg_get_u32(e, "id", &id))
|
||||
id = 0;
|
||||
else if (list) {
|
||||
htsmsg_t *m = htsmsg_create_map();
|
||||
char buf[16];
|
||||
snprintf(buf, sizeof(buf), "%d", id);
|
||||
htsmsg_add_str(m, "id", buf);
|
||||
htsmsg_add_str(m, "uuid", u.hex);
|
||||
htsmsg_add_msg(list, NULL, m);
|
||||
}
|
||||
htsmsg_delete_field(e, "id");
|
||||
htsmsg_add_u32(e, "index", index++);
|
||||
if (modify)
|
||||
modify(e, id, u.hex, aux);
|
||||
hts_settings_save(e, "%s/%s", dir, u.hex);
|
||||
hts_settings_remove("%s/%s", dir, f->hmf_name);
|
||||
}
|
||||
|
||||
htsmsg_destroy(c);
|
||||
}
|
||||
|
||||
static void
|
||||
config_modify_acl( htsmsg_t *c, uint32_t id, const char *uuid, const void *aux )
|
||||
{
|
||||
uint32_t a, b;
|
||||
const char *s;
|
||||
if (htsmsg_get_u32(c, "adv_streaming", &a))
|
||||
if (!htsmsg_get_u32(c, "streaming", &b))
|
||||
htsmsg_add_u32(c, "adv_streaming", b);
|
||||
if ((s = htsmsg_get_str(c, "password")) != NULL) {
|
||||
char buf[256], result[300];
|
||||
snprintf(buf, sizeof(buf), "TVHeadend-Hide-%s", s);
|
||||
base64_encode(result, sizeof(result), (uint8_t *)buf, strlen(buf));
|
||||
htsmsg_add_str(c, "password2", result);
|
||||
htsmsg_delete_field(c, "password");
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
config_migrate_v7 ( void )
|
||||
{
|
||||
config_migrate_simple("accesscontrol", NULL, config_modify_acl, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
config_modify_tag( htsmsg_t *c, uint32_t id, const char *uuid, const void *aux )
|
||||
{
|
||||
htsmsg_t *ch = (htsmsg_t *)aux;
|
||||
htsmsg_t *e, *m, *t;
|
||||
htsmsg_field_t *f, *f2;
|
||||
uint32_t u32;
|
||||
|
||||
htsmsg_delete_field(c, "index");
|
||||
|
||||
if (ch == NULL || uuid == NULL)
|
||||
return;
|
||||
|
||||
HTSMSG_FOREACH(f, ch) {
|
||||
if (!(e = htsmsg_field_get_map(f))) continue;
|
||||
m = htsmsg_get_list(e, "tags");
|
||||
if (m == NULL)
|
||||
continue;
|
||||
t = htsmsg_get_list(e, "tags_new");
|
||||
HTSMSG_FOREACH(f2, m) {
|
||||
if (!htsmsg_field_get_u32(f2, &u32) && u32 == id) {
|
||||
if (t == NULL) {
|
||||
t = htsmsg_create_list();
|
||||
htsmsg_add_msg(e, "tags_new", t);
|
||||
t = htsmsg_get_list(e, "tags_new");
|
||||
}
|
||||
if (t)
|
||||
htsmsg_add_str(t, NULL, uuid);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
config_migrate_v8 ( void )
|
||||
{
|
||||
htsmsg_t *ch, *e, *m;
|
||||
htsmsg_field_t *f;
|
||||
|
||||
ch = hts_settings_load_r(1, "channel");
|
||||
config_migrate_simple("channeltags", NULL, config_modify_tag, ch);
|
||||
if (ch == NULL)
|
||||
return;
|
||||
HTSMSG_FOREACH(f, ch) {
|
||||
if (!(e = htsmsg_field_get_map(f))) continue;
|
||||
htsmsg_delete_field(e, "tags");
|
||||
m = htsmsg_get_list(e, "tags_new");
|
||||
if (m) {
|
||||
htsmsg_add_msg(e, "tags", htsmsg_copy(m));
|
||||
htsmsg_delete_field(e, "tags_new");
|
||||
}
|
||||
hts_settings_save(e, "channel/%s", f->hmf_name);
|
||||
}
|
||||
htsmsg_destroy(ch);
|
||||
}
|
||||
|
||||
static void
|
||||
config_modify_autorec( htsmsg_t *c, uint32_t id, const char *uuid, const void *aux )
|
||||
{
|
||||
uint32_t u32;
|
||||
htsmsg_delete_field(c, "index");
|
||||
if (!htsmsg_get_u32(c, "approx_time", &u32)) {
|
||||
htsmsg_delete_field(c, "approx_time");
|
||||
if (u32 != 0)
|
||||
htsmsg_add_u32(c, "start", u32);
|
||||
else
|
||||
htsmsg_add_str(c, "start", "");
|
||||
}
|
||||
if (!htsmsg_get_u32(c, "contenttype", &u32)) {
|
||||
htsmsg_delete_field(c, "contenttype");
|
||||
htsmsg_add_u32(c, "content_type", u32 / 16);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
config_modify_dvr_log( htsmsg_t *c, uint32_t id, const char *uuid, const void *aux )
|
||||
{
|
||||
const htsmsg_t *list = aux;
|
||||
const char *chname = htsmsg_get_str(c, "channelname");
|
||||
const char *chuuid = htsmsg_get_str(c, "channel");
|
||||
htsmsg_t *e;
|
||||
htsmsg_field_t *f;
|
||||
tvh_uuid_t uuid0;
|
||||
const char *s1;
|
||||
uint32_t u32;
|
||||
|
||||
htsmsg_delete_field(c, "index");
|
||||
if (chname == NULL || (chuuid != NULL && uuid_init_bin(&uuid0, chuuid))) {
|
||||
chname = strdup(chuuid ?: "");
|
||||
htsmsg_delete_field(c, "channelname");
|
||||
htsmsg_delete_field(c, "channel");
|
||||
htsmsg_add_str(c, "channelname", chname);
|
||||
free((char *)chname);
|
||||
if (!htsmsg_get_u32(c, "contenttype", &u32)) {
|
||||
htsmsg_delete_field(c, "contenttype");
|
||||
htsmsg_add_u32(c, "content_type", u32 / 16);
|
||||
}
|
||||
}
|
||||
if ((s1 = htsmsg_get_str(c, "autorec")) != NULL) {
|
||||
s1 = strdup(s1);
|
||||
htsmsg_delete_field(c, "autorec");
|
||||
if (s1 != NULL) {
|
||||
HTSMSG_FOREACH(f, list) {
|
||||
if (!(e = htsmsg_field_get_map(f))) continue;
|
||||
if (strcmp(s1, htsmsg_get_str(e, "id") ?: "") == 0) {
|
||||
const char *s2 = htsmsg_get_str(e, "uuid");
|
||||
if (s2)
|
||||
htsmsg_add_str(c, "autorec", s2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
free((char *)s1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
config_migrate_v9 ( void )
|
||||
{
|
||||
htsmsg_t *list = htsmsg_create_list();
|
||||
htsmsg_t *c, *e;
|
||||
htsmsg_field_t *f;
|
||||
tvh_uuid_t u;
|
||||
|
||||
config_migrate_simple("autorec", list, config_modify_autorec, NULL);
|
||||
config_migrate_simple("dvr/log", NULL, config_modify_dvr_log, list);
|
||||
htsmsg_destroy(list);
|
||||
|
||||
if ((c = hts_settings_load("dvr")) != NULL) {
|
||||
/* step 1: only "config" */
|
||||
HTSMSG_FOREACH(f, c) {
|
||||
if (!(e = htsmsg_field_get_map(f))) continue;
|
||||
if (strcmp(f->hmf_name, "config")) continue;
|
||||
htsmsg_add_str(e, "name", f->hmf_name + 6);
|
||||
uuid_init_hex(&u, NULL);
|
||||
hts_settings_remove("dvr/%s", f->hmf_name);
|
||||
hts_settings_save(e, "dvr/config/%s", u.hex);
|
||||
}
|
||||
/* step 2: reset (without "config") */
|
||||
HTSMSG_FOREACH(f, c) {
|
||||
if (!(e = htsmsg_field_get_map(f))) continue;
|
||||
if (strcmp(f->hmf_name, "config") == 0) continue;
|
||||
if (strncmp(f->hmf_name, "config", 6)) continue;
|
||||
htsmsg_add_str(e, "name", f->hmf_name + 6);
|
||||
uuid_init_hex(&u, NULL);
|
||||
hts_settings_remove("dvr/%s", f->hmf_name);
|
||||
hts_settings_save(e, "dvr/config/%s", u.hex);
|
||||
}
|
||||
htsmsg_destroy(c);
|
||||
}
|
||||
|
||||
if ((c = hts_settings_load("autorec")) != NULL) {
|
||||
HTSMSG_FOREACH(f, c) {
|
||||
if (!(e = htsmsg_field_get_map(f))) continue;
|
||||
hts_settings_remove("autorec/%s", f->hmf_name);
|
||||
hts_settings_save(e, "dvr/autorec/%s", f->hmf_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
config_migrate_move ( const char *dir,
|
||||
const char *newdir )
|
||||
{
|
||||
htsmsg_t *c, *e;
|
||||
htsmsg_field_t *f;
|
||||
|
||||
if (!(c = hts_settings_load(dir)))
|
||||
return;
|
||||
|
||||
HTSMSG_FOREACH(f, c) {
|
||||
if (!(e = htsmsg_field_get_map(f))) continue;
|
||||
hts_settings_save(e, "%s/%s", newdir, f->hmf_name);
|
||||
hts_settings_remove("%s/%s", dir, f->hmf_name);
|
||||
}
|
||||
|
||||
htsmsg_destroy(c);
|
||||
}
|
||||
|
||||
static void
|
||||
config_migrate_v10 ( void )
|
||||
{
|
||||
config_migrate_move("channel", "channel/config");
|
||||
config_migrate_move("channeltags", "channel/tag");
|
||||
}
|
||||
|
||||
static const char *
|
||||
config_find_uuid( htsmsg_t *map, const char *name, const char *value )
|
||||
{
|
||||
htsmsg_t *e;
|
||||
htsmsg_field_t *f;
|
||||
const char *s;
|
||||
|
||||
if (!map || !name || !value)
|
||||
return NULL;
|
||||
HTSMSG_FOREACH(f, map) {
|
||||
if (!(e = htsmsg_field_get_map(f))) continue;
|
||||
if ((s = htsmsg_get_str(e, name)) != NULL) {
|
||||
if (!strcmp(s, value))
|
||||
return f->hmf_name;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
config_modify_acl_dvallcfg( htsmsg_t *c, htsmsg_t *dvr_config )
|
||||
{
|
||||
uint32_t a;
|
||||
const char *username, *uuid;
|
||||
|
||||
username = htsmsg_get_str(c, "username");
|
||||
if (!htsmsg_get_u32(c, "dvallcfg", &a))
|
||||
if (a == 0) {
|
||||
uuid = username ? config_find_uuid(dvr_config, "name", username) : NULL;
|
||||
if (uuid)
|
||||
htsmsg_add_str(c, "dvr_config", uuid);
|
||||
}
|
||||
htsmsg_delete_field(c, "dvallcfg");
|
||||
}
|
||||
|
||||
static void
|
||||
config_modify_acl_tag_only( htsmsg_t *c, htsmsg_t *channel_tag )
|
||||
{
|
||||
uint32_t a;
|
||||
const char *username, *tag, *uuid;
|
||||
|
||||
username = htsmsg_get_str(c, "username");
|
||||
tag = htsmsg_get_str(c, "channel_tag");
|
||||
if (!tag || tag[0] == '\0')
|
||||
tag = NULL;
|
||||
if (tag == NULL && !htsmsg_get_u32(c, "tag_only", &a)) {
|
||||
if (a) {
|
||||
uuid = username ? config_find_uuid(channel_tag, "name", username) : NULL;
|
||||
if (uuid)
|
||||
htsmsg_add_str(c, "channel_tag", uuid);
|
||||
}
|
||||
} else if (tag) {
|
||||
uuid = config_find_uuid(channel_tag, "name", tag);
|
||||
if (uuid) {
|
||||
htsmsg_delete_field(c, "channel_tag");
|
||||
htsmsg_add_str(c, "channel_tag", uuid);
|
||||
}
|
||||
}
|
||||
htsmsg_delete_field(c, "tag_only");
|
||||
}
|
||||
|
||||
static void
|
||||
config_modify_dvr_config_name( htsmsg_t *c, htsmsg_t *dvr_config )
|
||||
{
|
||||
const char *config_name, *uuid;
|
||||
|
||||
config_name = htsmsg_get_str(c, "config_name");
|
||||
uuid = config_name ? config_find_uuid(dvr_config, "name", config_name) : NULL;
|
||||
htsmsg_delete_field(c, "config_name");
|
||||
htsmsg_add_str(c, "config_name", uuid ?: "");
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
config_migrate_v11 ( void )
|
||||
{
|
||||
htsmsg_t *dvr_config;
|
||||
htsmsg_t *channel_tag;
|
||||
htsmsg_t *c, *e;
|
||||
htsmsg_field_t *f;
|
||||
|
||||
dvr_config = hts_settings_load("dvr/config");
|
||||
channel_tag = hts_settings_load("channel/tag");
|
||||
|
||||
if ((c = hts_settings_load("accesscontrol")) != NULL) {
|
||||
HTSMSG_FOREACH(f, c) {
|
||||
if (!(e = htsmsg_field_get_map(f))) continue;
|
||||
config_modify_acl_dvallcfg(e, dvr_config);
|
||||
config_modify_acl_tag_only(e, channel_tag);
|
||||
}
|
||||
htsmsg_destroy(c);
|
||||
}
|
||||
|
||||
if ((c = hts_settings_load("dvr/log")) != NULL) {
|
||||
HTSMSG_FOREACH(f, c) {
|
||||
if (!(e = htsmsg_field_get_map(f))) continue;
|
||||
config_modify_dvr_config_name(e, dvr_config);
|
||||
}
|
||||
htsmsg_destroy(c);
|
||||
}
|
||||
|
||||
htsmsg_destroy(channel_tag);
|
||||
htsmsg_destroy(dvr_config);
|
||||
}
|
||||
|
||||
static void
|
||||
config_modify_caclient( htsmsg_t *c, uint32_t id, const char *uuid, const void *aux )
|
||||
{
|
||||
uint32_t u;
|
||||
|
||||
htsmsg_delete_field(c, "index");
|
||||
htsmsg_delete_field(c, "connected");
|
||||
htsmsg_add_str(c, "class", aux);
|
||||
if (!htsmsg_get_u32(c, "oscam", &u)) {
|
||||
htsmsg_delete_field(c, "oscam");
|
||||
htsmsg_add_u32(c, "mode", u);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
config_migrate_v12 ( void )
|
||||
{
|
||||
htsmsg_t *c, *e;
|
||||
htsmsg_field_t *f;
|
||||
|
||||
config_migrate_simple("cwc", NULL, config_modify_caclient, "caclient_cwc");
|
||||
config_migrate_simple("capmt", NULL, config_modify_caclient, "caclient_capmt");
|
||||
|
||||
if ((c = hts_settings_load("cwc")) != NULL) {
|
||||
HTSMSG_FOREACH(f, c) {
|
||||
if (!(e = htsmsg_field_get_map(f))) continue;
|
||||
hts_settings_remove("cwc/%s", f->hmf_name);
|
||||
hts_settings_save(e, "caclient/%s", f->hmf_name);
|
||||
}
|
||||
}
|
||||
if ((c = hts_settings_load("capmt")) != NULL) {
|
||||
HTSMSG_FOREACH(f, c) {
|
||||
if (!(e = htsmsg_field_get_map(f))) continue;
|
||||
hts_settings_remove("capmt/%s", f->hmf_name);
|
||||
hts_settings_save(e, "caclient/%s", f->hmf_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
config_migrate_v13 ( void )
|
||||
{
|
||||
htsmsg_t *c, *e;
|
||||
htsmsg_field_t *f;
|
||||
int i;
|
||||
|
||||
if ((c = hts_settings_load("dvr/config")) != NULL) {
|
||||
HTSMSG_FOREACH(f, c) {
|
||||
if (!(e = htsmsg_field_get_map(f))) continue;
|
||||
if (!htsmsg_get_bool(e, "container", &i)) {
|
||||
htsmsg_delete_field(e, "container");
|
||||
if (i == 1)
|
||||
htsmsg_add_str(e, "profile", "matroska");
|
||||
else if (i == 4)
|
||||
htsmsg_add_str(e, "profile", "pass");
|
||||
}
|
||||
htsmsg_delete_field(e, "rewrite-pat");
|
||||
htsmsg_delete_field(e, "rewrite-pmt");
|
||||
hts_settings_save(e, "dvr/config/%s", f->hmf_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static const char *
|
||||
config_migrate_v14_codec(int i)
|
||||
{
|
||||
switch (i) {
|
||||
case 1: return "mpeg2video";
|
||||
case 2: return "mp2";
|
||||
case 3: return "libx264";
|
||||
case 4: return "ac3";
|
||||
case 8: return "aac";
|
||||
case 13: return "libvpx";
|
||||
case 14: return "libvorbis";
|
||||
default: return "";
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
config_migrate_v14 ( void )
|
||||
{
|
||||
htsmsg_t *c, *e;
|
||||
htsmsg_field_t *f;
|
||||
int i;
|
||||
|
||||
if ((c = hts_settings_load("profile")) != NULL) {
|
||||
HTSMSG_FOREACH(f, c) {
|
||||
if (!(e = htsmsg_field_get_map(f))) continue;
|
||||
if (!htsmsg_get_s32(e, "vcodec", &i)) {
|
||||
htsmsg_delete_field(e, "vcodec");
|
||||
htsmsg_set_str(e, "vcodec", config_migrate_v14_codec(i));
|
||||
}
|
||||
if (!htsmsg_get_s32(e, "acodec", &i)) {
|
||||
htsmsg_delete_field(e, "acodec");
|
||||
htsmsg_set_str(e, "acodec", config_migrate_v14_codec(i));
|
||||
}
|
||||
if (!htsmsg_get_s32(e, "scodec", &i))
|
||||
htsmsg_delete_field(e, "scodec");
|
||||
hts_settings_save(e, "profile/%s", f->hmf_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
config_migrate_v15 ( void )
|
||||
{
|
||||
htsmsg_t *c, *e;
|
||||
htsmsg_field_t *f;
|
||||
int i;
|
||||
|
||||
if ((c = hts_settings_load("profile")) != NULL) {
|
||||
HTSMSG_FOREACH(f, c) {
|
||||
if (!(e = htsmsg_field_get_map(f))) continue;
|
||||
if (htsmsg_get_s32(e, "timeout", &i)) {
|
||||
htsmsg_set_s32(e, "timeout", 5);
|
||||
hts_settings_save(e, "profile/%s", f->hmf_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
config_dvr_autorec_start_set(const char *s, int *tm)
|
||||
{
|
||||
int t;
|
||||
|
||||
if(s == NULL || s[0] == '\0' || !isdigit(s[0]))
|
||||
t = -1;
|
||||
else if(strchr(s, ':') != NULL)
|
||||
// formatted time string - convert
|
||||
t = (atoi(s) * 60) + atoi(s + 3);
|
||||
else {
|
||||
t = atoi(s);
|
||||
}
|
||||
if (t >= 24 * 60)
|
||||
t = -1;
|
||||
if (t != *tm) {
|
||||
*tm = t;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
config_modify_dvrauto( htsmsg_t *c )
|
||||
{
|
||||
int tm = -1, tw = -1;
|
||||
char buf[16];
|
||||
|
||||
if (config_dvr_autorec_start_set(htsmsg_get_str(c, "start"), &tm) > 0 && tm >= 0) {
|
||||
tm -= 15;
|
||||
if (tm < 0)
|
||||
tm += 24 * 60;
|
||||
tw = tm + 30;
|
||||
if (tw >= 24 * 60)
|
||||
tw -= 24 * 60;
|
||||
snprintf(buf, sizeof(buf), "%02d:%02d", tm / 60, tm % 60);
|
||||
htsmsg_set_str(c, "start", buf);
|
||||
snprintf(buf, sizeof(buf), "%02d:%02d", tw / 60, tw % 60);
|
||||
htsmsg_set_str(c, "start_window", buf);
|
||||
} else {
|
||||
htsmsg_delete_field(c, "start");
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
config_migrate_v16 ( void )
|
||||
{
|
||||
htsmsg_t *c, *e;
|
||||
htsmsg_field_t *f;
|
||||
|
||||
if ((c = hts_settings_load("dvr/autorec")) != NULL) {
|
||||
HTSMSG_FOREACH(f, c) {
|
||||
if (!(e = htsmsg_field_get_map(f))) continue;
|
||||
config_modify_dvrauto(e);
|
||||
hts_settings_save(e, "dvr/autorec/%s", f->hmf_name);
|
||||
}
|
||||
htsmsg_destroy(c);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
config_migrate_v17 ( void )
|
||||
{
|
||||
htsmsg_t *c, *e;
|
||||
htsmsg_field_t *f;
|
||||
int i, p;
|
||||
|
||||
if ((c = hts_settings_load("profile")) != NULL) {
|
||||
HTSMSG_FOREACH(f, c) {
|
||||
if (!(e = htsmsg_field_get_map(f))) continue;
|
||||
if (htsmsg_get_s32(e, "priority", &i)) {
|
||||
p = PROFILE_SPRIO_NORMAL;
|
||||
if (strcmp(htsmsg_get_str(e, "name") ?: "", "htsp") == 0)
|
||||
p = PROFILE_SPRIO_IMPORTANT;
|
||||
htsmsg_set_s32(e, "priority", p);
|
||||
hts_settings_save(e, "profile/%s", f->hmf_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Perform backup
|
||||
*/
|
||||
static void
|
||||
dobackup(const char *oldver)
|
||||
{
|
||||
char outfile[PATH_MAX], cwd[PATH_MAX];
|
||||
const char *argv[] = {
|
||||
"/usr/bin/tar", "cjf", outfile,
|
||||
"--exclude", "backup", "--exclude", "epggrab/*.sock",
|
||||
".", NULL
|
||||
};
|
||||
const char *root = hts_settings_get_root();
|
||||
char errtxt[128];
|
||||
const char **arg;
|
||||
pid_t pid;
|
||||
int code;
|
||||
|
||||
assert(root);
|
||||
|
||||
tvhinfo("config", "backup: migrating config from %s (running %s)",
|
||||
oldver, tvheadend_version);
|
||||
|
||||
if (getcwd(cwd, sizeof(cwd)) == NULL) {
|
||||
tvherror("config", "unable to get the current working directory");
|
||||
goto fatal;
|
||||
}
|
||||
|
||||
if (!access("/bin/tar", X_OK))
|
||||
argv[0] = "/bin/tar";
|
||||
else if (!access("/usr/bin/tar", X_OK))
|
||||
argv[0] = "/usr/bin/tar";
|
||||
else if (!access("/usr/local/bin/tar", X_OK))
|
||||
argv[0] = "/usr/local/bin/tar";
|
||||
else {
|
||||
tvherror("config", "unable to find tar program");
|
||||
goto fatal;
|
||||
}
|
||||
|
||||
snprintf(outfile, sizeof(outfile), "%s/backup", root);
|
||||
if (makedirs(outfile, 0700, -1, -1))
|
||||
goto fatal;
|
||||
if (chdir(root)) {
|
||||
tvherror("config", "unable to find directory '%s'", root);
|
||||
goto fatal;
|
||||
}
|
||||
|
||||
snprintf(outfile, sizeof(outfile), "%s/backup/%s.tar.bz2",
|
||||
root, oldver);
|
||||
tvhinfo("config", "backup: running, output file %s", outfile);
|
||||
|
||||
if (spawnv(argv[0], (void *)argv, &pid, 1, 1)) {
|
||||
code = -ENOENT;
|
||||
} else {
|
||||
while ((code = spawn_reap(pid, errtxt, sizeof(errtxt))) == -EAGAIN)
|
||||
usleep(20000);
|
||||
if (code == -ECHILD)
|
||||
code = 0;
|
||||
}
|
||||
|
||||
if (code) {
|
||||
htsbuf_queue_t q;
|
||||
char *s;
|
||||
htsbuf_queue_init(&q, 0);
|
||||
for (arg = argv; *arg; arg++) {
|
||||
htsbuf_append(&q, *arg, strlen(*arg));
|
||||
if (arg[1])
|
||||
htsbuf_append(&q, " ", 1);
|
||||
}
|
||||
s = htsbuf_to_string(&q);
|
||||
tvherror("config", "command '%s' returned error code %d", s, code);
|
||||
tvherror("config", "executed in directory '%s'", root);
|
||||
tvherror("config", "please, do not report this as an error, you may use --nobackup option");
|
||||
tvherror("config", "... or run the above command in the printed directory");
|
||||
tvherror("config", "... using the same user/group as for the tvheadend executable");
|
||||
tvherror("config", "... to check the reason for the unfinished backup");
|
||||
free(s);
|
||||
htsbuf_queue_flush(&q);
|
||||
goto fatal;
|
||||
}
|
||||
|
||||
if (chdir(cwd)) {
|
||||
tvherror("config", "unable to change directory to '%s'", cwd);
|
||||
goto fatal;
|
||||
}
|
||||
return;
|
||||
|
||||
fatal:
|
||||
tvherror("config", "backup: fatal error");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Migration table
|
||||
*/
|
||||
|
@ -1287,36 +625,18 @@ static const config_migrate_t config_migrate_table[] = {
|
|||
config_migrate_v3, // Re-run due to bug in previous version of function
|
||||
config_migrate_v5,
|
||||
config_migrate_v6,
|
||||
config_migrate_v7,
|
||||
config_migrate_v8,
|
||||
config_migrate_v9,
|
||||
config_migrate_v10,
|
||||
config_migrate_v11,
|
||||
config_migrate_v12,
|
||||
config_migrate_v13,
|
||||
config_migrate_v14,
|
||||
config_migrate_v15,
|
||||
config_migrate_v16,
|
||||
config_migrate_v17
|
||||
};
|
||||
|
||||
/*
|
||||
* Perform migrations (if required)
|
||||
*/
|
||||
static int
|
||||
config_migrate ( int backup )
|
||||
static void
|
||||
config_migrate ( void )
|
||||
{
|
||||
uint32_t v;
|
||||
const char *s;
|
||||
|
||||
/* Get the current version */
|
||||
v = htsmsg_get_u32_or_default(config, "version", 0);
|
||||
s = htsmsg_get_str(config, "fullversion") ?: "unknown";
|
||||
|
||||
if (backup && strcmp(s, tvheadend_version))
|
||||
dobackup(s);
|
||||
else
|
||||
backup = 0;
|
||||
|
||||
/* Attempt to auto-detect versions prior to v2 */
|
||||
if (!v) {
|
||||
|
@ -1327,11 +647,8 @@ config_migrate ( int backup )
|
|||
}
|
||||
|
||||
/* No changes required */
|
||||
if (v == ARRAY_SIZE(config_migrate_table)) {
|
||||
if (backup)
|
||||
goto update;
|
||||
return 0;
|
||||
}
|
||||
if (v == ARRAY_SIZE(config_migrate_table))
|
||||
return;
|
||||
|
||||
/* Run migrations */
|
||||
for ( ; v < ARRAY_SIZE(config_migrate_table); v++) {
|
||||
|
@ -1340,80 +657,32 @@ config_migrate ( int backup )
|
|||
}
|
||||
|
||||
/* Update */
|
||||
update:
|
||||
htsmsg_set_u32(config, "version", v);
|
||||
htsmsg_set_str(config, "fullversion", tvheadend_version);
|
||||
config_save();
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
static void
|
||||
config_check_one ( const char *dir )
|
||||
{
|
||||
htsmsg_t *c, *e;
|
||||
htsmsg_field_t *f;
|
||||
|
||||
if (!(c = hts_settings_load(dir)))
|
||||
return;
|
||||
|
||||
HTSMSG_FOREACH(f, c) {
|
||||
if (!(e = htsmsg_field_get_map(f))) continue;
|
||||
if (strlen(f->hmf_name) != UUID_HEX_SIZE - 1) {
|
||||
tvherror("START", "filename %s/%s/%s is invalid", hts_settings_get_root(), dir, f->hmf_name);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
htsmsg_destroy(c);
|
||||
}
|
||||
|
||||
/*
|
||||
* Perform a simple check for UUID files
|
||||
*/
|
||||
static void
|
||||
config_check ( void )
|
||||
{
|
||||
config_check_one("accesscontrol");
|
||||
config_check_one("channel/config");
|
||||
config_check_one("channel/tag");
|
||||
config_check_one("dvr/config");
|
||||
config_check_one("dvr/log");
|
||||
config_check_one("dvr/autorec");
|
||||
config_check_one("esfilter");
|
||||
}
|
||||
|
||||
/* **************************************************************************
|
||||
* Initialisation / Shutdown / Saving
|
||||
* *************************************************************************/
|
||||
|
||||
static int config_newcfg = 0;
|
||||
|
||||
void
|
||||
config_boot ( const char *path, gid_t gid, uid_t uid )
|
||||
config_init ( const char *path )
|
||||
{
|
||||
struct stat st;
|
||||
char buf[1024];
|
||||
htsmsg_t *config2;
|
||||
|
||||
config = htsmsg_create_map();
|
||||
const char *homedir = getenv("HOME");
|
||||
int new = 0;
|
||||
|
||||
/* Generate default */
|
||||
if (!path) {
|
||||
const char *homedir = getenv("HOME");
|
||||
if (homedir == NULL) {
|
||||
tvherror("START", "environment variable HOME is not set");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
snprintf(buf, sizeof(buf), "%s/.hts/tvheadend", homedir);
|
||||
path = buf;
|
||||
}
|
||||
|
||||
/* Ensure directory exists */
|
||||
if (stat(path, &st)) {
|
||||
config_newcfg = 1;
|
||||
if (makedirs(path, 0700, gid, uid)) {
|
||||
new = 1;
|
||||
if (makedirs(path, 0700)) {
|
||||
tvhwarn("START", "failed to create settings directory %s,"
|
||||
" settings will not be saved", path);
|
||||
return;
|
||||
|
@ -1432,56 +701,27 @@ config_boot ( const char *path, gid_t gid, uid_t uid )
|
|||
/* Configure settings routines */
|
||||
hts_settings_init(path);
|
||||
|
||||
/* Lock it */
|
||||
hts_settings_buildpath(config_lock, sizeof(config_lock), ".lock");
|
||||
if ((config_lock_fd = file_lock(config_lock, 3)) < 0)
|
||||
exit(78); /* config error */
|
||||
|
||||
if (chown(config_lock, uid, gid))
|
||||
tvhwarn("config", "unable to chown lock file %s UID:%d GID:%d", config_lock, uid, gid);
|
||||
|
||||
/* Load global settings */
|
||||
config2 = hts_settings_load("config");
|
||||
if (!config2) {
|
||||
config = hts_settings_load("config");
|
||||
if (!config) {
|
||||
tvhlog(LOG_DEBUG, "config", "no configuration, loading defaults");
|
||||
} else {
|
||||
htsmsg_destroy(config);
|
||||
config = config2;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
config_init ( int backup )
|
||||
{
|
||||
const char *path = hts_settings_get_root();
|
||||
|
||||
if (path == NULL || access(path, R_OK | W_OK)) {
|
||||
tvhwarn("START", "configuration path %s is not r/w"
|
||||
" for UID:%d GID:%d [e=%s],"
|
||||
" settings will not be saved",
|
||||
path, getuid(), getgid(), strerror(errno));
|
||||
return;
|
||||
config = htsmsg_create_map();
|
||||
}
|
||||
|
||||
/* Store version number */
|
||||
if (config_newcfg) {
|
||||
if (new) {
|
||||
htsmsg_set_u32(config, "version", ARRAY_SIZE(config_migrate_table));
|
||||
htsmsg_set_str(config, "fullversion", tvheadend_version);
|
||||
config_save();
|
||||
|
||||
/* Perform migrations */
|
||||
} else {
|
||||
if (config_migrate(backup))
|
||||
config_check();
|
||||
config_migrate();
|
||||
}
|
||||
tvhinfo("config", "loaded");
|
||||
}
|
||||
|
||||
void config_done ( void )
|
||||
{
|
||||
/* note: tvhlog is inactive !!! */
|
||||
htsmsg_destroy(config);
|
||||
file_unlock(config_lock, config_lock_fd);
|
||||
}
|
||||
|
||||
void config_save ( void )
|
||||
|
@ -1498,14 +738,8 @@ htsmsg_t *config_get_all ( void )
|
|||
return htsmsg_copy(config);
|
||||
}
|
||||
|
||||
const char *
|
||||
config_get_str ( const char *fld )
|
||||
{
|
||||
return htsmsg_get_str(config, fld);
|
||||
}
|
||||
|
||||
int
|
||||
config_set_str ( const char *fld, const char *val )
|
||||
static int
|
||||
_config_set_str ( const char *fld, const char *val )
|
||||
{
|
||||
const char *c = htsmsg_get_str(config, fld);
|
||||
if (!c || strcmp(c, val)) {
|
||||
|
@ -1516,26 +750,6 @@ config_set_str ( const char *fld, const char *val )
|
|||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
config_get_int ( const char *fld, int deflt )
|
||||
{
|
||||
return htsmsg_get_s32_or_default(config, fld, deflt);
|
||||
}
|
||||
|
||||
int
|
||||
config_set_int ( const char *fld, int val )
|
||||
{
|
||||
const char *c = htsmsg_get_str(config, fld);
|
||||
char buf[16];
|
||||
snprintf(buf, sizeof(buf), "%d", val);
|
||||
if (!c || strcmp(c, buf)) {
|
||||
if (c) htsmsg_delete_field(config, fld);
|
||||
htsmsg_add_s32(config, fld, val);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char *config_get_language ( void )
|
||||
{
|
||||
return htsmsg_get_str(config, "language");
|
||||
|
@ -1543,7 +757,7 @@ const char *config_get_language ( void )
|
|||
|
||||
int config_set_language ( const char *lang )
|
||||
{
|
||||
return config_set_str("language", lang);
|
||||
return _config_set_str("language", lang);
|
||||
}
|
||||
|
||||
const char *config_get_muxconfpath ( void )
|
||||
|
@ -1553,37 +767,5 @@ const char *config_get_muxconfpath ( void )
|
|||
|
||||
int config_set_muxconfpath ( const char *path )
|
||||
{
|
||||
return config_set_str("muxconfpath", path);
|
||||
}
|
||||
|
||||
int config_get_prefer_picon ( void )
|
||||
{
|
||||
int b = 0;
|
||||
htsmsg_get_bool(config, "prefer_picon", &b);
|
||||
return b;
|
||||
}
|
||||
|
||||
int config_set_prefer_picon ( const char *str )
|
||||
{
|
||||
return config_set_str("prefer_picon", str);
|
||||
}
|
||||
|
||||
const char *config_get_chicon_path ( void )
|
||||
{
|
||||
return htsmsg_get_str(config, "chiconpath");
|
||||
}
|
||||
|
||||
int config_set_chicon_path ( const char *str )
|
||||
{
|
||||
return config_set_str("chiconpath", str);
|
||||
}
|
||||
|
||||
const char *config_get_picon_path ( void )
|
||||
{
|
||||
return htsmsg_get_str(config, "piconpath");
|
||||
}
|
||||
|
||||
int config_set_picon_path ( const char *str )
|
||||
{
|
||||
return config_set_str("piconpath", str);
|
||||
return _config_set_str("muxconfpath", path);
|
||||
}
|
||||
|
|
21
src/config.h
|
@ -21,21 +21,14 @@
|
|||
#ifndef __TVH_CONFIG__H__
|
||||
#define __TVH_CONFIG__H__
|
||||
|
||||
#include <unistd.h>
|
||||
#include "htsmsg.h"
|
||||
|
||||
void config_boot ( const char *path, gid_t gid, uid_t uid );
|
||||
void config_init ( int backup );
|
||||
void config_init ( const char *path );
|
||||
void config_done ( void );
|
||||
void config_save ( void );
|
||||
|
||||
htsmsg_t *config_get_all ( void );
|
||||
|
||||
const char *config_get_str ( const char *fld );
|
||||
int config_set_str ( const char *fld, const char *val );
|
||||
int config_get_int ( const char *fld, int dflt );
|
||||
int config_set_int ( const char *fld, int val );
|
||||
|
||||
const char *config_get_muxconfpath ( void );
|
||||
int config_set_muxconfpath ( const char *str )
|
||||
__attribute__((warn_unused_result));
|
||||
|
@ -44,16 +37,4 @@ const char *config_get_language ( void );
|
|||
int config_set_language ( const char *str )
|
||||
__attribute__((warn_unused_result));
|
||||
|
||||
int config_get_prefer_picon ( void );
|
||||
int config_set_prefer_picon ( const char *str )
|
||||
__attribute__((warn_unused_result));
|
||||
|
||||
const char *config_get_chicon_path ( void );
|
||||
int config_set_chicon_path ( const char *str )
|
||||
__attribute__((warn_unused_result));
|
||||
|
||||
const char *config_get_picon_path ( void );
|
||||
int config_set_picon_path ( const char *str )
|
||||
__attribute__((warn_unused_result));
|
||||
|
||||
#endif /* __TVH_CONFIG__H__ */
|
||||
|
|
10
src/cron.c
|
@ -17,17 +17,13 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "build.h"
|
||||
#include "cron.h"
|
||||
|
||||
#include <time.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#if !defined(PLATFORM_FREEBSD)
|
||||
#include <alloca.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Parse value
|
||||
|
@ -36,8 +32,6 @@ static int
|
|||
cron_parse_val ( const char *str, const char **key, int *v )
|
||||
{
|
||||
int i = 0;
|
||||
if (!str)
|
||||
return 0;
|
||||
if (key) {
|
||||
while (key[i]) {
|
||||
if (!strncasecmp(str, key[i], strlen(key[i]))) {
|
||||
|
@ -75,7 +69,7 @@ cron_parse_field
|
|||
if ((sn - off) >= bits || (en - off) >= bits || mn > bits)
|
||||
return 1;
|
||||
if (en < 0) en = sn;
|
||||
if (mn <= 0) mn = 1;
|
||||
if (mn < 0) mn = 1;
|
||||
while (sn <= en) {
|
||||
if ( (sn % mn) == 0 )
|
||||
val |= (0x1ULL << (sn - off));
|
||||
|
@ -178,7 +172,7 @@ cron_multi_set ( const char *str )
|
|||
if (line[0] != '#')
|
||||
if (!cron_set(&cron, line)) {
|
||||
count++;
|
||||
cm2 = realloc(cm, sizeof(*cm) + sizeof(cron) * count);
|
||||
cm2 = realloc(cm, sizeof(cm) + sizeof(cron) * count);
|
||||
if (cm2 == NULL) {
|
||||
free(cm);
|
||||
return NULL;
|
||||
|
|
482
src/dbus.c
|
@ -1,482 +0,0 @@
|
|||
/*
|
||||
* DBUS interface
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
#include <time.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include <signal.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include <dbus-1.0/dbus/dbus.h>
|
||||
|
||||
#include "tvheadend.h"
|
||||
#include "tvhpoll.h"
|
||||
#include "subscriptions.h"
|
||||
#include "dbus.h"
|
||||
|
||||
|
||||
typedef struct dbus_sig {
|
||||
TAILQ_ENTRY(dbus_sig) link;
|
||||
char *obj_name;
|
||||
char *sig_name;
|
||||
htsmsg_t *msg;
|
||||
} dbus_sig_t;
|
||||
|
||||
typedef struct dbus_rpc {
|
||||
LIST_ENTRY(dbus_rpc) link;
|
||||
char *call_name;
|
||||
void *opaque;
|
||||
int64_t (*rpc_s64)(void *opaque, const char *path, int64_t value);
|
||||
char *(*rpc_str)(void *opaque, const char *path, char *value);
|
||||
} dbus_rpc_t;
|
||||
|
||||
TAILQ_HEAD(dbus_signal_queue, dbus_sig);
|
||||
LIST_HEAD(dbus_rpc_list, dbus_rpc);
|
||||
static struct dbus_signal_queue dbus_signals;
|
||||
static struct dbus_rpc_list dbus_rpcs;
|
||||
static th_pipe_t dbus_pipe;
|
||||
static pthread_mutex_t dbus_lock;
|
||||
static int dbus_running;
|
||||
static int dbus_session;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
void
|
||||
dbus_emit_signal(const char *obj_name, const char *sig_name, htsmsg_t *msg)
|
||||
{
|
||||
dbus_sig_t *ds;
|
||||
int unused __attribute__((unused));
|
||||
size_t l;
|
||||
|
||||
if (!dbus_running) {
|
||||
htsmsg_destroy(msg);
|
||||
return;
|
||||
}
|
||||
ds = calloc(1, sizeof(dbus_sig_t));
|
||||
l = strlen(obj_name);
|
||||
ds->obj_name = malloc(l + 15);
|
||||
strcpy(ds->obj_name, "/org/tvheadend");
|
||||
strcpy(ds->obj_name + 14, obj_name);
|
||||
ds->sig_name = strdup(sig_name);
|
||||
ds->msg = msg;
|
||||
pthread_mutex_lock(&dbus_lock);
|
||||
TAILQ_INSERT_TAIL(&dbus_signals, ds, link);
|
||||
pthread_mutex_unlock(&dbus_lock);
|
||||
unused = write(dbus_pipe.wr, "s", 1); /* do not wait here - no tvh_write() */
|
||||
}
|
||||
|
||||
void
|
||||
dbus_emit_signal_str(const char *obj_name, const char *sig_name, const char *value)
|
||||
{
|
||||
htsmsg_t *l = htsmsg_create_list();
|
||||
htsmsg_add_str(l, NULL, value);
|
||||
dbus_emit_signal(obj_name, sig_name, l);
|
||||
}
|
||||
|
||||
void
|
||||
dbus_emit_signal_s64(const char *obj_name, const char *sig_name, int64_t value)
|
||||
{
|
||||
htsmsg_t *l = htsmsg_create_list();
|
||||
htsmsg_add_s64(l, NULL, value);
|
||||
dbus_emit_signal(obj_name, sig_name, l);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
static void
|
||||
dbus_from_htsmsg(htsmsg_t *msg, DBusMessageIter *args)
|
||||
{
|
||||
htsmsg_field_t *f;
|
||||
|
||||
TAILQ_FOREACH(f, &msg->hm_fields, hmf_link) {
|
||||
switch(f->hmf_type) {
|
||||
case HMF_STR:
|
||||
dbus_message_iter_append_basic(args, DBUS_TYPE_STRING, &f->hmf_str);
|
||||
break;
|
||||
case HMF_S64:
|
||||
dbus_message_iter_append_basic(args, DBUS_TYPE_INT64, &f->hmf_s64);
|
||||
break;
|
||||
case HMF_BOOL:
|
||||
dbus_message_iter_append_basic(args, DBUS_TYPE_BOOLEAN, &f->hmf_bool);
|
||||
break;
|
||||
case HMF_DBL:
|
||||
dbus_message_iter_append_basic(args, DBUS_TYPE_DOUBLE, &f->hmf_dbl);
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
static DBusConnection *
|
||||
dbus_create_session(const char *name)
|
||||
{
|
||||
DBusConnection *conn;
|
||||
DBusError err;
|
||||
int ret;
|
||||
|
||||
dbus_error_init(&err);
|
||||
|
||||
conn = dbus_bus_get_private(dbus_session ? DBUS_BUS_SESSION : DBUS_BUS_SYSTEM, &err);
|
||||
if (dbus_error_is_set(&err)) {
|
||||
tvherror("dbus", "Connection error: %s", err.message);
|
||||
dbus_error_free(&err);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ret = dbus_bus_request_name(conn, name, DBUS_NAME_FLAG_REPLACE_EXISTING, &err);
|
||||
if (dbus_error_is_set(&err)) {
|
||||
tvherror("dbus", "Name error: %s", err.message);
|
||||
dbus_error_free(&err);
|
||||
dbus_connection_close(conn);
|
||||
dbus_connection_unref(conn);
|
||||
return NULL;
|
||||
}
|
||||
if (DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER != ret) {
|
||||
tvherror("dbus", "Not primary owner");
|
||||
dbus_connection_close(conn);
|
||||
dbus_connection_unref(conn);
|
||||
return NULL;
|
||||
}
|
||||
return conn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a signal
|
||||
*/
|
||||
static int
|
||||
dbus_send_signal(DBusConnection *conn, const char *obj_name,
|
||||
const char *if_name, const char *sig_name,
|
||||
htsmsg_t *value)
|
||||
{
|
||||
DBusMessage *msg;
|
||||
DBusMessageIter args;
|
||||
|
||||
msg = dbus_message_new_signal(obj_name, if_name, sig_name);
|
||||
if (msg == NULL) {
|
||||
tvherror("dbus", "Unable to create signal %s %s %s",
|
||||
obj_name, if_name, sig_name);
|
||||
dbus_connection_unref(conn);
|
||||
return -1;
|
||||
}
|
||||
dbus_message_iter_init_append(msg, &args);
|
||||
dbus_from_htsmsg(value, &args);
|
||||
if (!dbus_connection_send(conn, msg, NULL)) {
|
||||
tvherror("dbus", "Unable to send signal %s %s %s",
|
||||
obj_name, if_name, sig_name);
|
||||
dbus_message_unref(msg);
|
||||
dbus_connection_unref(conn);
|
||||
return -1;
|
||||
}
|
||||
dbus_connection_flush(conn);
|
||||
dbus_message_unref(msg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Simple ping (alive) RPC, just return the string
|
||||
*/
|
||||
static void
|
||||
dbus_reply_to_ping(DBusMessage *msg, DBusConnection *conn)
|
||||
{
|
||||
DBusMessageIter args;
|
||||
DBusMessage *reply;
|
||||
char *param;
|
||||
|
||||
if (!dbus_message_iter_init(msg, &args))
|
||||
return;
|
||||
if (DBUS_TYPE_STRING != dbus_message_iter_get_arg_type(&args))
|
||||
return;
|
||||
dbus_message_iter_get_basic(&args, ¶m);
|
||||
reply = dbus_message_new_method_return(msg);
|
||||
dbus_message_iter_init_append(reply, &args);
|
||||
dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, ¶m);
|
||||
dbus_connection_send(conn, reply, NULL);
|
||||
dbus_connection_flush(conn);
|
||||
dbus_message_unref(reply);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the subscription postpone delay
|
||||
*/
|
||||
static void
|
||||
dbus_reply_to_rpc(dbus_rpc_t *rpc, DBusMessage *msg, DBusConnection *conn)
|
||||
{
|
||||
DBusMessageIter args;
|
||||
DBusMessage *reply;
|
||||
const char *path;
|
||||
int64_t param_s64;
|
||||
char *param_str;
|
||||
|
||||
path = dbus_message_get_path(msg);
|
||||
if (path == NULL)
|
||||
return;
|
||||
if (strncmp(path, "/org/tvheadend/", 15))
|
||||
return;
|
||||
path += 14;
|
||||
if (!dbus_message_iter_init(msg, &args))
|
||||
return;
|
||||
if (rpc->rpc_s64) {
|
||||
if (DBUS_TYPE_INT64 != dbus_message_iter_get_arg_type(&args))
|
||||
return;
|
||||
dbus_message_iter_get_basic(&args, ¶m_s64);
|
||||
param_s64 = rpc->rpc_s64(rpc->opaque, path, param_s64);
|
||||
reply = dbus_message_new_method_return(msg);
|
||||
dbus_message_iter_init_append(reply, &args);
|
||||
dbus_message_iter_append_basic(&args, DBUS_TYPE_INT64, ¶m_s64);
|
||||
} else if (rpc->rpc_str) {
|
||||
if (DBUS_TYPE_STRING != dbus_message_iter_get_arg_type(&args))
|
||||
return;
|
||||
dbus_message_iter_get_basic(&args, ¶m_str);
|
||||
param_str = rpc->rpc_str(rpc->opaque, path, param_str);
|
||||
reply = dbus_message_new_method_return(msg);
|
||||
dbus_message_iter_init_append(reply, &args);
|
||||
dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, ¶m_str);
|
||||
free(param_str);
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
dbus_connection_send(conn, reply, NULL);
|
||||
dbus_connection_flush(conn);
|
||||
dbus_message_unref(reply);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
void
|
||||
dbus_register_rpc_s64(const char *call_name, void *opaque,
|
||||
int64_t (*fcn)(void *, const char *, int64_t))
|
||||
{
|
||||
dbus_rpc_t *rpc = calloc(1, sizeof(*rpc));
|
||||
rpc->call_name = strdup(call_name);
|
||||
rpc->rpc_s64 = fcn;
|
||||
rpc->opaque = opaque;
|
||||
pthread_mutex_lock(&dbus_lock);
|
||||
LIST_INSERT_HEAD(&dbus_rpcs, rpc, link);
|
||||
pthread_mutex_unlock(&dbus_lock);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
void
|
||||
dbus_register_rpc_str(const char *call_name, void *opaque,
|
||||
char *(*fcn)(void *, const char *, char *))
|
||||
{
|
||||
dbus_rpc_t *rpc = calloc(1, sizeof(*rpc));
|
||||
rpc->call_name = strdup(call_name);
|
||||
rpc->rpc_str = fcn;
|
||||
rpc->opaque = opaque;
|
||||
pthread_mutex_lock(&dbus_lock);
|
||||
LIST_INSERT_HEAD(&dbus_rpcs, rpc, link);
|
||||
pthread_mutex_unlock(&dbus_lock);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
||||
static void
|
||||
dbus_connection_safe_close(DBusConnection *conn)
|
||||
{
|
||||
dbus_connection_flush(conn);
|
||||
dbus_connection_close(conn);
|
||||
dbus_connection_unref(conn);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
static void
|
||||
dbus_flush_queue(DBusConnection *conn)
|
||||
{
|
||||
dbus_sig_t *ds;
|
||||
|
||||
while (1) {
|
||||
pthread_mutex_lock(&dbus_lock);
|
||||
ds = TAILQ_FIRST(&dbus_signals);
|
||||
if (ds)
|
||||
TAILQ_REMOVE(&dbus_signals, ds, link);
|
||||
pthread_mutex_unlock(&dbus_lock);
|
||||
|
||||
if (ds == NULL)
|
||||
break;
|
||||
|
||||
if (conn)
|
||||
dbus_send_signal(conn,
|
||||
ds->obj_name, "org.tvheadend.notify",
|
||||
ds->sig_name, ds->msg);
|
||||
|
||||
htsmsg_destroy(ds->msg);
|
||||
free(ds->sig_name);
|
||||
free(ds->obj_name);
|
||||
free(ds);
|
||||
}
|
||||
if (conn)
|
||||
dbus_connection_flush(conn);
|
||||
}
|
||||
|
||||
/**
|
||||
* Listen for remote requests
|
||||
*/
|
||||
static void *
|
||||
dbus_server_thread(void *aux)
|
||||
{
|
||||
DBusMessage *msg;
|
||||
DBusConnection *conn, *notify;
|
||||
tvhpoll_t *poll;
|
||||
tvhpoll_event_t ev;
|
||||
dbus_rpc_t *rpc;
|
||||
int n;
|
||||
uint8_t c;
|
||||
|
||||
conn = dbus_create_session("org.tvheadend.server");
|
||||
if (conn == NULL) {
|
||||
dbus_running = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
notify = dbus_create_session("org.tvheadend.notify");
|
||||
if (notify == NULL) {
|
||||
dbus_running = 0;
|
||||
dbus_connection_safe_close(conn);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
poll = tvhpoll_create(2);
|
||||
memset(&ev, 0, sizeof(ev));
|
||||
ev.fd = dbus_pipe.rd;
|
||||
ev.events = TVHPOLL_IN;
|
||||
ev.data.ptr = &dbus_pipe;
|
||||
tvhpoll_add(poll, &ev, 1);
|
||||
memset(&ev, 0, sizeof(ev));
|
||||
if (!dbus_connection_get_unix_fd(conn, &ev.fd)) {
|
||||
dbus_running = 0;
|
||||
tvhpoll_destroy(poll);
|
||||
dbus_connection_safe_close(notify);
|
||||
dbus_connection_safe_close(conn);
|
||||
return NULL;
|
||||
}
|
||||
ev.events = TVHPOLL_IN;
|
||||
ev.data.ptr = conn;
|
||||
tvhpoll_add(poll, &ev, 1);
|
||||
|
||||
while (dbus_running) {
|
||||
|
||||
n = tvhpoll_wait(poll, &ev, 1, -1);
|
||||
if (n < 0) {
|
||||
if (dbus_running && !ERRNO_AGAIN(errno))
|
||||
tvherror("dbus", "tvhpoll_wait() error");
|
||||
} else if (n == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ev.data.ptr == &dbus_pipe) {
|
||||
if (read(dbus_pipe.rd, &c, 1) == 1) {
|
||||
if (c == 's')
|
||||
dbus_flush_queue(notify);
|
||||
else
|
||||
break; /* end-of-task */
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
while (1) {
|
||||
dbus_connection_read_write(conn, 0);
|
||||
msg = dbus_connection_pop_message(conn);
|
||||
if (msg == NULL)
|
||||
break;
|
||||
|
||||
if (dbus_message_is_method_call(msg, "org.tvheadend", "ping")) {
|
||||
dbus_reply_to_ping(msg, conn);
|
||||
continue;
|
||||
}
|
||||
|
||||
pthread_mutex_lock(&dbus_lock);
|
||||
LIST_FOREACH(rpc, &dbus_rpcs, link)
|
||||
if (dbus_message_is_method_call(msg, "org.tvheadend", rpc->call_name))
|
||||
break;
|
||||
pthread_mutex_unlock(&dbus_lock);
|
||||
|
||||
if (rpc)
|
||||
dbus_reply_to_rpc(rpc, msg, conn);
|
||||
|
||||
dbus_message_unref(msg);
|
||||
}
|
||||
}
|
||||
|
||||
dbus_connection_safe_close(conn);
|
||||
dbus_flush_queue(notify);
|
||||
dbus_connection_safe_close(notify);
|
||||
tvhpoll_destroy(poll);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
pthread_t dbus_tid;
|
||||
|
||||
void
|
||||
dbus_server_init(int enabled, int session)
|
||||
{
|
||||
dbus_session = session;
|
||||
pthread_mutex_init(&dbus_lock, NULL);
|
||||
TAILQ_INIT(&dbus_signals);
|
||||
LIST_INIT(&dbus_rpcs);
|
||||
if (enabled) {
|
||||
tvh_pipe(O_NONBLOCK, &dbus_pipe);
|
||||
dbus_threads_init_default();
|
||||
dbus_running = 1;
|
||||
dbus_emit_signal_str("/main", "start", tvheadend_version);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
dbus_server_start(void)
|
||||
{
|
||||
if (dbus_pipe.wr > 0)
|
||||
tvhthread_create(&dbus_tid, NULL, dbus_server_thread, NULL);
|
||||
}
|
||||
|
||||
void
|
||||
dbus_server_done(void)
|
||||
{
|
||||
dbus_rpc_t *rpc;
|
||||
|
||||
dbus_emit_signal_str("/main", "stop", "bye");
|
||||
dbus_running = 0;
|
||||
if (dbus_pipe.wr > 0) {
|
||||
tvh_write(dbus_pipe.wr, "", 1);
|
||||
pthread_kill(dbus_tid, SIGTERM);
|
||||
pthread_join(dbus_tid, NULL);
|
||||
}
|
||||
dbus_flush_queue(NULL);
|
||||
while ((rpc = LIST_FIRST(&dbus_rpcs)) != NULL) {
|
||||
LIST_REMOVE(rpc, link);
|
||||
free(rpc->call_name);
|
||||
free(rpc);
|
||||
}
|
||||
}
|
69
src/dbus.h
|
@ -1,69 +0,0 @@
|
|||
/*
|
||||
* tvheadend, UPnP interface
|
||||
* 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 DBUS_H_
|
||||
#define DBUS_H_
|
||||
|
||||
#include "build.h"
|
||||
#include "htsmsg.h"
|
||||
|
||||
#if ENABLE_DBUS_1
|
||||
|
||||
void
|
||||
dbus_emit_signal(const char *obj_name, const char *sig_name, htsmsg_t *msg);
|
||||
void
|
||||
dbus_emit_signal_str(const char *obj_name, const char *sig_name, const char *value);
|
||||
void
|
||||
dbus_emit_signal_s64(const char *obj_name, const char *sig_name, int64_t value);
|
||||
|
||||
void
|
||||
dbus_register_rpc_s64(const char *call_name, void *opaque,
|
||||
int64_t (*fcn)(void *, const char *, int64_t));
|
||||
|
||||
void
|
||||
dbus_register_rpc_str(const char *call_name, void *opaque,
|
||||
char *(*fcn)(void *, const char *, char *));
|
||||
|
||||
void dbus_server_init(int enabled, int session);
|
||||
void dbus_server_start(void);
|
||||
void dbus_server_done(void);
|
||||
|
||||
#else
|
||||
|
||||
static inline void
|
||||
dbus_emit_signal(const char *obj_name, const char *sig_name, htsmsg_t *msg) { htsmsg_destroy(msg); }
|
||||
static inline void
|
||||
dbus_emit_signal_str(const char *obj_name, const char *sig_name, const char *value) { }
|
||||
static inline void
|
||||
dbus_emit_signal_s64(const char *obj_name, const char *sig_name, int64_t value) { }
|
||||
|
||||
static inline void
|
||||
dbus_register_rpc_s64(const char *call_name, void *opaque,
|
||||
int64_t (*fcn)(void *, const char *, int64_t)) { }
|
||||
|
||||
static inline void
|
||||
dbus_register_rpc_str(const char *call_name, void *opaque,
|
||||
char *(*fcn)(void *, const char *, char *)) { }
|
||||
|
||||
static inline void dbus_server_init(int enabled, int session) { }
|
||||
static inline void dbus_server_start(void) { }
|
||||
static inline void dbus_server_done(void) { }
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* DBUS_H_ */
|
32
src/descrambler.h
Normal file → Executable file
|
@ -22,7 +22,6 @@
|
|||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include "queue.h"
|
||||
#include "descrambler/tvhcsa.h"
|
||||
|
||||
struct service;
|
||||
struct elementary_stream;
|
||||
|
@ -30,10 +29,6 @@ struct tvhcsa;
|
|||
struct mpegts_table;
|
||||
struct mpegts_mux;
|
||||
|
||||
#define DESCRAMBLER_NONE 0
|
||||
#define DESCRAMBLER_DES 1
|
||||
#define DESCRAMBLER_AES 2
|
||||
|
||||
/**
|
||||
* Descrambler superclass
|
||||
*
|
||||
|
@ -52,30 +47,27 @@ typedef struct th_descrambler {
|
|||
} td_keystate;
|
||||
|
||||
struct service *td_service;
|
||||
struct tvhcsa *td_csa;
|
||||
|
||||
void (*td_stop) (struct th_descrambler *d);
|
||||
void (*td_caid_change)(struct th_descrambler *d);
|
||||
int (*td_ecm_reset) (struct th_descrambler *d);
|
||||
void (*td_ecm_idle) (struct th_descrambler *d);
|
||||
|
||||
} th_descrambler_t;
|
||||
|
||||
typedef struct th_descrambler_runtime {
|
||||
tvhcsa_t dr_csa;
|
||||
time_t dr_last_descramble;
|
||||
uint32_t dr_key:1;
|
||||
uint32_t dr_key_first:1;
|
||||
uint8_t dr_key_index;
|
||||
uint8_t dr_key_valid;
|
||||
uint8_t dr_key_changed;
|
||||
uint8_t dr_ecm_valid;
|
||||
time_t dr_key_start;
|
||||
time_t dr_key_timestamp[2];
|
||||
time_t dr_ecm_start;
|
||||
time_t dr_ecm_key_time;
|
||||
time_t dr_last_err;
|
||||
sbuf_t dr_buf;
|
||||
tvhlog_limit_t dr_loglimit_key;
|
||||
uint8_t dr_key_even[16];
|
||||
uint8_t dr_key_odd[16];
|
||||
loglimiter_t dr_loglimit_key;
|
||||
} th_descrambler_runtime_t;
|
||||
|
||||
typedef void (*descrambler_section_callback_t)
|
||||
|
@ -84,18 +76,12 @@ typedef void (*descrambler_section_callback_t)
|
|||
/**
|
||||
* Track required PIDs
|
||||
*/
|
||||
typedef struct descrambler_ecmsec {
|
||||
LIST_ENTRY(descrambler_ecmsec) link;
|
||||
uint8_t number;
|
||||
uint8_t *last_data;
|
||||
int last_data_len;
|
||||
} descrambler_ecmsec_t;
|
||||
|
||||
typedef struct descrambler_section {
|
||||
TAILQ_ENTRY(descrambler_section) link;
|
||||
descrambler_section_callback_t callback;
|
||||
void *opaque;
|
||||
LIST_HEAD(, descrambler_ecmsec) ecmsecs;
|
||||
uint8_t *last_data;
|
||||
int last_data_len;
|
||||
} descrambler_section_t;
|
||||
|
||||
typedef struct descrambler_table {
|
||||
|
@ -149,7 +135,6 @@ typedef enum {
|
|||
CARD_NDS,
|
||||
CARD_CRYPTOWORKS,
|
||||
CARD_BULCRYPT,
|
||||
CARD_STREAMGUARD,
|
||||
CARD_UNKNOWN
|
||||
} card_type_t;
|
||||
|
||||
|
@ -162,12 +147,11 @@ void descrambler_done ( void );
|
|||
void descrambler_service_start ( struct service *t );
|
||||
void descrambler_service_stop ( struct service *t );
|
||||
void descrambler_caid_changed ( struct service *t );
|
||||
int descrambler_resolved ( struct service *t, th_descrambler_t *ignore );
|
||||
void descrambler_keys ( th_descrambler_t *t, int type,
|
||||
void descrambler_keys ( th_descrambler_t *t,
|
||||
const uint8_t *even, const uint8_t *odd );
|
||||
int descrambler_descramble ( struct service *t,
|
||||
struct elementary_stream *st,
|
||||
const uint8_t *tsb, int len );
|
||||
const uint8_t *tsb );
|
||||
int descrambler_open_pid ( struct mpegts_mux *mux, void *opaque, int pid,
|
||||
descrambler_section_callback_t callback,
|
||||
struct service *service );
|
||||
|
|