mirror of
https://github.com/rofafor/vdr-plugin-satip.git
synced 2023-10-10 11:37:42 +00:00
Compare commits
No commits in common. "master" and "v0.3.2" have entirely different histories.
3
.gitignore
vendored
3
.gitignore
vendored
@ -4,6 +4,3 @@
|
|||||||
*~
|
*~
|
||||||
po/*.pot
|
po/*.pot
|
||||||
po/*.mo
|
po/*.mo
|
||||||
.settings
|
|
||||||
.cproject
|
|
||||||
.project
|
|
||||||
|
168
HISTORY
168
HISTORY
@ -59,171 +59,3 @@ VDR Plugin 'satip' Revision History
|
|||||||
|
|
||||||
- Fixed model detection and OctopusNet DVB-C model quirks.
|
- Fixed model detection and OctopusNet DVB-C model quirks.
|
||||||
- Added a session id quirk for GSSBOX.
|
- Added a session id quirk for GSSBOX.
|
||||||
|
|
||||||
2014-05-18: Version 0.3.3
|
|
||||||
|
|
||||||
- Added a validity check for the session member.
|
|
||||||
- Added a session id quirk for Triax TSS 400.
|
|
||||||
|
|
||||||
2014-12-24: Version 1.0.0
|
|
||||||
|
|
||||||
- Fixed the cable only device detection.
|
|
||||||
- Added support for blacklisted sources.
|
|
||||||
- Fixed server reuse for active transponders.
|
|
||||||
- Added a preliminary support for Fritz!WLAN
|
|
||||||
Repeater DVB-C (Thanks to Christian Wick).
|
|
||||||
- Added a preliminary support for Telestar
|
|
||||||
Digibit R1 (Thanks to Dirk Wagner).
|
|
||||||
- Added a new device status menu.
|
|
||||||
- Added support for SAT>IP frontend selection via
|
|
||||||
Radio ID.
|
|
||||||
- Added command-line switches for manually defining
|
|
||||||
used SAT>IP servers and setting used tracing mode.
|
|
||||||
- Added new STAT and TRAC commands into the SVDRP
|
|
||||||
interface.
|
|
||||||
- Refactored the tuner implementation.
|
|
||||||
- Updated against SAT>IP protocol specification
|
|
||||||
version 1.2.1.
|
|
||||||
- Refactored input thread to increase performance.
|
|
||||||
- Added plenty of performance tweaks (Thanks to
|
|
||||||
Stefan Schallenberg).
|
|
||||||
- Fixed EIT scan (Thanks to Stefan Schallenberg).
|
|
||||||
|
|
||||||
2015-01-10: Version 1.0.1
|
|
||||||
|
|
||||||
- Updated the command-line help and README.
|
|
||||||
- Fixed the server teardown.
|
|
||||||
- Removed the unnecessary config directory definition.
|
|
||||||
- Added a fallback for older glibc libraries.
|
|
||||||
- Improved pid selection performance.
|
|
||||||
- Added support for Digital Devices CI extension.
|
|
||||||
|
|
||||||
2015-01-18: Version 1.0.2
|
|
||||||
|
|
||||||
- Added configurable CI slots.
|
|
||||||
- Fixed parsing of the setup values.
|
|
||||||
- Added an option to disable sources via sources.conf.
|
|
||||||
- Added a command-line option to disable all the
|
|
||||||
SAT>IP server quirks.
|
|
||||||
- Updated Spanish and Catalan translations (Thanks to
|
|
||||||
Gabriel Bonich).
|
|
||||||
- Updated German translations (Thanks to Frank Neumann).
|
|
||||||
|
|
||||||
|
|
||||||
===================================
|
|
||||||
VDR Plugin 'satip' Revision History
|
|
||||||
===================================
|
|
||||||
|
|
||||||
2015-02-19: Version 2.2.0
|
|
||||||
|
|
||||||
- Updated for vdr-2.2.0.
|
|
||||||
- Fixed memory deallocation errors.
|
|
||||||
- Cleaned up all scan-build warnings.
|
|
||||||
- Refactored the frontend handling.
|
|
||||||
|
|
||||||
2015-04-04: Version 2.2.1
|
|
||||||
|
|
||||||
- Improved RTSP error checking.
|
|
||||||
- Got rid of SATIP_DEBUG.
|
|
||||||
- Robustify the server discovery.
|
|
||||||
- Fixed a memory leak in TinyXML implementation
|
|
||||||
(Thanks to Oliver Endriss).
|
|
||||||
- Updated against SAT>IP protocol specification
|
|
||||||
version 1.2.2.
|
|
||||||
|
|
||||||
2015-04-26: Version 2.2.2
|
|
||||||
|
|
||||||
- Added a more flexible OPER command in the SVDRP
|
|
||||||
interface.
|
|
||||||
- Added new ATTA and DETA SVDRP commands.
|
|
||||||
- Set the default device count to two.
|
|
||||||
|
|
||||||
2015-09-18: Version 2.2.3
|
|
||||||
|
|
||||||
- Added a timeout for releasing idling devices.
|
|
||||||
- Reset the RTSP connection after any failed connect.
|
|
||||||
- Added tweaks for minisatip and Schwaiger MS41IP.
|
|
||||||
- Updated for vdr-2.3.1 (Thanks to Klaus Schmidinger).
|
|
||||||
|
|
||||||
2016-12-18: Version 2.2.4
|
|
||||||
|
|
||||||
- Updated German translation (Thanks to Frank Neumann).
|
|
||||||
- Fixed Panasonic CXW804 support (Thanks to Tobias Grimm).
|
|
||||||
- Fixed C++11 support (Thanks to Tobias Grimm).
|
|
||||||
- Fixed server assigment with source validation (Thanks to Patrick Boettcher).
|
|
||||||
- Added configurable RTP/RTCP ports (Thanks to chriszero).
|
|
||||||
- Added support for X-SATIP-RTSP-Port header.
|
|
||||||
- Added multicast and RTP-over-TCP support.
|
|
||||||
- Added support for activating/deactivating server on-the-fly.
|
|
||||||
- Extended command-line parameters for setting server quirks.
|
|
||||||
|
|
||||||
2017-08-15: Version 2.2.5
|
|
||||||
|
|
||||||
- Added Polish translation (Thanks to Tomasz Nowak).
|
|
||||||
- Updated Catalan and Spanish translations (Thanks to Gabriel Bonich).
|
|
||||||
- Added support for KATHREIN SatIP Server (Thanks to kavanu).
|
|
||||||
- Added support for FRITZ!Box 6490 Cable (Thanks to 9000h).
|
|
||||||
- Updated FRITZ!WLAN Repeater DVB-C detection for the latest firmware (Thanks to 9000h).
|
|
||||||
- Added GCC7 compatibility (Thanks to Sascha Kuehndel).
|
|
||||||
|
|
||||||
|
|
||||||
===================================
|
|
||||||
VDR Plugin 'satip' Revision History
|
|
||||||
===================================
|
|
||||||
|
|
||||||
2016-12-18: Version 2.3.0
|
|
||||||
|
|
||||||
- Updated for vdr-2.3.1.
|
|
||||||
- Updated German translation (Thanks to Frank Neumann).
|
|
||||||
- Fixed Panasonic CXW804 support (Thanks to Tobias Grimm).
|
|
||||||
- Fixed C++11 support (Thanks to Tobias Grimm).
|
|
||||||
- Fixed server assigment with source validation (Thanks to Patrick Boettcher).
|
|
||||||
- Added configurable RTP/RTCP ports (Thanks to chriszero).
|
|
||||||
- Added support for X-SATIP-RTSP-Port header.
|
|
||||||
- Added multicast and RTP-over-TCP support.
|
|
||||||
- Added support for activating/deactivating server on-the-fly.
|
|
||||||
- Extended command-line parameters for setting server quirks.
|
|
||||||
|
|
||||||
2017-08-15: Version 2.3.1
|
|
||||||
|
|
||||||
- Updated for vdr-2.3.7 (Thanks to Klaus Schmidinger).
|
|
||||||
- Added Polish translation (Thanks to Tomasz Nowak).
|
|
||||||
- Updated Catalan and Spanish translations (Thanks to Gabriel Bonich).
|
|
||||||
- Added support for KATHREIN SatIP Server (Thanks to kavanu).
|
|
||||||
- Added support for FRITZ!Box 6490 Cable (Thanks to 9000h).
|
|
||||||
- Updated FRITZ!WLAN Repeater DVB-C detection for the latest firmware (Thanks to 9000h).
|
|
||||||
- Added GCC7 compatibility (Thanks to Sascha Kuehndel).
|
|
||||||
|
|
||||||
|
|
||||||
===================================
|
|
||||||
VDR Plugin 'satip' Revision History
|
|
||||||
===================================
|
|
||||||
|
|
||||||
2018-04-15: Version 2.4.0
|
|
||||||
|
|
||||||
- Updated for vdr-2.4.0.
|
|
||||||
- Removed speed limit.
|
|
||||||
- Fixed transport media changes.
|
|
||||||
- Fixed memory leak in cSatipSectionFilter (Thanks to Alexander Pipelka).
|
|
||||||
- Added more robust section filter handling (Thanks to Alexander Pipelka).
|
|
||||||
- Added a command line parameter for the RTP receive buffer size (Thanks to Stefan Rehm).
|
|
||||||
|
|
||||||
2021-06-01: Version 2.4.1
|
|
||||||
|
|
||||||
- Added an option to enable/disable frontend reuse.
|
|
||||||
- Added a preliminary ATSC support.
|
|
||||||
- Fixed a channel switching logic bug (Thanks to REELcoder).
|
|
||||||
- Added a workaround for detecting Panasonic devices.
|
|
||||||
- Removed quirks from FRITZ!Box 6490 Cable due to new firmware.
|
|
||||||
- Fixed RTP over TCP.
|
|
||||||
- Fixed URL parameter creation (Thanks to Martin Janser).
|
|
||||||
- Added an option to enable/disable frontend reuse.
|
|
||||||
- Added a preliminary ATSC support.
|
|
||||||
- Fixed a channel switching logic bug (Thanks to REELcoder).
|
|
||||||
- Added quirks for Inverto IDL-400s.
|
|
||||||
- Updated German translation (Thanks to Martin Dummer).
|
|
||||||
- Added a quirk for always teardown before play (Thanks to maazl).
|
|
||||||
- Updated for vdr-2.4.3 (Thanks to <Winfried Koehler).
|
|
||||||
- Added timeout for HasLock (Thanks to Winfried Koehler).
|
|
||||||
- Updated detectsatip script for Python 3.
|
|
||||||
- Fixed keepalive interval.
|
|
||||||
|
47
Makefile
47
Makefile
@ -2,10 +2,18 @@
|
|||||||
# Makefile for SAT>IP plugin
|
# Makefile for SAT>IP plugin
|
||||||
#
|
#
|
||||||
|
|
||||||
|
# Debugging on/off
|
||||||
|
|
||||||
|
#SATIP_DEBUG = 1
|
||||||
|
|
||||||
# Use TinyXML instead of PugiXML
|
# Use TinyXML instead of PugiXML
|
||||||
|
|
||||||
#SATIP_USE_TINYXML = 1
|
#SATIP_USE_TINYXML = 1
|
||||||
|
|
||||||
|
# Strip debug symbols? Set eg. to /bin/true if not
|
||||||
|
|
||||||
|
STRIP = strip
|
||||||
|
|
||||||
# The official name of this plugin.
|
# The official name of this plugin.
|
||||||
# This name will be used in the '-P...' option of VDR to load the plugin.
|
# This name will be used in the '-P...' option of VDR to load the plugin.
|
||||||
# By default the main source file also carries this name.
|
# By default the main source file also carries this name.
|
||||||
@ -32,7 +40,6 @@ TMPDIR ?= /tmp
|
|||||||
|
|
||||||
export CFLAGS = $(call PKGCFG,cflags)
|
export CFLAGS = $(call PKGCFG,cflags)
|
||||||
export CXXFLAGS = $(call PKGCFG,cxxflags)
|
export CXXFLAGS = $(call PKGCFG,cxxflags)
|
||||||
STRIP ?= /bin/true
|
|
||||||
|
|
||||||
### The version number of VDR's plugin API:
|
### The version number of VDR's plugin API:
|
||||||
|
|
||||||
@ -68,6 +75,10 @@ else
|
|||||||
LIBS += -lpugixml
|
LIBS += -lpugixml
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifdef SATIP_DEBUG
|
||||||
|
DEFINES += -DDEBUG
|
||||||
|
endif
|
||||||
|
|
||||||
ifneq ($(strip $(GITTAG)),)
|
ifneq ($(strip $(GITTAG)),)
|
||||||
DEFINES += -DGITVERSION='"-GIT-$(GITTAG)"'
|
DEFINES += -DGITVERSION='"-GIT-$(GITTAG)"'
|
||||||
endif
|
endif
|
||||||
@ -77,9 +88,8 @@ all-redirect: all
|
|||||||
|
|
||||||
### The object files (add further files here):
|
### The object files (add further files here):
|
||||||
|
|
||||||
OBJS = $(PLUGIN).o common.o config.o device.o discover.o msearch.o param.o \
|
OBJS = $(PLUGIN).o common.o config.o device.o discover.o param.o \
|
||||||
poller.o rtp.o rtcp.o rtsp.o sectionfilter.o server.o setup.o socket.o \
|
sectionfilter.o server.o setup.o socket.o statistics.o tuner.o
|
||||||
statistics.o tuner.o
|
|
||||||
|
|
||||||
### The main target:
|
### The main target:
|
||||||
|
|
||||||
@ -88,15 +98,14 @@ all: $(SOFILE) i18n
|
|||||||
### Implicit rules:
|
### Implicit rules:
|
||||||
|
|
||||||
%.o: %.c
|
%.o: %.c
|
||||||
@echo CC $@
|
$(CXX) $(CXXFLAGS) -c $(DEFINES) $(INCLUDES) -o $@ $<
|
||||||
$(Q)$(CXX) $(CXXFLAGS) -c $(DEFINES) $(INCLUDES) -o $@ $<
|
|
||||||
|
|
||||||
### Dependencies:
|
### Dependencies:
|
||||||
|
|
||||||
MAKEDEP = $(CXX) -MM -MG
|
MAKEDEP = $(CXX) -MM -MG
|
||||||
DEPFILE = .dependencies
|
DEPFILE = .dependencies
|
||||||
$(DEPFILE): Makefile
|
$(DEPFILE): Makefile
|
||||||
$(Q)$(MAKEDEP) $(CXXFLAGS) $(DEFINES) $(INCLUDES) $(OBJS:%.o=%.c) > $@
|
@$(MAKEDEP) $(CXXFLAGS) $(DEFINES) $(INCLUDES) $(OBJS:%.o=%.c) > $@
|
||||||
|
|
||||||
-include $(DEPFILE)
|
-include $(DEPFILE)
|
||||||
|
|
||||||
@ -109,21 +118,17 @@ I18Nmsgs = $(addprefix $(DESTDIR)$(LOCDIR)/, $(addsuffix /LC_MESSAGES/vdr-$(PLU
|
|||||||
I18Npot = $(PODIR)/$(PLUGIN).pot
|
I18Npot = $(PODIR)/$(PLUGIN).pot
|
||||||
|
|
||||||
%.mo: %.po
|
%.mo: %.po
|
||||||
@echo MO $@
|
msgfmt -c -o $@ $<
|
||||||
$(Q)msgfmt -c -o $@ $<
|
|
||||||
|
|
||||||
$(I18Npot): $(wildcard *.c)
|
$(I18Npot): $(wildcard *.c)
|
||||||
@echo GT $@
|
xgettext -C -cTRANSLATORS --no-wrap --no-location -k -ktr -ktrNOOP --package-name=vdr-$(PLUGIN) --package-version=$(VERSION) --msgid-bugs-address='<see README>' -o $@ `ls $^`
|
||||||
$(Q)xgettext -C -cTRANSLATORS --no-wrap --no-location -k -ktr -ktrNOOP --package-name=vdr-$(PLUGIN) --package-version=$(VERSION) --msgid-bugs-address='<see README>' -o $@ `ls $^`
|
|
||||||
|
|
||||||
%.po: $(I18Npot)
|
%.po: $(I18Npot)
|
||||||
@echo PO $@
|
msgmerge -U --no-wrap --no-location --backup=none -q -N $@ $<
|
||||||
$(Q)msgmerge -U --no-wrap --no-location --backup=none -q -N $@ $<
|
|
||||||
@touch $@
|
@touch $@
|
||||||
|
|
||||||
$(I18Nmsgs): $(DESTDIR)$(LOCDIR)/%/LC_MESSAGES/vdr-$(PLUGIN).mo: $(PODIR)/%.mo
|
$(I18Nmsgs): $(DESTDIR)$(LOCDIR)/%/LC_MESSAGES/vdr-$(PLUGIN).mo: $(PODIR)/%.mo
|
||||||
@echo IN $@
|
install -D -m644 $< $@
|
||||||
$(Q)install -D -m644 $< $@
|
|
||||||
|
|
||||||
.PHONY: i18n
|
.PHONY: i18n
|
||||||
i18n: $(I18Nmo) $(I18Npot)
|
i18n: $(I18Nmo) $(I18Npot)
|
||||||
@ -133,13 +138,13 @@ install-i18n: $(I18Nmsgs)
|
|||||||
### Targets:
|
### Targets:
|
||||||
|
|
||||||
$(SOFILE): $(OBJS)
|
$(SOFILE): $(OBJS)
|
||||||
@echo LD $@
|
$(CXX) $(CXXFLAGS) $(LDFLAGS) -shared $(OBJS) $(LIBS) -o $@
|
||||||
$(Q)$(CXX) $(CXXFLAGS) $(LDFLAGS) -shared $(OBJS) $(LIBS) -o $@
|
ifndef SATIP_DEBUG
|
||||||
$(Q)$(STRIP) $@
|
@$(STRIP) $@
|
||||||
|
endif
|
||||||
|
|
||||||
install-lib: $(SOFILE)
|
install-lib: $(SOFILE)
|
||||||
@echo IN $(DESTDIR)$(LIBDIR)/$^.$(APIVERSION)
|
install -D $^ $(DESTDIR)$(LIBDIR)/$^.$(APIVERSION)
|
||||||
$(Q)install -D $^ $(DESTDIR)$(LIBDIR)/$^.$(APIVERSION)
|
|
||||||
|
|
||||||
install-conf:
|
install-conf:
|
||||||
@mkdir -p $(DESTDIR)$(CFGDIR)/plugins/$(PLUGIN)
|
@mkdir -p $(DESTDIR)$(CFGDIR)/plugins/$(PLUGIN)
|
||||||
@ -160,4 +165,4 @@ clean:
|
|||||||
|
|
||||||
.PHONY: cppcheck
|
.PHONY: cppcheck
|
||||||
cppcheck:
|
cppcheck:
|
||||||
$(Q)cppcheck --language=c++ --enable=all -v -f $(OBJS:%.o=%.c)
|
@cppcheck --language=c++ --enable=all -v -f $(OBJS:%.o=%.c)
|
||||||
|
169
README
169
README
@ -3,9 +3,9 @@ This is an SAT>IP plugin for the Video Disk Recorder (VDR).
|
|||||||
Written by: Rolf Ahrenberg
|
Written by: Rolf Ahrenberg
|
||||||
< R o l f . A h r e n b e r g @ s c i . f i >
|
< R o l f . A h r e n b e r g @ s c i . f i >
|
||||||
|
|
||||||
Project's homepage: https://github.com/rofafor/vdr-plugin-satip
|
Project's homepage: http://www.saunalahti.fi/~rahrenbe/vdr/satip/
|
||||||
|
|
||||||
Latest version available at: https://github.com/rofafor/vdr-plugin-satip/releases
|
Latest version available at: http://www.saunalahti.fi/~rahrenbe/vdr/satip/
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
This program is free software; you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License version 2 as
|
it under the terms of the GNU General Public License version 2 as
|
||||||
@ -23,8 +23,7 @@ Requirements:
|
|||||||
TinyXML - a simple, small, C++ XML parser
|
TinyXML - a simple, small, C++ XML parser
|
||||||
http://www.grinninglizard.com/tinyxml/
|
http://www.grinninglizard.com/tinyxml/
|
||||||
|
|
||||||
- Glibc >= 2.12 - the GNU C library (recvmmsg)
|
- VDR >= 2.1.4 for scrambled channels
|
||||||
http://www.gnu.org/software/libc/
|
|
||||||
|
|
||||||
Description:
|
Description:
|
||||||
|
|
||||||
@ -42,56 +41,13 @@ make -C satip-X.Y.Z install
|
|||||||
Configuration:
|
Configuration:
|
||||||
|
|
||||||
The plugin accepts a "--devices" (-d) command-line parameter defaulting
|
The plugin accepts a "--devices" (-d) command-line parameter defaulting
|
||||||
to two. This parameter defines how many simultaneous transponders can
|
to one. This parameter defines how many simultaneous transponders can
|
||||||
be received, if there are available SAT>IP tuners.
|
be received, if there are available SAT>IP tuners.
|
||||||
|
|
||||||
The plugin accepts also a "--server" (-s) command-line parameter, that
|
|
||||||
can be used to manually configure static SAT>IP servers if autodetection
|
|
||||||
via UPnP somehow can't be used. Multiple service entries can be given
|
|
||||||
separated by a semicolon:
|
|
||||||
|
|
||||||
[<srcaddress>@]<ipaddress>[:<port>]|<model>[:<filter>]|<description>[:<quirk>];...
|
|
||||||
|
|
||||||
- srcaddress (Optional) Source address can be used to define used
|
|
||||||
networking interface on a host, e.g. 127.0.0.1.
|
|
||||||
- ipaddress IP address of SAT>IP server, e.g. 127.0.0.1.
|
|
||||||
- port (Optional) IP port number of SAT>IP server, e.g 443.
|
|
||||||
- model Model defines DVB modulation system (DVBS2,
|
|
||||||
DVBT2, DVBT, DVBC) and number of available
|
|
||||||
frontends separated by a hyphen, e.g. DVBT2-4.
|
|
||||||
- filter (Optional) Filter can be used to limit satellite frontends
|
|
||||||
to certain satellite position, e.g. S19.2E.
|
|
||||||
- description Friendly name of SAT>IP server. This is used
|
|
||||||
for autodetection of quirks.
|
|
||||||
- quirk (Optional) Quirks are non-standard compliant features and
|
|
||||||
bug fixes of SAT>IP server defined by a
|
|
||||||
hexadecimal number. Multiple quirks can be
|
|
||||||
defined by combining values by addition:
|
|
||||||
|
|
||||||
0x01: Fix session id bug
|
|
||||||
0x02: Fix play parameter (addpids/delpids) bug
|
|
||||||
0x04: Fix frontend locking bug
|
|
||||||
0x08: Support for RTP over TCP
|
|
||||||
0x10: Support the X_PMT protocol extension
|
|
||||||
0x20: Support the CI TNR protocol extension
|
|
||||||
0x40: Fix auto-detection of pilot tones bug
|
|
||||||
0x80: Fix re-tuning bug by teardowning a session
|
|
||||||
|
|
||||||
Examples:
|
|
||||||
|
|
||||||
vdr -P 'satip -s 192.168.0.1|DVBS2-2,DVBT2-2|OctopusNet'
|
|
||||||
vdr -P 'satip -s 192.168.0.1|DVBS2-4|OctopusNet;192.168.0.2|DVBT2-4|minisatip:0x18'
|
|
||||||
vdr -P 'satip -s 192.168.0.1:554|DVBS2-2:S19.2E|OctopusNet;192.168.0.2:8554|DVBS2-4:S19.2E,S1W|minisatip'
|
|
||||||
|
|
||||||
The plugin accepts a "--portrange" (-p) command-line parameter, that can
|
|
||||||
be used to manually specify the RTP & RTCP port range and therefore
|
|
||||||
enables using the plugin through a NAT (e.g. Docker bridged network).
|
|
||||||
A minimum of 2 ports per device is required.
|
|
||||||
|
|
||||||
SAT>IP satellite positions (aka. signal sources) shall be defined via
|
SAT>IP satellite positions (aka. signal sources) shall be defined via
|
||||||
sources.conf. If the source description begins with a number, it's used
|
sources.conf. If the source description begins with a number, it's used
|
||||||
as SAT>IP signal source selection parameter. A special number zero can
|
as SAT>IP signal source selection parameter. Otherwise, the default
|
||||||
be used to disable the source. Otherwise, the default parameter is one:
|
parameter is one:
|
||||||
|
|
||||||
S19.2E Astra 1KR/1L/1M/2C
|
S19.2E Astra 1KR/1L/1M/2C
|
||||||
=> Signal source = 1
|
=> Signal source = 1
|
||||||
@ -102,60 +58,32 @@ S19.2E 2
|
|||||||
S19.2E 3 Astra 1KR/1L/1M/2C
|
S19.2E 3 Astra 1KR/1L/1M/2C
|
||||||
=> Signal source = 3
|
=> Signal source = 3
|
||||||
|
|
||||||
S19.2E 0 Astra 1KR/1L/1M/2C
|
|
||||||
=> Source is disabled
|
|
||||||
|
|
||||||
A channel can be assigned into a specific SAT>IP frontend by giving the
|
|
||||||
identifier number in RID field of a channels.conf entry:
|
|
||||||
FE = RID % 100
|
|
||||||
Valid range: 1 ... 99
|
|
||||||
|
|
||||||
Setup menu:
|
Setup menu:
|
||||||
|
|
||||||
- Operating mode = off If you want exclude all SAT>IP devices
|
- Operating mode = off If you want exclude all SAT>IP devices
|
||||||
low from VDR's device handling, set this
|
low from VDR's device handling, set this
|
||||||
normal option to "off". Otherwise, if you want
|
normal option to "off". Otherwise, if you want
|
||||||
high to keep SAT>IP at a low priority when
|
high to keep SAT>IP at a low priority when
|
||||||
selecting available devices, set this
|
selecting available devices, set this
|
||||||
option to "low". Similarly, the "high"
|
option to "low". Similarly, the "high"
|
||||||
value prefers the SAT>IP over the local
|
value prefers the SAT>IP over the local
|
||||||
DVB cards when selecting available devices.
|
DVB cards when selecting available devices.
|
||||||
- Use CI extension = no If you want to use the CI extension found
|
- Enable EPG scanning = yes If you want exclude all SAT>IP devices
|
||||||
in some SAT>IP hardware (e.g. Digital
|
from VDR's EIT background scanning, set
|
||||||
Devices OctopusNet), set this option to
|
this option to "no".
|
||||||
"yes".
|
- Disabled filters = none Certain section filters might cause some
|
||||||
- CICAM #<slot> = <system> If you want to assign a CA system into
|
unwanted behaviour to VDR such as time
|
||||||
a specific CI slot, set this option to
|
being falsely synchronized etc. This option
|
||||||
a named one. Use "---" for autoselection.
|
allows creation of blacklists of ill-behaving
|
||||||
- Enable EPG scanning = yes If you want exclude all SAT>IP devices
|
filters. If this option is set to a non-zero
|
||||||
from VDR's EIT background scanning, set
|
value, the menu page will contain that many
|
||||||
this option to "no".
|
"Disable filter" options which allow you
|
||||||
- Disabled sources = none If your SAT>IP servers don't have certain
|
to disable the individual section filters.
|
||||||
satellite positions available you can
|
Valid range: "none" = 0 ... 7
|
||||||
disable them via this option.
|
- [Red:Scan] Forces network scanning of SAT>IP hardware.
|
||||||
- Disabled filters = none Certain section filters might cause some
|
- [Blue:Info] Opens SAT>IP information/statistics menu.
|
||||||
unwanted behaviour to VDR such as time
|
- [Ok] Opens information menu of selected SAT>IP
|
||||||
being falsely synchronized etc. This option
|
device.
|
||||||
allows creation of blacklists of ill-behaving
|
|
||||||
filters. If this option is set to a non-zero
|
|
||||||
value, the menu page will contain that many
|
|
||||||
"Disable filter" options which allow you
|
|
||||||
to disable the individual section filters.
|
|
||||||
Valid range: "none" = 0 ... 7
|
|
||||||
- Transport mode = unicast If you want to use the non-standard
|
|
||||||
multicast RTP-over-TCP transport mode, set this option
|
|
||||||
rtp-o-tcp accordingly. Otherwise, the transport
|
|
||||||
mode will be RTP-over-UDP via unicast or
|
|
||||||
multicast.
|
|
||||||
- Enable frontend reuse = yes Certain devices might have artifacts if
|
|
||||||
multiple channels are assigned to the same
|
|
||||||
frontend. If you want to avoid such a
|
|
||||||
frontend assignment, set this option to "no".
|
|
||||||
- [Red:Scan] Forces network scanning of SAT>IP hardware.
|
|
||||||
- [Yellow:Devices] Opens SAT>IP device status menu.
|
|
||||||
- [Blue:Info] Opens SAT>IP information/statistics menu.
|
|
||||||
- [Ok] Opens information menu of selected SAT>IP
|
|
||||||
device.
|
|
||||||
|
|
||||||
Information menu:
|
Information menu:
|
||||||
|
|
||||||
@ -166,44 +94,19 @@ Information menu:
|
|||||||
|
|
||||||
Notes:
|
Notes:
|
||||||
|
|
||||||
- If you are having problems receiving DVB-S2 channels, make sure your
|
|
||||||
channels.conf entry contains correct pilot tone setting.
|
|
||||||
|
|
||||||
- The stream id "-1" states about unsuccessful tuning. This might be a
|
- The stream id "-1" states about unsuccessful tuning. This might be a
|
||||||
result of invalid channel parameters or lack of free SAT>IP tuners.
|
result of invalid channel parameters or lack of free SAT>IP tuners.
|
||||||
|
|
||||||
|
- SAT>IP specification 1.2 doesn't support DVB-C/DVB-C2 receivers yet,
|
||||||
|
but DVB-C (KABEL>IP) is supported for Digital Devices Octopus Net
|
||||||
|
devices.
|
||||||
|
|
||||||
- If the plugin doesn't detect your SAT>IP network device, make sure
|
- If the plugin doesn't detect your SAT>IP network device, make sure
|
||||||
your setup doesn't have firewalled the UDP port 1900.
|
your setup doesn't have firewalled the UDP port 1900.
|
||||||
|
|
||||||
- Stream decryption requires a separate CAM plugin that works without
|
- Stream decryption requires a separate CAM plugin that works without
|
||||||
direct access to any DVB card devices. Also the integrated CAM slots
|
direct access to any DVB card devices. The integrated CAM slot in
|
||||||
in Octopus Net devices are supported.
|
Octopus Net devices isn't supported.
|
||||||
|
|
||||||
- Tracing can be set on/off dynamically via command-line switch or
|
|
||||||
SVDRP command.
|
|
||||||
|
|
||||||
- OctopusNet firmware 1.0.40 or greater recommended.
|
|
||||||
|
|
||||||
- Inverto OEM firmware 1.17.0.120 or greater recommended.
|
|
||||||
The firmware 1.16.0.120 can be downloaded and installed
|
|
||||||
from their webpage: http://www.inverto.tv/support/
|
|
||||||
An update to a newer firmware should be offered afterwards.
|
|
||||||
|
|
||||||
- FRITZ!OS 7.00 or greater recommended for FRITZ!Box Cable devices.
|
|
||||||
Older firmware versions require both PlayPids and ForceLock quirks.
|
|
||||||
|
|
||||||
- If you are experiencing glitches in the video stream, one possible
|
|
||||||
reason can be buffer overflows in RTP receive sockets. You can verify
|
|
||||||
this by checking "receive buffer errors" counter by running "netstat -s"
|
|
||||||
command. If the counter increases every time a video glitch happens,
|
|
||||||
you should try to tweak the RTP receive buffer size with the "--rcvbuf"
|
|
||||||
(-r) plugin parameter.
|
|
||||||
A good starting point for the buffer size is to double the operating
|
|
||||||
system default value until errors disappear or the maximum value is
|
|
||||||
reached. You can check these values in Linux by checking the kernel
|
|
||||||
parameters:
|
|
||||||
$ cat /proc/sys/net/core/rmem_default
|
|
||||||
$ cat /proc/sys/net/core/rmem_max
|
|
||||||
|
|
||||||
Acknowledgements:
|
Acknowledgements:
|
||||||
|
|
||||||
|
73
common.c
73
common.c
@ -57,15 +57,6 @@ char *StripTags(char *strP)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *SkipZeroes(const char *strP)
|
|
||||||
{
|
|
||||||
if ((uchar)*strP != '0')
|
|
||||||
return (char *)strP;
|
|
||||||
while (*strP && (uchar)*strP == '0')
|
|
||||||
strP++;
|
|
||||||
return (char *)strP;
|
|
||||||
}
|
|
||||||
|
|
||||||
cString ChangeCase(const cString &strP, bool upperP)
|
cString ChangeCase(const cString &strP, bool upperP)
|
||||||
{
|
{
|
||||||
cString res(strP);
|
cString res(strP);
|
||||||
@ -79,72 +70,10 @@ cString ChangeCase(const cString &strP, bool upperP)
|
|||||||
|
|
||||||
const section_filter_table_type section_filter_table[SECTION_FILTER_TABLE_SIZE] =
|
const section_filter_table_type section_filter_table[SECTION_FILTER_TABLE_SIZE] =
|
||||||
{
|
{
|
||||||
// description tag pid tid mask
|
/* description tag pid tid mask */
|
||||||
{trNOOP("PAT (0x00)"), "PAT", 0x00, 0x00, 0xFF},
|
{trNOOP("PAT (0x00)"), "PAT", 0x00, 0x00, 0xFF},
|
||||||
{trNOOP("NIT (0x40)"), "NIT", 0x10, 0x40, 0xFF},
|
{trNOOP("NIT (0x40)"), "NIT", 0x10, 0x40, 0xFF},
|
||||||
{trNOOP("SDT (0x42)"), "SDT", 0x11, 0x42, 0xFF},
|
{trNOOP("SDT (0x42)"), "SDT", 0x11, 0x42, 0xFF},
|
||||||
{trNOOP("EIT (0x4E/0x4F/0x5X/0x6X)"), "EIT", 0x12, 0x40, 0xC0},
|
{trNOOP("EIT (0x4E/0x4F/0x5X/0x6X)"), "EIT", 0x12, 0x40, 0xC0},
|
||||||
{trNOOP("TDT (0x70)"), "TDT", 0x14, 0x70, 0xFF},
|
{trNOOP("TDT (0x70)"), "TDT", 0x14, 0x70, 0xFF},
|
||||||
};
|
};
|
||||||
|
|
||||||
const ca_systems_table_type ca_systems_table[CA_SYSTEMS_TABLE_SIZE] =
|
|
||||||
{
|
|
||||||
// http://www.dvb.org/index.php?id=174
|
|
||||||
// http://en.wikipedia.org/wiki/Conditional_access_system
|
|
||||||
// start end description
|
|
||||||
{0x0000, 0x0000, "---" }, // 0
|
|
||||||
{0x0100, 0x01FF, "SECA Mediaguard (100..1FF)"}, // 1
|
|
||||||
{0x0464, 0x0464, "EuroDec (464)" }, // 2
|
|
||||||
{0x0500, 0x05FF, "Viaccess (500..5FF)" }, // 3
|
|
||||||
{0x0600, 0x06FF, "Irdeto (600..6FF)" }, // 4
|
|
||||||
{0x0700, 0x07FF, "DigiCipher 2 (700..7FF)" }, // 5
|
|
||||||
{0x0900, 0x09FF, "NDS Videoguard (900..9FF)" }, // 6
|
|
||||||
{0x0B00, 0x0BFF, "Conax (B00..BFF)" }, // 7
|
|
||||||
{0x0D00, 0x0DFF, "CryptoWorks (D00..DFF)" }, // 8
|
|
||||||
{0x0E00, 0x0EFF, "PowerVu (E00..EFF)" }, // 9
|
|
||||||
{0x1000, 0x10FF, "RAS (1000..10FF)" }, // 10
|
|
||||||
{0x1200, 0x12FF, "NagraVision (1200..12FF)" }, // 11
|
|
||||||
{0x1700, 0x17FF, "VCAS (1700..17FF)" }, // 12
|
|
||||||
{0x1800, 0x18FF, "NagraVision (1800..18FF)" }, // 13
|
|
||||||
{0x22F0, 0x22F0, "Codicrypt (22F0)" }, // 14
|
|
||||||
{0x2600, 0x2600, "BISS (2600)" }, // 15
|
|
||||||
{0x2719, 0x2719, "VanyaCas (2719)" }, // 16
|
|
||||||
{0x4347, 0x4347, "CryptOn (4347)" }, // 17
|
|
||||||
{0x4800, 0x4800, "Accessgate (4800)" }, // 18
|
|
||||||
{0x4900, 0x4900, "China Crypt (4900)" }, // 19
|
|
||||||
{0x4A02, 0x4A02, "Tongfang (4A02)" }, // 20
|
|
||||||
{0x4A10, 0x4A10, "EasyCas (4A10)" }, // 21
|
|
||||||
{0x4A20, 0x4A20, "AlphaCrypt (4A20)" }, // 22
|
|
||||||
{0x4A60, 0x4A60, "SkyCrypt (4A60)" }, // 23
|
|
||||||
{0x4A61, 0x4A61, "Neotioncrypt (4A61)" }, // 24
|
|
||||||
{0x4A62, 0x4A62, "SkyCrypt (4A62)" }, // 25
|
|
||||||
{0x4A63, 0x4A63, "Neotion SHL (4A63)" }, // 26
|
|
||||||
{0x4A64, 0x4A6F, "SkyCrypt (4A64)" }, // 27
|
|
||||||
{0x4A70, 0x4A70, "DreamCrypt (4A70)" }, // 28
|
|
||||||
{0x4A80, 0x4A80, "ThalesCrypt (4A80)" }, // 29
|
|
||||||
{0x4AA1, 0x4AA1, "KeyFly (4AA1)" }, // 30
|
|
||||||
{0x4ABF, 0x4ABF, "CTI-CAS (4ABF)" }, // 31
|
|
||||||
{0x4AC1, 0x4AC1, "Latens (4AC1)" }, // 32
|
|
||||||
{0x4AD0, 0x4AD1, "X-Crypt (4AD0)" }, // 33
|
|
||||||
{0x4AD4, 0x4AD4, "OmniCrypt (4AD4)" }, // 34
|
|
||||||
{0x4AE0, 0x4AE1, "Z-Crypt (4AE0)" }, // 35
|
|
||||||
{0x4AE4, 0x4AE4, "CoreCrypt (4AE4)" }, // 36
|
|
||||||
{0x4AE5, 0x4AE5, "PRO-Crypt (4AE5)" }, // 37
|
|
||||||
{0x4AEA, 0x4AEA, "Cryptoguard (4AEA)" }, // 38
|
|
||||||
{0x4AEB, 0x4AEB, "Abel Quintic (4AEB)" }, // 39
|
|
||||||
{0x4AF0, 0x4AF0, "ABV (4AF0)" }, // 40
|
|
||||||
{0x5500, 0x5500, "Z-Crypt (5500)" }, // 41
|
|
||||||
{0x5501, 0x5501, "Griffin (5501)" }, // 42
|
|
||||||
{0x5581, 0x5581, "Bulcrypt (5581)" }, // 43
|
|
||||||
{0x7BE1, 0x7BE1, "DRE-Crypt (7BE1)" }, // 44
|
|
||||||
{0xA101, 0xA101, "RosCrypt-M (A101)" }, // 45
|
|
||||||
{0xEAD0, 0xEAD0, "VanyaCas (EAD0)" }, // 46
|
|
||||||
};
|
|
||||||
|
|
||||||
bool checkCASystem(unsigned int cicamP, int caidP)
|
|
||||||
{
|
|
||||||
// always skip the first row
|
|
||||||
if ((cicamP > 0) && (cicamP < ELEMENTS(ca_systems_table)))
|
|
||||||
return ((caidP >= ca_systems_table[cicamP].start) && (caidP <= ca_systems_table[cicamP].end));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
101
common.h
101
common.h
@ -8,16 +8,23 @@
|
|||||||
#ifndef __SATIP_COMMON_H
|
#ifndef __SATIP_COMMON_H
|
||||||
#define __SATIP_COMMON_H
|
#define __SATIP_COMMON_H
|
||||||
|
|
||||||
#include <vdr/device.h>
|
|
||||||
#include <vdr/tools.h>
|
#include <vdr/tools.h>
|
||||||
#include <vdr/config.h>
|
#include <vdr/config.h>
|
||||||
#include <vdr/i18n.h>
|
#include <vdr/i18n.h>
|
||||||
|
|
||||||
#define SATIP_DEFAULT_RTSP_PORT 554
|
#ifdef DEBUG
|
||||||
|
#define debug(x...) dsyslog("SATIP: " x);
|
||||||
|
#define info(x...) isyslog("SATIP: " x);
|
||||||
|
#define error(x...) esyslog("ERROR: " x);
|
||||||
|
#else
|
||||||
|
#define debug(x...) ;
|
||||||
|
#define info(x...) isyslog("SATIP: " x);
|
||||||
|
#define error(x...) esyslog("ERROR: " x);
|
||||||
|
#endif
|
||||||
|
|
||||||
#define SATIP_MAX_DEVICES MAXDEVICES
|
#define ELEMENTS(x) (sizeof(x) / sizeof(x[0]))
|
||||||
|
|
||||||
#define SATIP_BUFFER_SIZE KILOBYTE(2048)
|
#define SATIP_BUFFER_SIZE MEGABYTE(1)
|
||||||
|
|
||||||
#define SATIP_DEVICE_INFO_ALL 0
|
#define SATIP_DEVICE_INFO_ALL 0
|
||||||
#define SATIP_DEVICE_INFO_GENERAL 1
|
#define SATIP_DEVICE_INFO_GENERAL 1
|
||||||
@ -29,36 +36,32 @@
|
|||||||
#define SATIP_STATS_ACTIVE_PIDS_COUNT 10
|
#define SATIP_STATS_ACTIVE_PIDS_COUNT 10
|
||||||
#define SATIP_STATS_ACTIVE_FILTERS_COUNT 10
|
#define SATIP_STATS_ACTIVE_FILTERS_COUNT 10
|
||||||
|
|
||||||
#define MAX_DISABLED_SOURCES_COUNT 25
|
|
||||||
#define SECTION_FILTER_TABLE_SIZE 5
|
#define SECTION_FILTER_TABLE_SIZE 5
|
||||||
|
|
||||||
#define MAX_CICAM_COUNT 2
|
|
||||||
#define CA_SYSTEMS_TABLE_SIZE 47
|
|
||||||
|
|
||||||
#define SATIP_CURL_EASY_GETINFO(X, Y, Z) \
|
#define SATIP_CURL_EASY_GETINFO(X, Y, Z) \
|
||||||
if ((res = curl_easy_getinfo((X), (Y), (Z))) != CURLE_OK) { \
|
if ((res = curl_easy_getinfo((X), (Y), (Z))) != CURLE_OK) { \
|
||||||
esyslog("curl_easy_getinfo(%s) [%s,%d] failed: %s (%d)", #Y, __FILE__, __LINE__, curl_easy_strerror(res), res); \
|
error("curl_easy_getinfo(%s) [%s,%d] failed: %s (%d)", #Y, __FILE__, __LINE__, curl_easy_strerror(res), res); \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define SATIP_CURL_EASY_SETOPT(X, Y, Z) \
|
#define SATIP_CURL_EASY_SETOPT(X, Y, Z) \
|
||||||
if ((res = curl_easy_setopt((X), (Y), (Z))) != CURLE_OK) { \
|
if ((res = curl_easy_setopt((X), (Y), (Z))) != CURLE_OK) { \
|
||||||
esyslog("curl_easy_setopt(%s, %s) [%s,%d] failed: %s (%d)", #Y, #Z, __FILE__, __LINE__, curl_easy_strerror(res), res); \
|
error("curl_easy_setopt(%s, %s) [%s,%d] failed: %s (%d)", #Y, #Z, __FILE__, __LINE__, curl_easy_strerror(res), res); \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define SATIP_CURL_EASY_PERFORM(X) \
|
#define SATIP_CURL_EASY_PERFORM(X) \
|
||||||
if ((res = curl_easy_perform((X))) != CURLE_OK) { \
|
if ((res = curl_easy_perform((X))) != CURLE_OK) { \
|
||||||
esyslog("curl_easy_perform() [%s,%d] failed: %s (%d)", __FILE__, __LINE__, curl_easy_strerror(res), res); \
|
error("curl_easy_perform() [%s,%d] failed: %s (%d)", __FILE__, __LINE__, curl_easy_strerror(res), res); \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define ERROR_IF_FUNC(exp, errstr, func, ret) \
|
#define ERROR_IF_FUNC(exp, errstr, func, ret) \
|
||||||
do { \
|
do { \
|
||||||
if (exp) { \
|
if (exp) { \
|
||||||
char tmp[64]; \
|
char tmp[64]; \
|
||||||
esyslog("[%s,%d]: " errstr ": %s", __FILE__, __LINE__, \
|
error("[%s,%d]: "errstr": %s", __FILE__, __LINE__, \
|
||||||
strerror_r(errno, tmp, sizeof(tmp))); \
|
strerror_r(errno, tmp, sizeof(tmp))); \
|
||||||
func; \
|
func; \
|
||||||
ret; \
|
ret; \
|
||||||
} \
|
} \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
|
||||||
@ -84,59 +87,12 @@
|
|||||||
} \
|
} \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define ELEMENTS(x) (sizeof(x) / sizeof(x[0]))
|
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof(arr[0]))
|
||||||
|
|
||||||
class cSatipMemoryBuffer {
|
|
||||||
private:
|
|
||||||
enum {
|
|
||||||
eMaxDataSize = MEGABYTE(2)
|
|
||||||
};
|
|
||||||
char *dataM;
|
|
||||||
size_t sizeM;
|
|
||||||
void *AllocBuffer(void *ptrP, size_t sizeP)
|
|
||||||
{
|
|
||||||
// There might be a realloc() out there that doesn't like reallocing NULL pointers, so we take care of it here
|
|
||||||
if (ptrP)
|
|
||||||
return realloc(ptrP, sizeP);
|
|
||||||
else
|
|
||||||
return malloc(sizeP);
|
|
||||||
}
|
|
||||||
// to prevent copy constructor and assignment
|
|
||||||
cSatipMemoryBuffer(const cSatipMemoryBuffer&);
|
|
||||||
cSatipMemoryBuffer& operator=(const cSatipMemoryBuffer&);
|
|
||||||
public:
|
|
||||||
cSatipMemoryBuffer() : dataM(NULL), sizeM(0) {}
|
|
||||||
~cSatipMemoryBuffer() { Reset(); }
|
|
||||||
size_t Add(char *dataP, size_t sizeP)
|
|
||||||
{
|
|
||||||
if (sizeP > 0) {
|
|
||||||
size_t len = sizeM + sizeP + 1;
|
|
||||||
if (len < eMaxDataSize) {
|
|
||||||
dataM = (char *)AllocBuffer(dataM, len);
|
|
||||||
if (dataM) {
|
|
||||||
memcpy(&(dataM[sizeM]), dataP, sizeP);
|
|
||||||
sizeM += sizeP;
|
|
||||||
dataM[sizeM] = 0;
|
|
||||||
return sizeP;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
esyslog("[%s,%d]: Failed to allocate memory", __FILE__, __LINE__);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
esyslog("[%s,%d]: Buffer overflow", __FILE__, __LINE__);
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
};
|
|
||||||
char *Data(void) { return dataM; }
|
|
||||||
size_t Size(void) { return sizeM; }
|
|
||||||
void Reset(void) { FREE_POINTER(dataM); sizeM = 0; };
|
|
||||||
};
|
|
||||||
|
|
||||||
uint16_t ts_pid(const uint8_t *bufP);
|
uint16_t ts_pid(const uint8_t *bufP);
|
||||||
uint8_t payload(const uint8_t *bufP);
|
uint8_t payload(const uint8_t *bufP);
|
||||||
const char *id_pid(const u_short pidP);
|
const char *id_pid(const u_short pidP);
|
||||||
char *StripTags(char *strP);
|
char *StripTags(char *strP);
|
||||||
char *SkipZeroes(const char *strP);
|
|
||||||
cString ChangeCase(const cString &strP, bool upperP);
|
cString ChangeCase(const cString &strP, bool upperP);
|
||||||
|
|
||||||
struct section_filter_table_type {
|
struct section_filter_table_type {
|
||||||
@ -149,15 +105,6 @@ struct section_filter_table_type {
|
|||||||
|
|
||||||
extern const section_filter_table_type section_filter_table[SECTION_FILTER_TABLE_SIZE];
|
extern const section_filter_table_type section_filter_table[SECTION_FILTER_TABLE_SIZE];
|
||||||
|
|
||||||
struct ca_systems_table_type {
|
|
||||||
int start;
|
|
||||||
int end;
|
|
||||||
const char *description;
|
|
||||||
};
|
|
||||||
|
|
||||||
extern const ca_systems_table_type ca_systems_table[CA_SYSTEMS_TABLE_SIZE];
|
|
||||||
extern bool checkCASystem(unsigned int cicamP, int caidP);
|
|
||||||
|
|
||||||
extern const char VERSION[];
|
extern const char VERSION[];
|
||||||
|
|
||||||
#endif // __SATIP_COMMON_H
|
#endif // __SATIP_COMMON_H
|
||||||
|
62
config.c
62
config.c
@ -6,79 +6,41 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "discover.h"
|
#include "discover.h"
|
||||||
#include "log.h"
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
cSatipConfig SatipConfig;
|
cSatipConfig SatipConfig;
|
||||||
|
|
||||||
cSatipConfig::cSatipConfig(void)
|
cSatipConfig::cSatipConfig(void)
|
||||||
: operatingModeM(eOperatingModeLow),
|
: operatingModeM(eOperatingModeLow),
|
||||||
traceModeM(eTraceModeNormal),
|
|
||||||
ciExtensionM(0),
|
|
||||||
frontendReuseM(1),
|
|
||||||
eitScanM(1),
|
eitScanM(1),
|
||||||
useBytesM(1),
|
useBytesM(1)
|
||||||
portRangeStartM(0),
|
|
||||||
portRangeStopM(0),
|
|
||||||
transportModeM(eTransportModeUnicast),
|
|
||||||
detachedModeM(false),
|
|
||||||
disableServerQuirksM(false),
|
|
||||||
useSingleModelServersM(false),
|
|
||||||
rtpRcvBufSizeM(0)
|
|
||||||
{
|
{
|
||||||
for (unsigned int i = 0; i < ELEMENTS(cicamsM); ++i)
|
for (unsigned int i = 0; i < ARRAY_SIZE(disabledFiltersM); ++i)
|
||||||
cicamsM[i] = 0;
|
|
||||||
for (unsigned int i = 0; i < ELEMENTS(disabledSourcesM); ++i)
|
|
||||||
disabledSourcesM[i] = cSource::stNone;
|
|
||||||
for (unsigned int i = 0; i < ELEMENTS(disabledFiltersM); ++i)
|
|
||||||
disabledFiltersM[i] = -1;
|
disabledFiltersM[i] = -1;
|
||||||
}
|
memset(configDirectoryM, 0, sizeof(configDirectoryM));
|
||||||
|
|
||||||
int cSatipConfig::GetCICAM(unsigned int indexP) const
|
|
||||||
{
|
|
||||||
return (indexP < ELEMENTS(cicamsM)) ? cicamsM[indexP] : -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void cSatipConfig::SetCICAM(unsigned int indexP, int cicamP)
|
|
||||||
{
|
|
||||||
if (indexP < ELEMENTS(cicamsM))
|
|
||||||
cicamsM[indexP] = cicamP;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int cSatipConfig::GetDisabledSourcesCount(void) const
|
|
||||||
{
|
|
||||||
unsigned int n = 0;
|
|
||||||
while ((n < ELEMENTS(disabledSourcesM) && (disabledSourcesM[n] != cSource::stNone)))
|
|
||||||
n++;
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
|
|
||||||
int cSatipConfig::GetDisabledSources(unsigned int indexP) const
|
|
||||||
{
|
|
||||||
return (indexP < ELEMENTS(disabledSourcesM)) ? disabledSourcesM[indexP] : cSource::stNone;
|
|
||||||
}
|
|
||||||
|
|
||||||
void cSatipConfig::SetDisabledSources(unsigned int indexP, int sourceP)
|
|
||||||
{
|
|
||||||
if (indexP < ELEMENTS(disabledSourcesM))
|
|
||||||
disabledSourcesM[indexP] = sourceP;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int cSatipConfig::GetDisabledFiltersCount(void) const
|
unsigned int cSatipConfig::GetDisabledFiltersCount(void) const
|
||||||
{
|
{
|
||||||
unsigned int n = 0;
|
unsigned int n = 0;
|
||||||
while ((n < ELEMENTS(disabledFiltersM) && (disabledFiltersM[n] != -1)))
|
while ((n < ARRAY_SIZE(disabledFiltersM) && (disabledFiltersM[n] != -1)))
|
||||||
n++;
|
n++;
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
int cSatipConfig::GetDisabledFilters(unsigned int indexP) const
|
int cSatipConfig::GetDisabledFilters(unsigned int indexP) const
|
||||||
{
|
{
|
||||||
return (indexP < ELEMENTS(disabledFiltersM)) ? disabledFiltersM[indexP] : -1;
|
return (indexP < ARRAY_SIZE(disabledFiltersM)) ? disabledFiltersM[indexP] : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void cSatipConfig::SetDisabledFilters(unsigned int indexP, int numberP)
|
void cSatipConfig::SetDisabledFilters(unsigned int indexP, int numberP)
|
||||||
{
|
{
|
||||||
if (indexP < ELEMENTS(disabledFiltersM))
|
if (indexP < ARRAY_SIZE(disabledFiltersM))
|
||||||
disabledFiltersM[indexP] = numberP;
|
disabledFiltersM[indexP] = numberP;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void cSatipConfig::SetConfigDirectory(const char *directoryP)
|
||||||
|
{
|
||||||
|
debug("cSatipConfig::%s(%s)", __FUNCTION__, directoryP);
|
||||||
|
ERROR_IF(!realpath(directoryP, configDirectoryM), "Cannot canonicalize configuration directory");
|
||||||
|
}
|
||||||
|
72
config.h
72
config.h
@ -15,56 +15,19 @@ class cSatipConfig
|
|||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
unsigned int operatingModeM;
|
unsigned int operatingModeM;
|
||||||
unsigned int traceModeM;
|
|
||||||
unsigned int ciExtensionM;
|
|
||||||
unsigned int frontendReuseM;
|
|
||||||
unsigned int eitScanM;
|
unsigned int eitScanM;
|
||||||
unsigned int useBytesM;
|
unsigned int useBytesM;
|
||||||
unsigned int portRangeStartM;
|
|
||||||
unsigned int portRangeStopM;
|
|
||||||
unsigned int transportModeM;
|
|
||||||
bool detachedModeM;
|
|
||||||
bool disableServerQuirksM;
|
|
||||||
bool useSingleModelServersM;
|
|
||||||
int cicamsM[MAX_CICAM_COUNT];
|
|
||||||
int disabledSourcesM[MAX_DISABLED_SOURCES_COUNT];
|
|
||||||
int disabledFiltersM[SECTION_FILTER_TABLE_SIZE];
|
int disabledFiltersM[SECTION_FILTER_TABLE_SIZE];
|
||||||
size_t rtpRcvBufSizeM;
|
char configDirectoryM[PATH_MAX];
|
||||||
|
|
||||||
public:
|
public:
|
||||||
enum eOperatingMode {
|
enum {
|
||||||
eOperatingModeOff = 0,
|
eOperatingModeOff = 0,
|
||||||
eOperatingModeLow,
|
eOperatingModeLow,
|
||||||
eOperatingModeNormal,
|
eOperatingModeNormal,
|
||||||
eOperatingModeHigh,
|
eOperatingModeHigh,
|
||||||
eOperatingModeCount
|
eOperatingModeCount
|
||||||
};
|
};
|
||||||
enum eTransportMode {
|
|
||||||
eTransportModeUnicast = 0,
|
|
||||||
eTransportModeMulticast,
|
|
||||||
eTransportModeRtpOverTcp,
|
|
||||||
eTransportModeCount
|
|
||||||
};
|
|
||||||
enum eTraceMode {
|
|
||||||
eTraceModeNormal = 0x0000,
|
|
||||||
eTraceModeDebug1 = 0x0001,
|
|
||||||
eTraceModeDebug2 = 0x0002,
|
|
||||||
eTraceModeDebug3 = 0x0004,
|
|
||||||
eTraceModeDebug4 = 0x0008,
|
|
||||||
eTraceModeDebug5 = 0x0010,
|
|
||||||
eTraceModeDebug6 = 0x0020,
|
|
||||||
eTraceModeDebug7 = 0x0040,
|
|
||||||
eTraceModeDebug8 = 0x0080,
|
|
||||||
eTraceModeDebug9 = 0x0100,
|
|
||||||
eTraceModeDebug10 = 0x0200,
|
|
||||||
eTraceModeDebug11 = 0x0400,
|
|
||||||
eTraceModeDebug12 = 0x0800,
|
|
||||||
eTraceModeDebug13 = 0x1000,
|
|
||||||
eTraceModeDebug14 = 0x2000,
|
|
||||||
eTraceModeDebug15 = 0x4000,
|
|
||||||
eTraceModeDebug16 = 0x8000,
|
|
||||||
eTraceModeMask = 0xFFFF
|
|
||||||
};
|
|
||||||
cSatipConfig();
|
cSatipConfig();
|
||||||
unsigned int GetOperatingMode(void) const { return operatingModeM; }
|
unsigned int GetOperatingMode(void) const { return operatingModeM; }
|
||||||
bool IsOperatingModeOff(void) const { return (operatingModeM == eOperatingModeOff); }
|
bool IsOperatingModeOff(void) const { return (operatingModeM == eOperatingModeOff); }
|
||||||
@ -72,44 +35,17 @@ public:
|
|||||||
bool IsOperatingModeNormal(void) const { return (operatingModeM == eOperatingModeNormal); }
|
bool IsOperatingModeNormal(void) const { return (operatingModeM == eOperatingModeNormal); }
|
||||||
bool IsOperatingModeHigh(void) const { return (operatingModeM == eOperatingModeHigh); }
|
bool IsOperatingModeHigh(void) const { return (operatingModeM == eOperatingModeHigh); }
|
||||||
void ToggleOperatingMode(void) { operatingModeM = (operatingModeM + 1) % eOperatingModeCount; }
|
void ToggleOperatingMode(void) { operatingModeM = (operatingModeM + 1) % eOperatingModeCount; }
|
||||||
unsigned int GetTraceMode(void) const { return traceModeM; }
|
|
||||||
bool IsTraceMode(eTraceMode modeP) const { return (traceModeM & modeP); }
|
|
||||||
unsigned int GetCIExtension(void) const { return ciExtensionM; }
|
|
||||||
unsigned int GetFrontendReuse(void) const { return frontendReuseM; }
|
|
||||||
int GetCICAM(unsigned int indexP) const;
|
|
||||||
unsigned int GetEITScan(void) const { return eitScanM; }
|
unsigned int GetEITScan(void) const { return eitScanM; }
|
||||||
unsigned int GetUseBytes(void) const { return useBytesM; }
|
unsigned int GetUseBytes(void) const { return useBytesM; }
|
||||||
unsigned int GetTransportMode(void) const { return transportModeM; }
|
const char *GetConfigDirectory(void) const { return configDirectoryM; }
|
||||||
bool IsTransportModeUnicast(void) const { return (transportModeM == eTransportModeUnicast); }
|
|
||||||
bool IsTransportModeRtpOverTcp(void) const { return (transportModeM == eTransportModeRtpOverTcp); }
|
|
||||||
bool IsTransportModeMulticast(void) const { return (transportModeM == eTransportModeMulticast); }
|
|
||||||
bool GetDetachedMode(void) const { return detachedModeM; }
|
|
||||||
bool GetDisableServerQuirks(void) const { return disableServerQuirksM; }
|
|
||||||
bool GetUseSingleModelServers(void) const { return useSingleModelServersM; }
|
|
||||||
unsigned int GetDisabledSourcesCount(void) const;
|
|
||||||
int GetDisabledSources(unsigned int indexP) const;
|
|
||||||
unsigned int GetDisabledFiltersCount(void) const;
|
unsigned int GetDisabledFiltersCount(void) const;
|
||||||
int GetDisabledFilters(unsigned int indexP) const;
|
int GetDisabledFilters(unsigned int indexP) const;
|
||||||
unsigned int GetPortRangeStart(void) const { return portRangeStartM; }
|
|
||||||
unsigned int GetPortRangeStop(void) const { return portRangeStopM; }
|
|
||||||
size_t GetRtpRcvBufSize(void) const { return rtpRcvBufSizeM; }
|
|
||||||
|
|
||||||
void SetOperatingMode(unsigned int operatingModeP) { operatingModeM = operatingModeP; }
|
void SetOperatingMode(unsigned int operatingModeP) { operatingModeM = operatingModeP; }
|
||||||
void SetTraceMode(unsigned int modeP) { traceModeM = (modeP & eTraceModeMask); }
|
|
||||||
void SetCIExtension(unsigned int onOffP) { ciExtensionM = onOffP; }
|
|
||||||
void SetFrontendReuse(unsigned int onOffP) { frontendReuseM = onOffP; }
|
|
||||||
void SetCICAM(unsigned int indexP, int cicamP);
|
|
||||||
void SetEITScan(unsigned int onOffP) { eitScanM = onOffP; }
|
void SetEITScan(unsigned int onOffP) { eitScanM = onOffP; }
|
||||||
void SetUseBytes(unsigned int onOffP) { useBytesM = onOffP; }
|
void SetUseBytes(unsigned int onOffP) { useBytesM = onOffP; }
|
||||||
void SetTransportMode(unsigned int transportModeP) { transportModeM = transportModeP; }
|
void SetConfigDirectory(const char *directoryP);
|
||||||
void SetDetachedMode(bool onOffP) { detachedModeM = onOffP; }
|
|
||||||
void SetDisableServerQuirks(bool onOffP) { disableServerQuirksM = onOffP; }
|
|
||||||
void SetUseSingleModelServers(bool onOffP) { useSingleModelServersM = onOffP; }
|
|
||||||
void SetDisabledSources(unsigned int indexP, int sourceP);
|
|
||||||
void SetDisabledFilters(unsigned int indexP, int numberP);
|
void SetDisabledFilters(unsigned int indexP, int numberP);
|
||||||
void SetPortRangeStart(unsigned int rangeStartP) { portRangeStartM = rangeStartP; }
|
|
||||||
void SetPortRangeStop(unsigned int rangeStopP) { portRangeStopM = rangeStopP; }
|
|
||||||
void SetRtpRcvBufSize(size_t sizeP) { rtpRcvBufSizeM = sizeP; }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
extern cSatipConfig SatipConfig;
|
extern cSatipConfig SatipConfig;
|
||||||
|
@ -1,98 +0,0 @@
|
|||||||
#!/usr/bin/env python3
|
|
||||||
""" Simple tool to detect SAT>IP devices as JSON.
|
|
||||||
"""
|
|
||||||
import json
|
|
||||||
import socket
|
|
||||||
import sys
|
|
||||||
import xml.etree.ElementTree as ET
|
|
||||||
import requests
|
|
||||||
|
|
||||||
SSDP_BIND = "0.0.0.0"
|
|
||||||
SSDP_ADDR = "239.255.255.250"
|
|
||||||
SSDP_PORT = 1900
|
|
||||||
SSDP_MX = 1
|
|
||||||
SSDP_ST = "urn:ses-com:device:SatIPServer:1"
|
|
||||||
SSDP_REQUEST = "\r\n".join(
|
|
||||||
[
|
|
||||||
"M-SEARCH * HTTP/1.1",
|
|
||||||
f"HOST: {SSDP_ADDR}:{SSDP_PORT}",
|
|
||||||
'MAN: "ssdp:discover"',
|
|
||||||
f"MX: {SSDP_MX}",
|
|
||||||
f"ST: {SSDP_ST}",
|
|
||||||
"USER-AGENT: vdr-detectsatip",
|
|
||||||
"\r\n",
|
|
||||||
]
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def parse_satip_xml(data):
|
|
||||||
"""Parse SAT>IP XML data.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
data (str): XML input data..
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
dict: Parsed SAT>IP device name and frontend information.
|
|
||||||
"""
|
|
||||||
result = {"name": "", "frontends": {}}
|
|
||||||
if data:
|
|
||||||
root = ET.fromstring(data)
|
|
||||||
name = root.find(".//*/{urn:schemas-upnp-org:device-1-0}friendlyName")
|
|
||||||
result["name"] = name.text
|
|
||||||
satipcap = root.find(".//*/{urn:ses-com:satip}X_SATIPCAP")
|
|
||||||
if satipcap is None:
|
|
||||||
# fallback for non-standard Panasonic
|
|
||||||
satipcap = root.find(".//*/{urn-ses-com:satip}X_SATIPCAP")
|
|
||||||
caps = {}
|
|
||||||
for system in satipcap.text.split(","):
|
|
||||||
cap = system.split("-")
|
|
||||||
if cap:
|
|
||||||
count = int(cap[1])
|
|
||||||
if cap[0] in caps:
|
|
||||||
count = count + caps[cap[0]]
|
|
||||||
caps[cap[0]] = count
|
|
||||||
result["frontends"] = caps
|
|
||||||
return result
|
|
||||||
|
|
||||||
|
|
||||||
def detect_satip_devices():
|
|
||||||
"""Detect available SAT>IP devices by sending a broadcast message.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
list: Found SAT>IP devices.
|
|
||||||
"""
|
|
||||||
urls = []
|
|
||||||
devices = []
|
|
||||||
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
|
||||||
sock.setblocking(0)
|
|
||||||
sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
|
|
||||||
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
|
||||||
try:
|
|
||||||
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1)
|
|
||||||
except BaseException:
|
|
||||||
pass
|
|
||||||
sock.settimeout(1)
|
|
||||||
sock.bind((SSDP_BIND, SSDP_PORT))
|
|
||||||
sock.sendto(SSDP_REQUEST.encode("utf-8"), (SSDP_ADDR, SSDP_PORT))
|
|
||||||
try:
|
|
||||||
while 1:
|
|
||||||
data = sock.recv(1024).decode("utf-8")
|
|
||||||
if data:
|
|
||||||
for row in data.split("\r\n"):
|
|
||||||
if "LOCATION:" in row:
|
|
||||||
url = row.replace("LOCATION:", "").strip()
|
|
||||||
if url in urls:
|
|
||||||
continue
|
|
||||||
urls.append(url)
|
|
||||||
info = requests.get(url, timeout=2)
|
|
||||||
devices.append(parse_satip_xml(info.text))
|
|
||||||
else:
|
|
||||||
break
|
|
||||||
except BaseException:
|
|
||||||
pass
|
|
||||||
sock.close()
|
|
||||||
return devices
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
json.dump(detect_satip_devices(), fp=sys.stdout, sort_keys=True, indent=2)
|
|
292
device.c
292
device.c
@ -5,35 +5,31 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <vdr/menu.h> // cRecordControl
|
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "discover.h"
|
#include "discover.h"
|
||||||
#include "log.h"
|
|
||||||
#include "param.h"
|
#include "param.h"
|
||||||
#include "device.h"
|
#include "device.h"
|
||||||
|
|
||||||
static cSatipDevice * SatipDevicesS[SATIP_MAX_DEVICES] = { NULL };
|
#define SATIP_MAX_DEVICES MAXDEVICES
|
||||||
|
|
||||||
cMutex cSatipDevice::mutexS = cMutex();
|
static cSatipDevice * SatipDevicesS[SATIP_MAX_DEVICES] = { NULL };
|
||||||
|
|
||||||
cSatipDevice::cSatipDevice(unsigned int indexP)
|
cSatipDevice::cSatipDevice(unsigned int indexP)
|
||||||
: deviceIndexM(indexP),
|
: deviceIndexM(indexP),
|
||||||
bytesDeliveredM(0),
|
isPacketDeliveredM(false),
|
||||||
isOpenDvrM(false),
|
isOpenDvrM(false),
|
||||||
checkTsBufferM(false),
|
|
||||||
deviceNameM(*cString::sprintf("%s %d", *DeviceType(), deviceIndexM)),
|
deviceNameM(*cString::sprintf("%s %d", *DeviceType(), deviceIndexM)),
|
||||||
channelM(),
|
channelM(),
|
||||||
createdM(0),
|
createdM(0),
|
||||||
tunedM()
|
mutexM()
|
||||||
{
|
{
|
||||||
unsigned int bufsize = (unsigned int)SATIP_BUFFER_SIZE;
|
unsigned int bufsize = (unsigned int)SATIP_BUFFER_SIZE;
|
||||||
bufsize -= (bufsize % TS_SIZE);
|
bufsize -= (bufsize % TS_SIZE);
|
||||||
info("Creating device CardIndex=%d DeviceNumber=%d [device %u]", CardIndex(), DeviceNumber(), deviceIndexM);
|
isyslog("creating SAT>IP device %d (CardIndex=%d)", deviceIndexM, CardIndex());
|
||||||
tsBufferM = new cRingBufferLinear(bufsize + 1, TS_SIZE, false,
|
tsBufferM = new cRingBufferLinear(bufsize + 1, TS_SIZE, false,
|
||||||
*cString::sprintf("SATIP#%d TS", deviceIndexM));
|
*cString::sprintf("SAT>IP TS %d", deviceIndexM));
|
||||||
if (tsBufferM) {
|
if (tsBufferM) {
|
||||||
tsBufferM->SetTimeouts(10, 10);
|
tsBufferM->SetTimeouts(100, 100);
|
||||||
tsBufferM->SetIoThrottle();
|
tsBufferM->SetIoThrottle();
|
||||||
pTunerM = new cSatipTuner(*this, tsBufferM->Free());
|
pTunerM = new cSatipTuner(*this, tsBufferM->Free());
|
||||||
}
|
}
|
||||||
@ -44,9 +40,7 @@ cSatipDevice::cSatipDevice(unsigned int indexP)
|
|||||||
|
|
||||||
cSatipDevice::~cSatipDevice()
|
cSatipDevice::~cSatipDevice()
|
||||||
{
|
{
|
||||||
debug1("%s [device %u]", __PRETTY_FUNCTION__, deviceIndexM);
|
debug("cSatipDevice::%s(%u)", __FUNCTION__, deviceIndexM);
|
||||||
// Release immediately any pending conditional wait
|
|
||||||
tunedM.Broadcast();
|
|
||||||
// Stop section handler
|
// Stop section handler
|
||||||
StopSectionHandler();
|
StopSectionHandler();
|
||||||
DELETE_POINTER(pSectionFilterHandlerM);
|
DELETE_POINTER(pSectionFilterHandlerM);
|
||||||
@ -56,7 +50,7 @@ cSatipDevice::~cSatipDevice()
|
|||||||
|
|
||||||
bool cSatipDevice::Initialize(unsigned int deviceCountP)
|
bool cSatipDevice::Initialize(unsigned int deviceCountP)
|
||||||
{
|
{
|
||||||
debug1("%s (%u)", __PRETTY_FUNCTION__, deviceCountP);
|
debug("cSatipDevice::%s(%u)", __FUNCTION__, deviceCountP);
|
||||||
if (deviceCountP > SATIP_MAX_DEVICES)
|
if (deviceCountP > SATIP_MAX_DEVICES)
|
||||||
deviceCountP = SATIP_MAX_DEVICES;
|
deviceCountP = SATIP_MAX_DEVICES;
|
||||||
for (unsigned int i = 0; i < deviceCountP; ++i)
|
for (unsigned int i = 0; i < deviceCountP; ++i)
|
||||||
@ -68,7 +62,7 @@ bool cSatipDevice::Initialize(unsigned int deviceCountP)
|
|||||||
|
|
||||||
void cSatipDevice::Shutdown(void)
|
void cSatipDevice::Shutdown(void)
|
||||||
{
|
{
|
||||||
debug1("%s", __PRETTY_FUNCTION__);
|
debug("cSatipDevice::%s()", __FUNCTION__);
|
||||||
for (int i = 0; i < SATIP_MAX_DEVICES; ++i) {
|
for (int i = 0; i < SATIP_MAX_DEVICES; ++i) {
|
||||||
if (SatipDevicesS[i])
|
if (SatipDevicesS[i])
|
||||||
SatipDevicesS[i]->CloseDvr();
|
SatipDevicesS[i]->CloseDvr();
|
||||||
@ -78,7 +72,7 @@ void cSatipDevice::Shutdown(void)
|
|||||||
unsigned int cSatipDevice::Count(void)
|
unsigned int cSatipDevice::Count(void)
|
||||||
{
|
{
|
||||||
unsigned int count = 0;
|
unsigned int count = 0;
|
||||||
debug1("%s", __PRETTY_FUNCTION__);
|
debug("cSatipDevice::%s()", __FUNCTION__);
|
||||||
for (unsigned int i = 0; i < SATIP_MAX_DEVICES; ++i) {
|
for (unsigned int i = 0; i < SATIP_MAX_DEVICES; ++i) {
|
||||||
if (SatipDevicesS[i] != NULL)
|
if (SatipDevicesS[i] != NULL)
|
||||||
count++;
|
count++;
|
||||||
@ -88,75 +82,37 @@ unsigned int cSatipDevice::Count(void)
|
|||||||
|
|
||||||
cSatipDevice *cSatipDevice::GetSatipDevice(int cardIndexP)
|
cSatipDevice *cSatipDevice::GetSatipDevice(int cardIndexP)
|
||||||
{
|
{
|
||||||
debug16("%s (%d)", __PRETTY_FUNCTION__, cardIndexP);
|
//debug("cSatipDevice::%s(%d)", __FUNCTION__, cardIndexP);
|
||||||
for (unsigned int i = 0; i < SATIP_MAX_DEVICES; ++i) {
|
for (unsigned int i = 0; i < SATIP_MAX_DEVICES; ++i) {
|
||||||
if (SatipDevicesS[i] && (SatipDevicesS[i]->CardIndex() == cardIndexP)) {
|
if (SatipDevicesS[i] && (SatipDevicesS[i]->CardIndex() == cardIndexP)) {
|
||||||
debug16("%s (%d): Found!", __PRETTY_FUNCTION__, cardIndexP);
|
//debug("cSatipDevice::%s(%d): found!", __FUNCTION__, cardIndexP);
|
||||||
return SatipDevicesS[i];
|
return SatipDevicesS[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
cString cSatipDevice::GetSatipStatus(void)
|
|
||||||
{
|
|
||||||
cString info = "";
|
|
||||||
for (int i = 0; i < cDevice::NumDevices(); i++) {
|
|
||||||
const cDevice *device = cDevice::GetDevice(i);
|
|
||||||
if (device && strstr(device->DeviceType(), "SAT>IP")) {
|
|
||||||
int timers = 0;
|
|
||||||
bool live = (device == cDevice::ActualDevice());
|
|
||||||
bool lock = device->HasLock();
|
|
||||||
const cChannel *channel = device->GetCurrentlyTunedTransponder();
|
|
||||||
LOCK_TIMERS_READ;
|
|
||||||
for (const cTimer *timer = Timers->First(); timer; timer = Timers->Next(timer)) {
|
|
||||||
if (timer->Recording()) {
|
|
||||||
cRecordControl *control = cRecordControls::GetRecordControl(timer);
|
|
||||||
if (control && control->Device() == device)
|
|
||||||
timers++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
info = cString::sprintf("%sDevice: %s\n", *info, *device->DeviceName());
|
|
||||||
if (lock)
|
|
||||||
info = cString::sprintf("%sCardIndex: %d HasLock: yes Strength: %d Quality: %d%s\n", *info, device->CardIndex(), device->SignalStrength(), device->SignalQuality(), live ? " Live: yes" : "");
|
|
||||||
else
|
|
||||||
info = cString::sprintf("%sCardIndex: %d HasLock: no\n", *info, device->CardIndex());
|
|
||||||
if (channel) {
|
|
||||||
if (channel->Number() > 0 && device->Receiving())
|
|
||||||
info = cString::sprintf("%sTransponder: %d Channel: %s\n", *info, channel->Transponder(), channel->Name());
|
|
||||||
else
|
|
||||||
info = cString::sprintf("%sTransponder: %d\n", *info, channel->Transponder());
|
|
||||||
}
|
|
||||||
if (timers)
|
|
||||||
info = cString::sprintf("%sRecording: %d timer%s\n", *info, timers, (timers > 1) ? "s" : "");
|
|
||||||
info = cString::sprintf("%s\n", *info);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return isempty(*info) ? cString(tr("SAT>IP information not available!")) : info;
|
|
||||||
}
|
|
||||||
|
|
||||||
cString cSatipDevice::GetGeneralInformation(void)
|
cString cSatipDevice::GetGeneralInformation(void)
|
||||||
{
|
{
|
||||||
debug16("%s [device %u]", __PRETTY_FUNCTION__, deviceIndexM);
|
//debug("cSatipDevice::%s(%u)", __FUNCTION__, deviceIndexM);
|
||||||
LOCK_CHANNELS_READ;
|
return cString::sprintf("SAT>IP device: %d\nCardIndex: %d\nStream: %s\nSignal: %s\nStream bitrate: %s\n%sChannel: %s",
|
||||||
return cString::sprintf("SAT>IP device: %d\nCardIndex: %d\nStream: %s\nSignal: %s\nStream bitrate: %s\n%sChannel: %s\n",
|
|
||||||
deviceIndexM, CardIndex(),
|
deviceIndexM, CardIndex(),
|
||||||
pTunerM ? *pTunerM->GetInformation() : "",
|
pTunerM ? *pTunerM->GetInformation() : "",
|
||||||
pTunerM ? *pTunerM->GetSignalStatus() : "",
|
pTunerM ? *pTunerM->GetSignalStatus() : "",
|
||||||
pTunerM ? *pTunerM->GetTunerStatistic() : "",
|
pTunerM ? *pTunerM->GetTunerStatistic() : "",
|
||||||
*GetBufferStatistic(),
|
*GetBufferStatistic(),
|
||||||
*Channels->GetByNumber(cDevice::CurrentChannel())->ToText());
|
*Channels.GetByNumber(cDevice::CurrentChannel())->ToText());
|
||||||
}
|
}
|
||||||
|
|
||||||
cString cSatipDevice::GetPidsInformation(void)
|
cString cSatipDevice::GetPidsInformation(void)
|
||||||
{
|
{
|
||||||
debug16("%s [device %u]", __PRETTY_FUNCTION__, deviceIndexM);
|
//debug("cSatipDevice::%s(%u)", __FUNCTION__, deviceIndexM);
|
||||||
return GetPidStatistic();
|
return GetPidStatistic();
|
||||||
}
|
}
|
||||||
|
|
||||||
cString cSatipDevice::GetFiltersInformation(void)
|
cString cSatipDevice::GetFiltersInformation(void)
|
||||||
{
|
{
|
||||||
debug16("%s [device %u]", __PRETTY_FUNCTION__, deviceIndexM);
|
//debug("cSatipDevice::%s(%u)", __FUNCTION__, deviceIndexM);
|
||||||
return cString::sprintf("Active section filters:\n%s", pSectionFilterHandlerM ? *pSectionFilterHandlerM->GetInformation() : "");
|
return cString::sprintf("Active section filters:\n%s", pSectionFilterHandlerM ? *pSectionFilterHandlerM->GetInformation() : "");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -192,83 +148,50 @@ cString cSatipDevice::GetInformation(unsigned int pageP)
|
|||||||
|
|
||||||
bool cSatipDevice::Ready(void)
|
bool cSatipDevice::Ready(void)
|
||||||
{
|
{
|
||||||
debug16("%s [device %u]", __PRETTY_FUNCTION__, deviceIndexM);
|
//debug("cSatipDevice::%s(%u)", __FUNCTION__, deviceIndexM);
|
||||||
return ((cSatipDiscover::GetInstance()->GetServerCount() > 0) || (createdM.Elapsed() > eReadyTimeoutMs));
|
return ((cSatipDiscover::GetInstance()->GetServerCount() > 0) || (createdM.Elapsed() > eReadyTimeoutMs));
|
||||||
}
|
}
|
||||||
|
|
||||||
cString cSatipDevice::DeviceType(void) const
|
cString cSatipDevice::DeviceType(void) const
|
||||||
{
|
{
|
||||||
debug16("%s [device %u]", __PRETTY_FUNCTION__, deviceIndexM);
|
//debug("cSatipDevice::%s(%u)", __FUNCTION__, deviceIndexM);
|
||||||
return "SAT>IP";
|
return "SAT>IP";
|
||||||
}
|
}
|
||||||
|
|
||||||
cString cSatipDevice::DeviceName(void) const
|
cString cSatipDevice::DeviceName(void) const
|
||||||
{
|
{
|
||||||
debug16("%s [device %u]", __PRETTY_FUNCTION__, deviceIndexM);
|
//debug("cSatipDevice::%s(%u)", __FUNCTION__, deviceIndexM);
|
||||||
if (!Receiving())
|
|
||||||
return cString::sprintf("%s %d", *DeviceType(), deviceIndexM);
|
|
||||||
return deviceNameM;
|
return deviceNameM;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool cSatipDevice::AvoidRecording(void) const
|
bool cSatipDevice::AvoidRecording(void) const
|
||||||
{
|
{
|
||||||
debug16("%s [device %u]", __PRETTY_FUNCTION__, deviceIndexM);
|
//debug("cSatipDevice::%s(%u)", __FUNCTION__, deviceIndexM);
|
||||||
return SatipConfig.IsOperatingModeLow();
|
return SatipConfig.IsOperatingModeLow();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool cSatipDevice::SignalStats(int &Valid, double *Strength, double *Cnr, double *BerPre, double *BerPost, double *Per, int *Status) const
|
|
||||||
{
|
|
||||||
debug16("%s [device %u]", __PRETTY_FUNCTION__, deviceIndexM);
|
|
||||||
Valid = DTV_STAT_VALID_NONE;
|
|
||||||
if (Strength && pTunerM) {
|
|
||||||
*Strength = pTunerM->SignalStrengthDBm();
|
|
||||||
Valid |= DTV_STAT_VALID_STRENGTH;
|
|
||||||
}
|
|
||||||
if (Status) {
|
|
||||||
*Status = HasLock() ? (DTV_STAT_HAS_SIGNAL | DTV_STAT_HAS_CARRIER | DTV_STAT_HAS_VITERBI | DTV_STAT_HAS_SYNC | DTV_STAT_HAS_LOCK) : DTV_STAT_HAS_NONE;
|
|
||||||
Valid |= DTV_STAT_VALID_STATUS;
|
|
||||||
}
|
|
||||||
return Valid != DTV_STAT_VALID_NONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
int cSatipDevice::SignalStrength(void) const
|
int cSatipDevice::SignalStrength(void) const
|
||||||
{
|
{
|
||||||
debug16("%s [device %u]", __PRETTY_FUNCTION__, deviceIndexM);
|
//debug("cSatipDevice::%s(%u)", __FUNCTION__, deviceIndexM);
|
||||||
return (pTunerM ? pTunerM->SignalStrength() : -1);
|
return (pTunerM ? pTunerM->SignalStrength() : -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
int cSatipDevice::SignalQuality(void) const
|
int cSatipDevice::SignalQuality(void) const
|
||||||
{
|
{
|
||||||
debug16("%s [device %u]", __PRETTY_FUNCTION__, deviceIndexM);
|
//debug("cSatipDevice::%s(%u)", __FUNCTION__, deviceIndexM);
|
||||||
return (pTunerM ? pTunerM->SignalQuality() : -1);
|
return (pTunerM ? pTunerM->SignalQuality() : -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool cSatipDevice::ProvidesSource(int sourceP) const
|
bool cSatipDevice::ProvidesSource(int sourceP) const
|
||||||
{
|
{
|
||||||
cSource *s = Sources.Get(sourceP);
|
//debug("cSatipDevice::%s(%u)", __FUNCTION__, deviceIndexM);
|
||||||
debug9("%s (%c) desc='%s' [device %u]", __PRETTY_FUNCTION__, cSource::ToChar(sourceP), s ? s->Description() : "", deviceIndexM);
|
return (!SatipConfig.IsOperatingModeOff() && !!cSatipDiscover::GetInstance()->GetServer(sourceP));
|
||||||
if (SatipConfig.GetDetachedMode())
|
|
||||||
return false;
|
|
||||||
// source descriptions starting with '0' are disabled
|
|
||||||
if (s && s->Description() && (*(s->Description()) == '0'))
|
|
||||||
return false;
|
|
||||||
if (!SatipConfig.IsOperatingModeOff() && !!cSatipDiscover::GetInstance()->GetServer(sourceP)) {
|
|
||||||
int numDisabledSourcesM = SatipConfig.GetDisabledSourcesCount();
|
|
||||||
for (int i = 0; i < numDisabledSourcesM; ++i) {
|
|
||||||
if (sourceP == SatipConfig.GetDisabledSources(i))
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool cSatipDevice::ProvidesTransponder(const cChannel *channelP) const
|
bool cSatipDevice::ProvidesTransponder(const cChannel *channelP) const
|
||||||
{
|
{
|
||||||
debug9("%s (%d) transponder=%d source=%c [device %u]", __PRETTY_FUNCTION__, channelP ? channelP->Number() : -1, channelP ? channelP->Transponder() : -1, channelP ? cSource::ToChar(channelP->Source()) : '?', deviceIndexM);
|
debug("cSatipDevice::%s(%u)", __FUNCTION__, deviceIndexM);
|
||||||
if (!ProvidesSource(channelP->Source()))
|
return (ProvidesSource(channelP->Source()));
|
||||||
return false;
|
|
||||||
return DeviceHooksProvidesTransponder(channelP);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool cSatipDevice::ProvidesChannel(const cChannel *channelP, int priorityP, bool *needsDetachReceiversP) const
|
bool cSatipDevice::ProvidesChannel(const cChannel *channelP, int priorityP, bool *needsDetachReceiversP) const
|
||||||
@ -277,7 +200,7 @@ bool cSatipDevice::ProvidesChannel(const cChannel *channelP, int priorityP, bool
|
|||||||
bool hasPriority = (priorityP == IDLEPRIORITY) || (priorityP > this->Priority());
|
bool hasPriority = (priorityP == IDLEPRIORITY) || (priorityP > this->Priority());
|
||||||
bool needsDetachReceivers = false;
|
bool needsDetachReceivers = false;
|
||||||
|
|
||||||
debug9("%s (%d, %d, %d) [device %u]", __PRETTY_FUNCTION__, channelP ? channelP->Number() : -1, priorityP, !!needsDetachReceiversP, deviceIndexM);
|
debug("cSatipDevice::%s(%u)", __FUNCTION__, deviceIndexM);
|
||||||
|
|
||||||
if (channelP && ProvidesTransponder(channelP)) {
|
if (channelP && ProvidesTransponder(channelP)) {
|
||||||
result = hasPriority;
|
result = hasPriority;
|
||||||
@ -295,10 +218,10 @@ bool cSatipDevice::ProvidesChannel(const cChannel *channelP, int priorityP, bool
|
|||||||
result = true;
|
result = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
result = !!SatipConfig.GetFrontendReuse();
|
result = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
needsDetachReceivers = true;
|
needsDetachReceivers = Receiving();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -309,11 +232,7 @@ bool cSatipDevice::ProvidesChannel(const cChannel *channelP, int priorityP, bool
|
|||||||
|
|
||||||
bool cSatipDevice::ProvidesEIT(void) const
|
bool cSatipDevice::ProvidesEIT(void) const
|
||||||
{
|
{
|
||||||
#if defined(APIVERSNUM) && APIVERSNUM < 20403
|
|
||||||
return (SatipConfig.GetEITScan());
|
return (SatipConfig.GetEITScan());
|
||||||
#else
|
|
||||||
return (SatipConfig.GetEITScan()) && DeviceHooksProvidesEIT();
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int cSatipDevice::NumProvidedSystems(void) const
|
int cSatipDevice::NumProvidedSystems(void) const
|
||||||
@ -353,51 +272,35 @@ bool cSatipDevice::MaySwitchTransponder(const cChannel *channelP) const
|
|||||||
|
|
||||||
bool cSatipDevice::SetChannelDevice(const cChannel *channelP, bool liveViewP)
|
bool cSatipDevice::SetChannelDevice(const cChannel *channelP, bool liveViewP)
|
||||||
{
|
{
|
||||||
cMutexLock MutexLock(&mutexS); // Global lock to prevent any simultaneous zapping
|
|
||||||
debug9("%s (%d, %d) [device %u]", __PRETTY_FUNCTION__, channelP ? channelP->Number() : -1, liveViewP, deviceIndexM);
|
|
||||||
if (channelP) {
|
if (channelP) {
|
||||||
cDvbTransponderParameters dtp(channelP->Parameters());
|
cDvbTransponderParameters dtp(channelP->Parameters());
|
||||||
cString params = GetTransponderUrlParameters(channelP);
|
cString params = GetTransponderUrlParameters(channelP);
|
||||||
if (isempty(params)) {
|
if (isempty(params)) {
|
||||||
error("Unrecognized channel parameters: %s [device %u]", channelP->Parameters(), deviceIndexM);
|
error("Unrecognized SAT>IP channel parameters: %s", channelP->Parameters());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
cString address;
|
cString address;
|
||||||
cSatipServer *server = cSatipDiscover::GetInstance()->AssignServer(deviceIndexM, channelP->Source(), channelP->Transponder(), dtp.System());
|
cSatipServer *server = cSatipDiscover::GetInstance()->GetServer(channelP->Source(), dtp.System());
|
||||||
if (!server) {
|
if (!server) {
|
||||||
debug9("%s No suitable server found [device %u]", __PRETTY_FUNCTION__, deviceIndexM);
|
debug("cSatipDevice::%s(%u): no suitable server found", __FUNCTION__, deviceIndexM);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (pTunerM && pTunerM->SetSource(server, channelP->Transponder(), *params, deviceIndexM)) {
|
if (pTunerM && pTunerM->SetSource(server, *params, deviceIndexM)) {
|
||||||
channelM = *channelP;
|
|
||||||
deviceNameM = cString::sprintf("%s %d %s", *DeviceType(), deviceIndexM, *cSatipDiscover::GetInstance()->GetServerString(server));
|
deviceNameM = cString::sprintf("%s %d %s", *DeviceType(), deviceIndexM, *cSatipDiscover::GetInstance()->GetServerString(server));
|
||||||
// Wait for actual channel tuning to prevent simultaneous frontend allocation failures
|
channelM = *channelP;
|
||||||
tunedM.TimedWait(mutexS, eTuningTimeoutMs);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (pTunerM) {
|
|
||||||
pTunerM->SetSource(NULL, 0, NULL, deviceIndexM);
|
|
||||||
deviceNameM = cString::sprintf("%s %d", *DeviceType(), deviceIndexM);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void cSatipDevice::SetChannelTuned(void)
|
|
||||||
{
|
|
||||||
debug9("%s () [device %u]", __PRETTY_FUNCTION__, deviceIndexM);
|
|
||||||
// Release immediately any pending conditional wait
|
|
||||||
tunedM.Broadcast();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool cSatipDevice::SetPid(cPidHandle *handleP, int typeP, bool onP)
|
bool cSatipDevice::SetPid(cPidHandle *handleP, int typeP, bool onP)
|
||||||
{
|
{
|
||||||
debug12("%s (%d, %d, %d) [device %u]", __PRETTY_FUNCTION__, handleP ? handleP->pid : -1, typeP, onP, deviceIndexM);
|
//debug("cSatipDevice::%s(%u): pid=%d type=%d on=%d", __FUNCTION__, deviceIndexM, handleP->pid, typeP, onP);
|
||||||
if (pTunerM && handleP && handleP->pid >= 0 && handleP->pid <= 8191) {
|
if (pTunerM && handleP && handleP->pid >= 0) {
|
||||||
if (onP)
|
if (onP)
|
||||||
return pTunerM->SetPid(handleP->pid, typeP, true);
|
return pTunerM->SetPid(handleP->pid, typeP, true);
|
||||||
else if (!handleP->used && pSectionFilterHandlerM && !pSectionFilterHandlerM->Exists(handleP->pid))
|
else if (!handleP->used)
|
||||||
return pTunerM->SetPid(handleP->pid, typeP, false);
|
return pTunerM->SetPid(handleP->pid, typeP, false);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@ -405,7 +308,7 @@ bool cSatipDevice::SetPid(cPidHandle *handleP, int typeP, bool onP)
|
|||||||
|
|
||||||
int cSatipDevice::OpenFilter(u_short pidP, u_char tidP, u_char maskP)
|
int cSatipDevice::OpenFilter(u_short pidP, u_char tidP, u_char maskP)
|
||||||
{
|
{
|
||||||
debug12("%s (%d, %02X, %02X) [device %d]", __PRETTY_FUNCTION__, pidP, tidP, maskP, deviceIndexM);
|
//debug("cSatipDevice::%s(%u): pid=%d tid=%d mask=%d", __FUNCTION__, deviceIndexM, pidP, tidP, maskP);
|
||||||
if (pSectionFilterHandlerM) {
|
if (pSectionFilterHandlerM) {
|
||||||
int handle = pSectionFilterHandlerM->Open(pidP, tidP, maskP);
|
int handle = pSectionFilterHandlerM->Open(pidP, tidP, maskP);
|
||||||
if (pTunerM && (handle >= 0))
|
if (pTunerM && (handle >= 0))
|
||||||
@ -417,19 +320,18 @@ int cSatipDevice::OpenFilter(u_short pidP, u_char tidP, u_char maskP)
|
|||||||
|
|
||||||
void cSatipDevice::CloseFilter(int handleP)
|
void cSatipDevice::CloseFilter(int handleP)
|
||||||
{
|
{
|
||||||
|
//debug("cSatipDevice::%s(%u): handle=%d", __FUNCTION__, deviceIndexM, handleP);
|
||||||
if (pSectionFilterHandlerM) {
|
if (pSectionFilterHandlerM) {
|
||||||
int pid = pSectionFilterHandlerM->GetPid(handleP);
|
|
||||||
debug12("%s (%d) [device %u]", __PRETTY_FUNCTION__, pid, deviceIndexM);
|
|
||||||
if (pTunerM)
|
if (pTunerM)
|
||||||
pTunerM->SetPid(pid, ptOther, false);
|
pTunerM->SetPid(pSectionFilterHandlerM->GetPid(handleP), ptOther, false);
|
||||||
pSectionFilterHandlerM->Close(handleP);
|
pSectionFilterHandlerM->Close(handleP);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool cSatipDevice::OpenDvr(void)
|
bool cSatipDevice::OpenDvr(void)
|
||||||
{
|
{
|
||||||
debug9("%s [device %u]", __PRETTY_FUNCTION__, deviceIndexM);
|
debug("cSatipDevice::%s(%u)", __FUNCTION__, deviceIndexM);
|
||||||
bytesDeliveredM = 0;
|
isPacketDeliveredM = false;
|
||||||
tsBufferM->Clear();
|
tsBufferM->Clear();
|
||||||
if (pTunerM)
|
if (pTunerM)
|
||||||
pTunerM->Open();
|
pTunerM->Open();
|
||||||
@ -439,7 +341,7 @@ bool cSatipDevice::OpenDvr(void)
|
|||||||
|
|
||||||
void cSatipDevice::CloseDvr(void)
|
void cSatipDevice::CloseDvr(void)
|
||||||
{
|
{
|
||||||
debug9("%s [device %u]", __PRETTY_FUNCTION__, deviceIndexM);
|
debug("cSatipDevice::%s(%u)", __FUNCTION__, deviceIndexM);
|
||||||
if (pTunerM)
|
if (pTunerM)
|
||||||
pTunerM->Close();
|
pTunerM->Close();
|
||||||
isOpenDvrM = false;
|
isOpenDvrM = false;
|
||||||
@ -447,29 +349,21 @@ void cSatipDevice::CloseDvr(void)
|
|||||||
|
|
||||||
bool cSatipDevice::HasLock(int timeoutMsP) const
|
bool cSatipDevice::HasLock(int timeoutMsP) const
|
||||||
{
|
{
|
||||||
debug16("%s (%d) [device %d]", __PRETTY_FUNCTION__, timeoutMsP, deviceIndexM);
|
//debug("cSatipDevice::%s(%u): timeoutMs=%d", __FUNCTION__, deviceIndexM, timeoutMsP);
|
||||||
if (timeoutMsP > 0) {
|
|
||||||
cTimeMs timer(timeoutMsP);
|
|
||||||
while (!timer.TimedOut()) {
|
|
||||||
if (pTunerM && pTunerM->HasLock())
|
|
||||||
return true;
|
|
||||||
cCondWait::SleepMs(100);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return (pTunerM && pTunerM->HasLock());
|
return (pTunerM && pTunerM->HasLock());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool cSatipDevice::HasInternalCam(void)
|
bool cSatipDevice::HasInternalCam(void)
|
||||||
{
|
{
|
||||||
debug16("%s [device %u]", __PRETTY_FUNCTION__, deviceIndexM);
|
//debug("cSatipDevice::%s(%u)", __FUNCTION__, deviceIndexM);
|
||||||
return SatipConfig.GetCIExtension();
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void cSatipDevice::WriteData(uchar *bufferP, int lengthP)
|
void cSatipDevice::WriteData(uchar *bufferP, int lengthP)
|
||||||
{
|
{
|
||||||
debug16("%s [device %u]", __PRETTY_FUNCTION__, deviceIndexM);
|
//debug("cSatipDevice::%s(%u)", __FUNCTION__, deviceIndexM);
|
||||||
// Fill up TS buffer
|
// Fill up TS buffer
|
||||||
if (isOpenDvrM && tsBufferM) {
|
if (tsBufferM) {
|
||||||
int len = tsBufferM->Put(bufferP, lengthP);
|
int len = tsBufferM->Put(bufferP, lengthP);
|
||||||
if (len != lengthP)
|
if (len != lengthP)
|
||||||
tsBufferM->ReportOverflow(lengthP - len);
|
tsBufferM->ReportOverflow(lengthP - len);
|
||||||
@ -479,61 +373,27 @@ void cSatipDevice::WriteData(uchar *bufferP, int lengthP)
|
|||||||
pSectionFilterHandlerM->Write(bufferP, lengthP);
|
pSectionFilterHandlerM->Write(bufferP, lengthP);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned int cSatipDevice::CheckData(void)
|
||||||
|
{
|
||||||
|
//debug("cSatipDevice::%s(%u)", __FUNCTION__, deviceIndexM);
|
||||||
|
if (tsBufferM)
|
||||||
|
return (unsigned int)tsBufferM->Free();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int cSatipDevice::GetId(void)
|
int cSatipDevice::GetId(void)
|
||||||
{
|
{
|
||||||
|
//debug("cSatipDevice::%s(%u)", __FUNCTION__, deviceIndexM);
|
||||||
return deviceIndexM;
|
return deviceIndexM;
|
||||||
}
|
}
|
||||||
|
|
||||||
int cSatipDevice::GetPmtPid(void)
|
uchar *cSatipDevice::GetData(int *availableP)
|
||||||
{
|
{
|
||||||
int pid = channelM.Ca() ? ::GetPmtPid(channelM.Source(), channelM.Transponder(), channelM.Sid()) : 0;
|
//debug("cSatipDevice::%s(%u)", __FUNCTION__, deviceIndexM);
|
||||||
debug11("%s pmtpid=%d source=%c transponder=%d sid=%d name=%s [device %u]", __PRETTY_FUNCTION__, pid, cSource::ToChar(channelM.Source()), channelM.Transponder(), channelM.Sid(), channelM.Name(), deviceIndexM);
|
|
||||||
return pid;
|
|
||||||
}
|
|
||||||
|
|
||||||
int cSatipDevice::GetCISlot(void)
|
|
||||||
{
|
|
||||||
int slot = 0;
|
|
||||||
int ca = 0;
|
|
||||||
for (const int *id = channelM.Caids(); *id; ++id) {
|
|
||||||
if (checkCASystem(SatipConfig.GetCICAM(0), *id)) {
|
|
||||||
ca = *id;
|
|
||||||
slot = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else if (checkCASystem(SatipConfig.GetCICAM(1), *id)) {
|
|
||||||
ca = *id;
|
|
||||||
slot = 2;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
debug11("%s slot=%d ca=%X name=%s [device %u]", __PRETTY_FUNCTION__, slot, ca, channelM.Name(), deviceIndexM);
|
|
||||||
return slot;
|
|
||||||
}
|
|
||||||
|
|
||||||
cString cSatipDevice::GetTnrParameterString(void)
|
|
||||||
{
|
|
||||||
if (channelM.Ca())
|
|
||||||
return GetTnrUrlParameters(&channelM);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool cSatipDevice::IsIdle(void)
|
|
||||||
{
|
|
||||||
return !Receiving();
|
|
||||||
}
|
|
||||||
|
|
||||||
uchar *cSatipDevice::GetData(int *availableP, bool checkTsBuffer)
|
|
||||||
{
|
|
||||||
debug16("%s [device %u]", __PRETTY_FUNCTION__, deviceIndexM);
|
|
||||||
if (isOpenDvrM && tsBufferM) {
|
if (isOpenDvrM && tsBufferM) {
|
||||||
int count = 0;
|
int count = 0;
|
||||||
if (bytesDeliveredM) {
|
if (isPacketDeliveredM)
|
||||||
tsBufferM->Del(bytesDeliveredM);
|
SkipData(TS_SIZE);
|
||||||
bytesDeliveredM = 0;
|
|
||||||
}
|
|
||||||
if (checkTsBuffer && tsBufferM->Available() < TS_SIZE)
|
|
||||||
return NULL;
|
|
||||||
uchar *p = tsBufferM->Get(count);
|
uchar *p = tsBufferM->Get(count);
|
||||||
if (p && count >= TS_SIZE) {
|
if (p && count >= TS_SIZE) {
|
||||||
if (*p != TS_SYNC_BYTE) {
|
if (*p != TS_SYNC_BYTE) {
|
||||||
@ -547,7 +407,7 @@ uchar *cSatipDevice::GetData(int *availableP, bool checkTsBuffer)
|
|||||||
info("Skipped %d bytes to sync on TS packet", count);
|
info("Skipped %d bytes to sync on TS packet", count);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
bytesDeliveredM = TS_SIZE;
|
isPacketDeliveredM = true;
|
||||||
if (availableP)
|
if (availableP)
|
||||||
*availableP = count;
|
*availableP = count;
|
||||||
// Update pid statistics
|
// Update pid statistics
|
||||||
@ -560,33 +420,35 @@ uchar *cSatipDevice::GetData(int *availableP, bool checkTsBuffer)
|
|||||||
|
|
||||||
void cSatipDevice::SkipData(int countP)
|
void cSatipDevice::SkipData(int countP)
|
||||||
{
|
{
|
||||||
debug16("%s [device %u]", __PRETTY_FUNCTION__, deviceIndexM);
|
//debug("cSatipDevice::%s(%u)", __FUNCTION__, deviceIndexM);
|
||||||
bytesDeliveredM = countP;
|
tsBufferM->Del(countP);
|
||||||
|
isPacketDeliveredM = false;
|
||||||
// Update buffer statistics
|
// Update buffer statistics
|
||||||
AddBufferStatistic(countP, tsBufferM->Available());
|
AddBufferStatistic(countP, tsBufferM->Available());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool cSatipDevice::GetTSPacket(uchar *&dataP)
|
bool cSatipDevice::GetTSPacket(uchar *&dataP)
|
||||||
{
|
{
|
||||||
debug16("%s [device %u]", __PRETTY_FUNCTION__, deviceIndexM);
|
//debug("cSatipDevice::%s(%u)", __FUNCTION__, deviceIndexM);
|
||||||
if (SatipConfig.GetDetachedMode())
|
|
||||||
return false;
|
|
||||||
if (tsBufferM) {
|
if (tsBufferM) {
|
||||||
|
#if defined(APIVERSNUM) && APIVERSNUM >= 20104
|
||||||
if (cCamSlot *cs = CamSlot()) {
|
if (cCamSlot *cs = CamSlot()) {
|
||||||
if (cs->WantsTsData()) {
|
if (cs->WantsTsData()) {
|
||||||
int available;
|
int available;
|
||||||
dataP = GetData(&available, checkTsBufferM);
|
dataP = GetData(&available);
|
||||||
if (!dataP)
|
if (dataP) {
|
||||||
available = 0;
|
dataP = cs->Decrypt(dataP, available);
|
||||||
dataP = cs->Decrypt(dataP, available);
|
SkipData(available);
|
||||||
SkipData(available);
|
}
|
||||||
checkTsBufferM = dataP != NULL;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
dataP = GetData();
|
dataP = GetData();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
// Reduce cpu load by preventing busylooping
|
||||||
|
cCondWait::SleepMs(10);
|
||||||
dataP = NULL;
|
dataP = NULL;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
24
device.h
24
device.h
@ -18,34 +18,31 @@
|
|||||||
class cSatipDevice : public cDevice, public cSatipPidStatistics, public cSatipBufferStatistics, public cSatipDeviceIf {
|
class cSatipDevice : public cDevice, public cSatipPidStatistics, public cSatipBufferStatistics, public cSatipDeviceIf {
|
||||||
// static ones
|
// static ones
|
||||||
public:
|
public:
|
||||||
static cMutex mutexS;
|
static unsigned int deviceCount;
|
||||||
static bool Initialize(unsigned int DeviceCount);
|
static bool Initialize(unsigned int DeviceCount);
|
||||||
static void Shutdown(void);
|
static void Shutdown(void);
|
||||||
static unsigned int Count(void);
|
static unsigned int Count(void);
|
||||||
static cSatipDevice *GetSatipDevice(int CardIndex);
|
static cSatipDevice *GetSatipDevice(int CardIndex);
|
||||||
static cString GetSatipStatus(void);
|
|
||||||
|
|
||||||
// private parts
|
// private parts
|
||||||
private:
|
private:
|
||||||
enum {
|
enum {
|
||||||
eReadyTimeoutMs = 2000, // in milliseconds
|
eReadyTimeoutMs = 2000 // in milliseconds
|
||||||
eTuningTimeoutMs = 1000 // in milliseconds
|
|
||||||
};
|
};
|
||||||
unsigned int deviceIndexM;
|
unsigned int deviceIndexM;
|
||||||
int bytesDeliveredM;
|
bool isPacketDeliveredM;
|
||||||
bool isOpenDvrM;
|
bool isOpenDvrM;
|
||||||
bool checkTsBufferM;
|
|
||||||
cString deviceNameM;
|
cString deviceNameM;
|
||||||
cChannel channelM;
|
cChannel channelM;
|
||||||
cRingBufferLinear *tsBufferM;
|
cRingBufferLinear *tsBufferM;
|
||||||
cSatipTuner *pTunerM;
|
cSatipTuner *pTunerM;
|
||||||
cSatipSectionFilterHandler *pSectionFilterHandlerM;
|
cSatipSectionFilterHandler *pSectionFilterHandlerM;
|
||||||
cTimeMs createdM;
|
cTimeMs createdM;
|
||||||
cCondVar tunedM;
|
cMutex mutexM;
|
||||||
|
|
||||||
// constructor & destructor
|
// constructor & destructor
|
||||||
public:
|
public:
|
||||||
explicit cSatipDevice(unsigned int deviceIndexP);
|
cSatipDevice(unsigned int deviceIndexP);
|
||||||
virtual ~cSatipDevice();
|
virtual ~cSatipDevice();
|
||||||
cString GetInformation(unsigned int pageP = SATIP_DEVICE_INFO_ALL);
|
cString GetInformation(unsigned int pageP = SATIP_DEVICE_INFO_ALL);
|
||||||
|
|
||||||
@ -65,7 +62,6 @@ public:
|
|||||||
virtual cString DeviceType(void) const;
|
virtual cString DeviceType(void) const;
|
||||||
virtual cString DeviceName(void) const;
|
virtual cString DeviceName(void) const;
|
||||||
virtual bool AvoidRecording(void) const;
|
virtual bool AvoidRecording(void) const;
|
||||||
virtual bool SignalStats(int &Valid, double *Strength = NULL, double *Cnr = NULL, double *BerPre = NULL, double *BerPost = NULL, double *Per = NULL, int *Status = NULL) const;
|
|
||||||
virtual int SignalStrength(void) const;
|
virtual int SignalStrength(void) const;
|
||||||
virtual int SignalQuality(void) const;
|
virtual int SignalQuality(void) const;
|
||||||
|
|
||||||
@ -85,7 +81,7 @@ protected:
|
|||||||
|
|
||||||
// for recording
|
// for recording
|
||||||
private:
|
private:
|
||||||
uchar *GetData(int *availableP = NULL, bool checkTsBuffer = false);
|
uchar *GetData(int *availableP = NULL);
|
||||||
void SkipData(int countP);
|
void SkipData(int countP);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
@ -101,7 +97,7 @@ public:
|
|||||||
|
|
||||||
// for transponder lock
|
// for transponder lock
|
||||||
public:
|
public:
|
||||||
virtual bool HasLock(int timeoutMsP = 0) const;
|
virtual bool HasLock(int timeoutMsP) const;
|
||||||
|
|
||||||
// for common interface
|
// for common interface
|
||||||
public:
|
public:
|
||||||
@ -110,12 +106,8 @@ public:
|
|||||||
// for internal device interface
|
// for internal device interface
|
||||||
public:
|
public:
|
||||||
virtual void WriteData(u_char *bufferP, int lengthP);
|
virtual void WriteData(u_char *bufferP, int lengthP);
|
||||||
virtual void SetChannelTuned(void);
|
virtual unsigned int CheckData(void);
|
||||||
virtual int GetId(void);
|
virtual int GetId(void);
|
||||||
virtual int GetPmtPid(void);
|
|
||||||
virtual int GetCISlot(void);
|
|
||||||
virtual cString GetTnrParameterString(void);
|
|
||||||
virtual bool IsIdle(void);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // __SATIP_DEVICE_H
|
#endif // __SATIP_DEVICE_H
|
||||||
|
@ -13,15 +13,11 @@ public:
|
|||||||
cSatipDeviceIf() {}
|
cSatipDeviceIf() {}
|
||||||
virtual ~cSatipDeviceIf() {}
|
virtual ~cSatipDeviceIf() {}
|
||||||
virtual void WriteData(u_char *bufferP, int lengthP) = 0;
|
virtual void WriteData(u_char *bufferP, int lengthP) = 0;
|
||||||
virtual void SetChannelTuned(void) = 0;
|
virtual unsigned int CheckData(void) = 0;
|
||||||
virtual int GetId(void) = 0;
|
virtual int GetId(void) = 0;
|
||||||
virtual int GetPmtPid(void) = 0;
|
|
||||||
virtual int GetCISlot(void) = 0;
|
|
||||||
virtual cString GetTnrParameterString(void) = 0;
|
|
||||||
virtual bool IsIdle(void) = 0;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
explicit cSatipDeviceIf(const cSatipDeviceIf&);
|
cSatipDeviceIf(const cSatipDeviceIf&);
|
||||||
cSatipDeviceIf& operator=(const cSatipDeviceIf&);
|
cSatipDeviceIf& operator=(const cSatipDeviceIf&);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
478
discover.c
478
discover.c
@ -13,12 +13,18 @@
|
|||||||
#endif
|
#endif
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "log.h"
|
|
||||||
#include "socket.h"
|
#include "socket.h"
|
||||||
#include "discover.h"
|
#include "discover.h"
|
||||||
|
|
||||||
cSatipDiscover *cSatipDiscover::instanceS = NULL;
|
cSatipDiscover *cSatipDiscover::instanceS = NULL;
|
||||||
|
|
||||||
|
const char *cSatipDiscover::bcastAddressS = "239.255.255.250";
|
||||||
|
const char *cSatipDiscover::bcastMessageS = "M-SEARCH * HTTP/1.1\r\n" \
|
||||||
|
"HOST: 239.255.255.250:1900\r\n" \
|
||||||
|
"MAN: \"ssdp:discover\"\r\n" \
|
||||||
|
"ST: urn:ses-com:device:SatIPServer:1\r\n" \
|
||||||
|
"MX: 2\r\n\r\n";
|
||||||
|
|
||||||
cSatipDiscover *cSatipDiscover::GetInstance(void)
|
cSatipDiscover *cSatipDiscover::GetInstance(void)
|
||||||
{
|
{
|
||||||
if (!instanceS)
|
if (!instanceS)
|
||||||
@ -26,105 +32,87 @@ cSatipDiscover *cSatipDiscover::GetInstance(void)
|
|||||||
return instanceS;
|
return instanceS;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool cSatipDiscover::Initialize(cSatipDiscoverServers *serversP)
|
bool cSatipDiscover::Initialize(void)
|
||||||
{
|
{
|
||||||
debug1("%s", __PRETTY_FUNCTION__);
|
debug("cSatipDiscover::%s()", __FUNCTION__);
|
||||||
if (instanceS) {
|
if (instanceS)
|
||||||
if (serversP) {
|
instanceS->Activate();
|
||||||
for (cSatipDiscoverServer *s = serversP->First(); s; s = serversP->Next(s))
|
|
||||||
instanceS->AddServer(s->SrcAddress(), s->IpAddress(), s->IpPort(), s->Model(), s->Filters(), s->Description(), s->Quirk());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
instanceS->Activate();
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void cSatipDiscover::Destroy(void)
|
void cSatipDiscover::Destroy(void)
|
||||||
{
|
{
|
||||||
debug1("%s", __PRETTY_FUNCTION__);
|
debug("cSatipDiscover::%s()", __FUNCTION__);
|
||||||
if (instanceS)
|
if (instanceS)
|
||||||
instanceS->Deactivate();
|
instanceS->Deactivate();
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t cSatipDiscover::HeaderCallback(char *ptrP, size_t sizeP, size_t nmembP, void *dataP)
|
size_t cSatipDiscover::WriteCallback(char *ptrP, size_t sizeP, size_t nmembP, void *dataP)
|
||||||
{
|
{
|
||||||
cSatipDiscover *obj = reinterpret_cast<cSatipDiscover *>(dataP);
|
cSatipDiscover *obj = reinterpret_cast<cSatipDiscover *>(dataP);
|
||||||
size_t len = sizeP * nmembP;
|
size_t len = sizeP * nmembP;
|
||||||
debug16("%s len=%zu", __PRETTY_FUNCTION__, len);
|
//debug("cSatipDiscover::%s(%zu)", __FUNCTION__, len);
|
||||||
|
|
||||||
if (obj && (len > 0))
|
|
||||||
obj->headerBufferM.Add(ptrP, len);
|
|
||||||
|
|
||||||
return len;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t cSatipDiscover::DataCallback(char *ptrP, size_t sizeP, size_t nmembP, void *dataP)
|
|
||||||
{
|
|
||||||
cSatipDiscover *obj = reinterpret_cast<cSatipDiscover *>(dataP);
|
|
||||||
size_t len = sizeP * nmembP;
|
|
||||||
debug16("%s len=%zu", __PRETTY_FUNCTION__, len);
|
|
||||||
|
|
||||||
if (obj && (len > 0))
|
|
||||||
obj->dataBufferM.Add(ptrP, len);
|
|
||||||
|
|
||||||
return len;
|
|
||||||
}
|
|
||||||
|
|
||||||
int cSatipDiscover::DebugCallback(CURL *handleP, curl_infotype typeP, char *dataP, size_t sizeP, void *userPtrP)
|
|
||||||
{
|
|
||||||
cSatipDiscover *obj = reinterpret_cast<cSatipDiscover *>(userPtrP);
|
|
||||||
|
|
||||||
if (obj) {
|
if (obj) {
|
||||||
switch (typeP) {
|
CURLcode res = CURLE_OK;
|
||||||
case CURLINFO_TEXT:
|
const char *desc = NULL, *model = NULL, *addr = NULL;
|
||||||
debug2("%s HTTP INFO %.*s", __PRETTY_FUNCTION__, (int)sizeP, dataP);
|
#ifdef USE_TINYXML
|
||||||
break;
|
TiXmlDocument doc;
|
||||||
case CURLINFO_HEADER_IN:
|
char *xml = MALLOC(char, len + 1);
|
||||||
debug2("%s HTTP HEAD <<< %.*s", __PRETTY_FUNCTION__, (int)sizeP, dataP);
|
memcpy(xml, ptrP, len);
|
||||||
break;
|
*(xml + len + 1) = 0;
|
||||||
case CURLINFO_HEADER_OUT:
|
doc.Parse((const char *)xml);
|
||||||
debug2("%s HTTP HEAD >>>\n%.*s", __PRETTY_FUNCTION__, (int)sizeP, dataP);
|
TiXmlHandle docHandle(&doc);
|
||||||
break;
|
TiXmlElement *descElement = docHandle.FirstChild("root").FirstChild("device").FirstChild("friendlyName").ToElement();
|
||||||
case CURLINFO_DATA_IN:
|
if (descElement)
|
||||||
debug2("%s HTTP DATA <<< %.*s", __PRETTY_FUNCTION__, (int)sizeP, dataP);
|
desc = descElement->GetText() ? descElement->GetText() : "MyBrokenHardware";
|
||||||
break;
|
TiXmlElement *modelElement = docHandle.FirstChild("root").FirstChild("device").FirstChild("satip:X_SATIPCAP").ToElement();
|
||||||
case CURLINFO_DATA_OUT:
|
if (modelElement)
|
||||||
debug2("%s HTTP DATA >>>\n%.*s", __PRETTY_FUNCTION__, (int)sizeP, dataP);
|
model = modelElement->GetText() ? modelElement->GetText() : "DVBS2-1";
|
||||||
break;
|
#else
|
||||||
default:
|
pugi::xml_document doc;
|
||||||
break;
|
pugi::xml_parse_result result = doc.load_buffer(ptrP, len);
|
||||||
}
|
if (result) {
|
||||||
|
pugi::xml_node descNode = doc.first_element_by_path("root/device/friendlyName");
|
||||||
|
if (descNode)
|
||||||
|
desc = descNode.text().as_string("MyBrokenHardware");
|
||||||
|
pugi::xml_node modelNode = doc.first_element_by_path("root/device/satip:X_SATIPCAP");
|
||||||
|
if (modelNode)
|
||||||
|
model = modelNode.text().as_string("DVBS2-1");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
SATIP_CURL_EASY_GETINFO(obj->handleM, CURLINFO_PRIMARY_IP, &addr);
|
||||||
|
obj->AddServer(addr, desc, model);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
cSatipDiscover::cSatipDiscover()
|
cSatipDiscover::cSatipDiscover()
|
||||||
: cThread("SATIP discover"),
|
: cThread("SAT>IP discover"),
|
||||||
mutexM(),
|
mutexM(),
|
||||||
headerBufferM(),
|
|
||||||
dataBufferM(),
|
|
||||||
msearchM(*this),
|
|
||||||
probeUrlListM(),
|
|
||||||
handleM(curl_easy_init()),
|
handleM(curl_easy_init()),
|
||||||
|
socketM(new cSatipSocket()),
|
||||||
sleepM(),
|
sleepM(),
|
||||||
probeIntervalM(0),
|
probeIntervalM(0),
|
||||||
serversM()
|
serversM(new cSatipServers())
|
||||||
{
|
{
|
||||||
debug1("%s", __PRETTY_FUNCTION__);
|
debug("cSatipDiscover::%s()", __FUNCTION__);
|
||||||
|
// Start the thread
|
||||||
|
Start();
|
||||||
}
|
}
|
||||||
|
|
||||||
cSatipDiscover::~cSatipDiscover()
|
cSatipDiscover::~cSatipDiscover()
|
||||||
{
|
{
|
||||||
debug1("%s", __PRETTY_FUNCTION__);
|
debug("cSatipDiscover::%s()", __FUNCTION__);
|
||||||
Deactivate();
|
Deactivate();
|
||||||
cMutexLock MutexLock(&mutexM);
|
cMutexLock MutexLock(&mutexM);
|
||||||
// Free allocated memory
|
// Free allocated memory
|
||||||
|
DELETENULL(socketM);
|
||||||
|
DELETENULL(serversM);
|
||||||
if (handleM)
|
if (handleM)
|
||||||
curl_easy_cleanup(handleM);
|
curl_easy_cleanup(handleM);
|
||||||
handleM = NULL;
|
handleM = NULL;
|
||||||
probeUrlListM.Clear();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void cSatipDiscover::Activate(void)
|
void cSatipDiscover::Activate(void)
|
||||||
@ -135,7 +123,7 @@ void cSatipDiscover::Activate(void)
|
|||||||
|
|
||||||
void cSatipDiscover::Deactivate(void)
|
void cSatipDiscover::Deactivate(void)
|
||||||
{
|
{
|
||||||
debug1("%s", __PRETTY_FUNCTION__);
|
debug("cSatipDiscover::%s()", __FUNCTION__);
|
||||||
cMutexLock MutexLock(&mutexM);
|
cMutexLock MutexLock(&mutexM);
|
||||||
sleepM.Signal();
|
sleepM.Signal();
|
||||||
if (Running())
|
if (Running())
|
||||||
@ -144,163 +132,131 @@ void cSatipDiscover::Deactivate(void)
|
|||||||
|
|
||||||
void cSatipDiscover::Action(void)
|
void cSatipDiscover::Action(void)
|
||||||
{
|
{
|
||||||
debug1("%s Entering", __PRETTY_FUNCTION__);
|
debug("cSatipDiscover::%s(): entering", __FUNCTION__);
|
||||||
probeIntervalM.Set(eProbeIntervalMs);
|
|
||||||
msearchM.Probe();
|
|
||||||
// Do the thread loop
|
// Do the thread loop
|
||||||
while (Running()) {
|
while (Running()) {
|
||||||
cStringList tmp;
|
|
||||||
|
|
||||||
if (probeIntervalM.TimedOut()) {
|
if (probeIntervalM.TimedOut()) {
|
||||||
probeIntervalM.Set(eProbeIntervalMs);
|
probeIntervalM.Set(eProbeIntervalMs);
|
||||||
msearchM.Probe();
|
Probe();
|
||||||
mutexM.Lock();
|
Janitor();
|
||||||
serversM.Cleanup(eCleanupTimeoutMs);
|
|
||||||
mutexM.Unlock();
|
|
||||||
}
|
|
||||||
mutexM.Lock();
|
|
||||||
if (probeUrlListM.Size()) {
|
|
||||||
for (int i = 0; i < probeUrlListM.Size(); ++i)
|
|
||||||
tmp.Insert(strdup(probeUrlListM.At(i)));
|
|
||||||
probeUrlListM.Clear();
|
|
||||||
}
|
|
||||||
mutexM.Unlock();
|
|
||||||
if (tmp.Size()) {
|
|
||||||
for (int i = 0; i < tmp.Size(); ++i)
|
|
||||||
Fetch(tmp.At(i));
|
|
||||||
tmp.Clear();
|
|
||||||
}
|
}
|
||||||
// to avoid busy loop and reduce cpu load
|
// to avoid busy loop and reduce cpu load
|
||||||
sleepM.Wait(eSleepTimeoutMs);
|
sleepM.Wait(10);
|
||||||
}
|
}
|
||||||
debug1("%s Exiting", __PRETTY_FUNCTION__);
|
debug("cSatipDiscover::%s(): exiting", __FUNCTION__);
|
||||||
}
|
}
|
||||||
|
|
||||||
void cSatipDiscover::Fetch(const char *urlP)
|
void cSatipDiscover::Janitor(void)
|
||||||
{
|
{
|
||||||
debug1("%s (%s)", __PRETTY_FUNCTION__, urlP);
|
debug("cSatipDiscover::%s()", __FUNCTION__);
|
||||||
if (handleM && !isempty(urlP)) {
|
|
||||||
const char *addr = NULL;
|
|
||||||
long rc = 0;
|
|
||||||
CURLcode res = CURLE_OK;
|
|
||||||
|
|
||||||
// Verbose output
|
|
||||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_VERBOSE, 1L);
|
|
||||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_DEBUGFUNCTION, cSatipDiscover::DebugCallback);
|
|
||||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_DEBUGDATA, this);
|
|
||||||
|
|
||||||
// Set header and data callbacks
|
|
||||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_HEADERFUNCTION, cSatipDiscover::HeaderCallback);
|
|
||||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEHEADER, this);
|
|
||||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEFUNCTION, cSatipDiscover::DataCallback);
|
|
||||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEDATA, this);
|
|
||||||
|
|
||||||
// No progress meter and no signaling
|
|
||||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_NOPROGRESS, 1L);
|
|
||||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_NOSIGNAL, 1L);
|
|
||||||
|
|
||||||
// Set timeouts
|
|
||||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_TIMEOUT_MS, (long)eConnectTimeoutMs);
|
|
||||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_CONNECTTIMEOUT_MS, (long)eConnectTimeoutMs);
|
|
||||||
|
|
||||||
// Set user-agent
|
|
||||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_USERAGENT, *cString::sprintf("vdr-%s/%s", PLUGIN_NAME_I18N, VERSION));
|
|
||||||
|
|
||||||
// Set URL
|
|
||||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_URL, urlP);
|
|
||||||
|
|
||||||
// Fetch the data
|
|
||||||
SATIP_CURL_EASY_PERFORM(handleM);
|
|
||||||
SATIP_CURL_EASY_GETINFO(handleM, CURLINFO_RESPONSE_CODE, &rc);
|
|
||||||
SATIP_CURL_EASY_GETINFO(handleM, CURLINFO_PRIMARY_IP, &addr);
|
|
||||||
if (rc == 200) {
|
|
||||||
ParseDeviceInfo(addr, ParseRtspPort());
|
|
||||||
headerBufferM.Reset();
|
|
||||||
dataBufferM.Reset();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
error("Discovery detected invalid status code: %ld", rc);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int cSatipDiscover::ParseRtspPort(void)
|
|
||||||
{
|
|
||||||
debug1("%s", __PRETTY_FUNCTION__);
|
|
||||||
char *s, *p = headerBufferM.Data();
|
|
||||||
char *r = strtok_r(p, "\r\n", &s);
|
|
||||||
int port = SATIP_DEFAULT_RTSP_PORT;
|
|
||||||
|
|
||||||
while (r) {
|
|
||||||
debug16("%s (%zu): %s", __PRETTY_FUNCTION__, headerBufferM.Size(), r);
|
|
||||||
r = skipspace(r);
|
|
||||||
if (strstr(r, "X-SATIP-RTSP-Port")) {
|
|
||||||
int tmp = -1;
|
|
||||||
if (sscanf(r, "X-SATIP-RTSP-Port:%11d", &tmp) == 1) {
|
|
||||||
port = tmp;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
r = strtok_r(NULL, "\r\n", &s);
|
|
||||||
}
|
|
||||||
|
|
||||||
return port;
|
|
||||||
}
|
|
||||||
|
|
||||||
void cSatipDiscover::ParseDeviceInfo(const char *addrP, const int portP)
|
|
||||||
{
|
|
||||||
debug1("%s (%s, %d)", __PRETTY_FUNCTION__, addrP, portP);
|
|
||||||
const char *desc = NULL, *model = NULL;
|
|
||||||
#ifdef USE_TINYXML
|
|
||||||
TiXmlDocument doc;
|
|
||||||
doc.Parse(dataBufferM.Data());
|
|
||||||
TiXmlHandle docHandle(&doc);
|
|
||||||
TiXmlElement *descElement = docHandle.FirstChild("root").FirstChild("device").FirstChild("friendlyName").ToElement();
|
|
||||||
if (descElement)
|
|
||||||
desc = descElement->GetText() ? descElement->GetText() : "MyBrokenHardware";
|
|
||||||
TiXmlElement *modelElement = docHandle.FirstChild("root").FirstChild("device").FirstChild("satip:X_SATIPCAP").ToElement();
|
|
||||||
if (modelElement)
|
|
||||||
model = modelElement->GetText() ? modelElement->GetText() : "DVBS2-1";
|
|
||||||
#else
|
|
||||||
pugi::xml_document doc;
|
|
||||||
if (doc.load_buffer(dataBufferM.Data(), dataBufferM.Size())) {
|
|
||||||
pugi::xml_node descNode = doc.first_element_by_path("root/device/friendlyName");
|
|
||||||
if (descNode)
|
|
||||||
desc = descNode.text().as_string("MyBrokenHardware");
|
|
||||||
pugi::xml_node modelNode = doc.first_element_by_path("root/device/satip:X_SATIPCAP");
|
|
||||||
if (modelNode)
|
|
||||||
model = modelNode.text().as_string("DVBS2-1");
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
AddServer(NULL, addrP, portP, model, NULL, desc, cSatipServer::eSatipQuirkNone);
|
|
||||||
}
|
|
||||||
|
|
||||||
void cSatipDiscover::AddServer(const char *srcAddrP, const char *addrP, const int portP, const char *modelP, const char *filtersP, const char *descP, const int quirkP)
|
|
||||||
{
|
|
||||||
debug1("%s (%s, %s, %d, %s, %s, %s, %d)", __PRETTY_FUNCTION__, srcAddrP, addrP, portP, modelP, filtersP, descP, quirkP);
|
|
||||||
cMutexLock MutexLock(&mutexM);
|
cMutexLock MutexLock(&mutexM);
|
||||||
if (SatipConfig.GetUseSingleModelServers() && modelP && !isempty(modelP)) {
|
if (serversM)
|
||||||
int n = 0;
|
serversM->Cleanup(eProbeIntervalMs * 2);
|
||||||
char *s, *p = strdup(modelP);
|
}
|
||||||
char *r = strtok_r(p, ",", &s);
|
|
||||||
while (r) {
|
void cSatipDiscover::Probe(void)
|
||||||
r = skipspace(r);
|
{
|
||||||
cString desc = cString::sprintf("%s #%d", !isempty(descP) ? descP : "MyBrokenHardware", n++);
|
debug("cSatipDiscover::%s()", __FUNCTION__);
|
||||||
cSatipServer *tmp = new cSatipServer(srcAddrP, addrP, portP, r, filtersP, desc, quirkP);
|
if (socketM && socketM->Open(eDiscoveryPort)) {
|
||||||
if (!serversM.Update(tmp)) {
|
cTimeMs timeout(eProbeTimeoutMs);
|
||||||
info("Adding server '%s|%s|%s' Bind: %s Filters: %s CI: %s Quirks: %s", tmp->Address(), tmp->Model(), tmp->Description(), !isempty(tmp->SrcAddress()) ? tmp->SrcAddress() : "default", !isempty(tmp->Filters()) ? tmp->Filters() : "none", tmp->HasCI() ? "yes" : "no", tmp->HasQuirk() ? tmp->Quirks() : "none");
|
socketM->Write(bcastAddressS, reinterpret_cast<const unsigned char *>(bcastMessageS), strlen(bcastMessageS));
|
||||||
serversM.Add(tmp);
|
while (Running() && !timeout.TimedOut()) {
|
||||||
}
|
Read();
|
||||||
else
|
// to avoid busy loop and reduce cpu load
|
||||||
DELETENULL(tmp);
|
sleepM.Wait(100);
|
||||||
r = strtok_r(NULL, ",", &s);
|
|
||||||
}
|
}
|
||||||
FREE_POINTER(p);
|
socketM->Close();
|
||||||
}
|
}
|
||||||
else {
|
}
|
||||||
cSatipServer *tmp = new cSatipServer(srcAddrP, addrP, portP, modelP, filtersP, descP, quirkP);
|
|
||||||
if (!serversM.Update(tmp)) {
|
void cSatipDiscover::Read(void)
|
||||||
info("Adding server '%s|%s|%s' Bind: %s Filters: %s CI: %s Quirks: %s", tmp->Address(), tmp->Model(), tmp->Description(), !isempty(tmp->SrcAddress()) ? tmp->SrcAddress() : "default", !isempty(tmp->Filters()) ? tmp->Filters() : "none", tmp->HasCI() ? "yes" : "no", tmp->HasQuirk() ? tmp->Quirks() : "none");
|
{
|
||||||
serversM.Add(tmp);
|
//debug("cSatipDiscover::%s()", __FUNCTION__);
|
||||||
|
if (socketM) {
|
||||||
|
unsigned char *buf = MALLOC(unsigned char, eProbeBufferSize + 1);
|
||||||
|
if (buf) {
|
||||||
|
memset(buf, 0, eProbeBufferSize + 1);
|
||||||
|
int len = socketM->Read(buf, eProbeBufferSize);
|
||||||
|
if (len > 0) {
|
||||||
|
//debug("cSatipDiscover::%s(): len=%d", __FUNCTION__, len);
|
||||||
|
bool status = false, valid = false;
|
||||||
|
char *s, *p = reinterpret_cast<char *>(buf), *location = NULL;
|
||||||
|
char *r = strtok_r(p, "\r\n", &s);
|
||||||
|
while (r) {
|
||||||
|
//debug("cSatipDiscover::%s(): %s", __FUNCTION__, r);
|
||||||
|
// Check the status code
|
||||||
|
// HTTP/1.1 200 OK
|
||||||
|
if (!status && startswith(r, "HTTP/1.1 200 OK")) {
|
||||||
|
status = true;
|
||||||
|
}
|
||||||
|
if (status) {
|
||||||
|
// Check the location data
|
||||||
|
// LOCATION: http://192.168.0.115:8888/octonet.xml
|
||||||
|
if (startswith(r, "LOCATION:")) {
|
||||||
|
location = compactspace(r + 9);
|
||||||
|
debug("cSatipDiscover::%s(): location='%s'", __FUNCTION__, location);
|
||||||
|
}
|
||||||
|
// Check the source type
|
||||||
|
// ST: urn:ses-com:device:SatIPServer:1
|
||||||
|
else if (startswith(r, "ST:")) {
|
||||||
|
char *st = compactspace(r + 3);
|
||||||
|
if (strstr(st, "urn:ses-com:device:SatIPServer:1"))
|
||||||
|
valid = true;
|
||||||
|
debug("cSatipDiscover::%s(): st='%s'", __FUNCTION__, st);
|
||||||
|
}
|
||||||
|
// Check whether all the required data is found
|
||||||
|
if (valid && !isempty(location))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
r = strtok_r(NULL, "\r\n", &s);
|
||||||
|
}
|
||||||
|
if (handleM && valid && !isempty(location)) {
|
||||||
|
long rc = 0;
|
||||||
|
CURLcode res = CURLE_OK;
|
||||||
|
#ifdef DEBUG
|
||||||
|
// Verbose output
|
||||||
|
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_VERBOSE, 1L);
|
||||||
|
#endif
|
||||||
|
// Set callback
|
||||||
|
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEFUNCTION, cSatipDiscover::WriteCallback);
|
||||||
|
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEDATA, this);
|
||||||
|
|
||||||
|
// No progress meter and no signaling
|
||||||
|
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_NOPROGRESS, 1L);
|
||||||
|
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_NOSIGNAL, 1L);
|
||||||
|
|
||||||
|
// Set timeouts
|
||||||
|
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_TIMEOUT_MS, (long)eConnectTimeoutMs);
|
||||||
|
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_CONNECTTIMEOUT_MS, (long)eConnectTimeoutMs);
|
||||||
|
|
||||||
|
// Set user-agent
|
||||||
|
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_USERAGENT, *cString::sprintf("vdr-%s/%s", PLUGIN_NAME_I18N, VERSION));
|
||||||
|
|
||||||
|
// Set URL
|
||||||
|
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_URL, location);
|
||||||
|
|
||||||
|
// Fetch the data
|
||||||
|
SATIP_CURL_EASY_PERFORM(handleM);
|
||||||
|
SATIP_CURL_EASY_GETINFO(handleM, CURLINFO_RESPONSE_CODE, &rc);
|
||||||
|
if (rc != 200)
|
||||||
|
error("Discovery detected invalid status code: %ld", rc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free(buf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void cSatipDiscover::AddServer(const char *addrP, const char *descP, const char * modelP)
|
||||||
|
{
|
||||||
|
debug("cSatipDiscover::%s(%s, %s, %s)", __FUNCTION__, addrP, descP, modelP);
|
||||||
|
cMutexLock MutexLock(&mutexM);
|
||||||
|
if (serversM) {
|
||||||
|
cSatipServer *tmp = new cSatipServer(addrP, descP, modelP);
|
||||||
|
// Validate against existing servers
|
||||||
|
if (!serversM->Update(tmp)) {
|
||||||
|
info("Adding device %s (%s %s)", tmp->Description(), tmp->Address(), tmp->Model());
|
||||||
|
serversM->Add(tmp);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
DELETENULL(tmp);
|
DELETENULL(tmp);
|
||||||
@ -309,121 +265,57 @@ void cSatipDiscover::AddServer(const char *srcAddrP, const char *addrP, const in
|
|||||||
|
|
||||||
int cSatipDiscover::GetServerCount(void)
|
int cSatipDiscover::GetServerCount(void)
|
||||||
{
|
{
|
||||||
debug16("%s", __PRETTY_FUNCTION__);
|
//debug("cSatipDiscover::%s()", __FUNCTION__);
|
||||||
cMutexLock MutexLock(&mutexM);
|
cMutexLock MutexLock(&mutexM);
|
||||||
return serversM.Count();
|
return serversM ? serversM->Count() : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
cSatipServer *cSatipDiscover::AssignServer(int deviceIdP, int sourceP, int transponderP, int systemP)
|
cSatipServer *cSatipDiscover::GetServer(int sourceP, int systemP)
|
||||||
{
|
{
|
||||||
debug16("%s (%d, %d, %d, %d)", __PRETTY_FUNCTION__, deviceIdP, sourceP, transponderP, systemP);
|
//debug("cSatipDiscover::%s(%d, %d)", __FUNCTION__, sourceP, systemP);
|
||||||
cMutexLock MutexLock(&mutexM);
|
cMutexLock MutexLock(&mutexM);
|
||||||
return serversM.Assign(deviceIdP, sourceP, transponderP, systemP);
|
return serversM ? serversM->Find(sourceP, systemP) : NULL;
|
||||||
}
|
|
||||||
|
|
||||||
cSatipServer *cSatipDiscover::GetServer(int sourceP)
|
|
||||||
{
|
|
||||||
debug16("%s (%d)", __PRETTY_FUNCTION__, sourceP);
|
|
||||||
cMutexLock MutexLock(&mutexM);
|
|
||||||
return serversM.Find(sourceP);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cSatipServer *cSatipDiscover::GetServer(cSatipServer *serverP)
|
cSatipServer *cSatipDiscover::GetServer(cSatipServer *serverP)
|
||||||
{
|
{
|
||||||
debug16("%s", __PRETTY_FUNCTION__);
|
//debug("cSatipDiscover::%s()", __FUNCTION__);
|
||||||
cMutexLock MutexLock(&mutexM);
|
cMutexLock MutexLock(&mutexM);
|
||||||
return serversM.Find(serverP);
|
return serversM ? serversM->Find(serverP) : NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
cSatipServers *cSatipDiscover::GetServers(void)
|
cSatipServers *cSatipDiscover::GetServers(void)
|
||||||
{
|
{
|
||||||
debug16("%s", __PRETTY_FUNCTION__);
|
//debug("cSatipDiscover::%s()", __FUNCTION__);
|
||||||
cMutexLock MutexLock(&mutexM);
|
cMutexLock MutexLock(&mutexM);
|
||||||
return &serversM;
|
return serversM;
|
||||||
}
|
}
|
||||||
|
|
||||||
cString cSatipDiscover::GetServerString(cSatipServer *serverP)
|
cString cSatipDiscover::GetServerString(cSatipServer *serverP)
|
||||||
{
|
{
|
||||||
debug16("%s", __PRETTY_FUNCTION__);
|
//debug("cSatipDiscover::%s(%d)", __FUNCTION__, modelP);
|
||||||
cMutexLock MutexLock(&mutexM);
|
cMutexLock MutexLock(&mutexM);
|
||||||
return serversM.GetString(serverP);
|
return serversM ? serversM->GetString(serverP) : "";
|
||||||
}
|
}
|
||||||
|
|
||||||
cString cSatipDiscover::GetServerList(void)
|
cString cSatipDiscover::GetServerList(void)
|
||||||
{
|
{
|
||||||
debug16("%s", __PRETTY_FUNCTION__);
|
//debug("cSatipDiscover::%s(%d)", __FUNCTION__, modelP);
|
||||||
cMutexLock MutexLock(&mutexM);
|
cMutexLock MutexLock(&mutexM);
|
||||||
return serversM.List();
|
return serversM ? serversM->List() : "";
|
||||||
}
|
}
|
||||||
|
|
||||||
void cSatipDiscover::ActivateServer(cSatipServer *serverP, bool onOffP)
|
void cSatipDiscover::UseServer(cSatipServer *serverP, bool onOffP)
|
||||||
{
|
{
|
||||||
debug16("%s (, %d)", __PRETTY_FUNCTION__, onOffP);
|
//debug("cSatipDiscover::%s(%d)", __FUNCTION__, modelP);
|
||||||
cMutexLock MutexLock(&mutexM);
|
cMutexLock MutexLock(&mutexM);
|
||||||
serversM.Activate(serverP, onOffP);
|
if (serversM)
|
||||||
}
|
serversM->Use(serverP, onOffP);
|
||||||
|
|
||||||
void cSatipDiscover::AttachServer(cSatipServer *serverP, int deviceIdP, int transponderP)
|
|
||||||
{
|
|
||||||
debug16("%s (, %d, %d)", __PRETTY_FUNCTION__, deviceIdP, transponderP);
|
|
||||||
cMutexLock MutexLock(&mutexM);
|
|
||||||
serversM.Attach(serverP, deviceIdP, transponderP);
|
|
||||||
}
|
|
||||||
|
|
||||||
void cSatipDiscover::DetachServer(cSatipServer *serverP, int deviceIdP, int transponderP)
|
|
||||||
{
|
|
||||||
debug16("%s (, %d, %d)", __PRETTY_FUNCTION__, deviceIdP, transponderP);
|
|
||||||
cMutexLock MutexLock(&mutexM);
|
|
||||||
serversM.Detach(serverP, deviceIdP, transponderP);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool cSatipDiscover::IsServerQuirk(cSatipServer *serverP, int quirkP)
|
|
||||||
{
|
|
||||||
debug16("%s (, %d)", __PRETTY_FUNCTION__, quirkP);
|
|
||||||
cMutexLock MutexLock(&mutexM);
|
|
||||||
return serversM.IsQuirk(serverP, quirkP);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool cSatipDiscover::HasServerCI(cSatipServer *serverP)
|
|
||||||
{
|
|
||||||
debug16("%s", __PRETTY_FUNCTION__);
|
|
||||||
cMutexLock MutexLock(&mutexM);
|
|
||||||
return serversM.HasCI(serverP);
|
|
||||||
}
|
|
||||||
|
|
||||||
cString cSatipDiscover::GetSourceAddress(cSatipServer *serverP)
|
|
||||||
{
|
|
||||||
debug16("%s", __PRETTY_FUNCTION__);
|
|
||||||
cMutexLock MutexLock(&mutexM);
|
|
||||||
return serversM.GetSrcAddress(serverP);
|
|
||||||
}
|
|
||||||
|
|
||||||
cString cSatipDiscover::GetServerAddress(cSatipServer *serverP)
|
|
||||||
{
|
|
||||||
debug16("%s", __PRETTY_FUNCTION__);
|
|
||||||
cMutexLock MutexLock(&mutexM);
|
|
||||||
return serversM.GetAddress(serverP);
|
|
||||||
}
|
|
||||||
|
|
||||||
int cSatipDiscover::GetServerPort(cSatipServer *serverP)
|
|
||||||
{
|
|
||||||
debug16("%s", __PRETTY_FUNCTION__);
|
|
||||||
cMutexLock MutexLock(&mutexM);
|
|
||||||
return serversM.GetPort(serverP);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int cSatipDiscover::NumProvidedSystems(void)
|
int cSatipDiscover::NumProvidedSystems(void)
|
||||||
{
|
{
|
||||||
debug16("%s", __PRETTY_FUNCTION__);
|
//debug("cSatipDiscover::%s(%d)", __FUNCTION__, modelP);
|
||||||
cMutexLock MutexLock(&mutexM);
|
cMutexLock MutexLock(&mutexM);
|
||||||
return serversM.NumProvidedSystems();
|
return serversM ? serversM->NumProvidedSystems() : 0;
|
||||||
}
|
|
||||||
|
|
||||||
void cSatipDiscover::SetUrl(const char *urlP)
|
|
||||||
{
|
|
||||||
debug16("%s (%s)", __PRETTY_FUNCTION__, urlP);
|
|
||||||
mutexM.Lock();
|
|
||||||
probeUrlListM.Insert(strdup(urlP));
|
|
||||||
mutexM.Unlock();
|
|
||||||
sleepM.Signal();
|
|
||||||
}
|
}
|
||||||
|
80
discover.h
80
discover.h
@ -13,66 +13,34 @@
|
|||||||
#include <vdr/thread.h>
|
#include <vdr/thread.h>
|
||||||
#include <vdr/tools.h>
|
#include <vdr/tools.h>
|
||||||
|
|
||||||
#include "common.h"
|
|
||||||
#include "discoverif.h"
|
|
||||||
#include "msearch.h"
|
|
||||||
#include "server.h"
|
#include "server.h"
|
||||||
#include "socket.h"
|
#include "socket.h"
|
||||||
|
|
||||||
class cSatipDiscoverServer : public cListObject {
|
class cSatipDiscover : public cThread {
|
||||||
private:
|
|
||||||
int ipPortM;
|
|
||||||
int quirkM;
|
|
||||||
cString srcAddressM;
|
|
||||||
cString ipAddressM;
|
|
||||||
cString descriptionM;
|
|
||||||
cString modelM;
|
|
||||||
cString filtersM;
|
|
||||||
public:
|
|
||||||
cSatipDiscoverServer(const char *srcAddressP, const char *ipAddressP, const int ipPortP, const char *modelP, const char *filtersP, const char *descriptionP, const int quirkP)
|
|
||||||
{
|
|
||||||
srcAddressM = srcAddressP; ipAddressM = ipAddressP; ipPortM = ipPortP; modelM = modelP; filtersM = filtersP; descriptionM = descriptionP; quirkM = quirkP;
|
|
||||||
}
|
|
||||||
int IpPort(void) { return ipPortM; }
|
|
||||||
int Quirk(void) { return quirkM; }
|
|
||||||
const char *SrcAddress(void) { return *srcAddressM; }
|
|
||||||
const char *IpAddress(void) { return *ipAddressM; }
|
|
||||||
const char *Model(void) { return *modelM; }
|
|
||||||
const char *Filters(void) { return *filtersM; }
|
|
||||||
const char *Description(void) { return *descriptionM; }
|
|
||||||
};
|
|
||||||
|
|
||||||
class cSatipDiscoverServers : public cList<cSatipDiscoverServer> {
|
|
||||||
};
|
|
||||||
|
|
||||||
class cSatipDiscover : public cThread, public cSatipDiscoverIf {
|
|
||||||
private:
|
private:
|
||||||
enum {
|
enum {
|
||||||
eSleepTimeoutMs = 500, // in milliseconds
|
eConnectTimeoutMs = 1500, // in milliseconds
|
||||||
eConnectTimeoutMs = 1500, // in milliseconds
|
eDiscoveryPort = 1900,
|
||||||
eProbeTimeoutMs = 2000, // in milliseconds
|
eProbeBufferSize = 1024, // in bytes
|
||||||
eProbeIntervalMs = 60000, // in milliseconds
|
eProbeTimeoutMs = 2000, // in milliseconds
|
||||||
eCleanupTimeoutMs = 124000 // in milliseoonds
|
eProbeIntervalMs = 60000 // in milliseconds
|
||||||
};
|
};
|
||||||
static cSatipDiscover *instanceS;
|
static cSatipDiscover *instanceS;
|
||||||
static size_t HeaderCallback(char *ptrP, size_t sizeP, size_t nmembP, void *dataP);
|
static const char *bcastAddressS;
|
||||||
static size_t DataCallback(char *ptrP, size_t sizeP, size_t nmembP, void *dataP);
|
static const char *bcastMessageS;
|
||||||
static int DebugCallback(CURL *handleP, curl_infotype typeP, char *dataP, size_t sizeP, void *userPtrP);
|
static size_t WriteCallback(char *ptrP, size_t sizeP, size_t nmembP, void *dataP);
|
||||||
cMutex mutexM;
|
cMutex mutexM;
|
||||||
cSatipMemoryBuffer headerBufferM;
|
|
||||||
cSatipMemoryBuffer dataBufferM;
|
|
||||||
cSatipMsearch msearchM;
|
|
||||||
cStringList probeUrlListM;
|
|
||||||
CURL *handleM;
|
CURL *handleM;
|
||||||
|
cSatipSocket *socketM;
|
||||||
cCondWait sleepM;
|
cCondWait sleepM;
|
||||||
cTimeMs probeIntervalM;
|
cTimeMs probeIntervalM;
|
||||||
cSatipServers serversM;
|
cSatipServers *serversM;
|
||||||
void Activate(void);
|
void Activate(void);
|
||||||
void Deactivate(void);
|
void Deactivate(void);
|
||||||
int ParseRtspPort(void);
|
void Janitor(void);
|
||||||
void ParseDeviceInfo(const char *addrP, const int portP);
|
void Probe(void);
|
||||||
void AddServer(const char *srcAddrP, const char *addrP, const int portP, const char *modelP, const char *filtersP, const char *descP, const int quirkP);
|
void Read(void);
|
||||||
void Fetch(const char *urlP);
|
void AddServer(const char *addrP, const char *descP, const char *modelP);
|
||||||
// constructor
|
// constructor
|
||||||
cSatipDiscover();
|
cSatipDiscover();
|
||||||
// to prevent copy constructor and assignment
|
// to prevent copy constructor and assignment
|
||||||
@ -84,30 +52,18 @@ protected:
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
static cSatipDiscover *GetInstance(void);
|
static cSatipDiscover *GetInstance(void);
|
||||||
static bool Initialize(cSatipDiscoverServers *serversP);
|
static bool Initialize(void);
|
||||||
static void Destroy(void);
|
static void Destroy(void);
|
||||||
virtual ~cSatipDiscover();
|
virtual ~cSatipDiscover();
|
||||||
void TriggerScan(void) { probeIntervalM.Set(0); }
|
void TriggerScan(void) { probeIntervalM.Set(0); }
|
||||||
int GetServerCount(void);
|
int GetServerCount(void);
|
||||||
cSatipServer *AssignServer(int deviceIdP, int sourceP, int transponderP, int systemP);
|
cSatipServer *GetServer(int sourceP, int systemP = -1);
|
||||||
cSatipServer *GetServer(int sourceP);
|
|
||||||
cSatipServer *GetServer(cSatipServer *serverP);
|
cSatipServer *GetServer(cSatipServer *serverP);
|
||||||
cSatipServers *GetServers(void);
|
cSatipServers *GetServers(void);
|
||||||
cString GetServerString(cSatipServer *serverP);
|
cString GetServerString(cSatipServer *serverP);
|
||||||
void ActivateServer(cSatipServer *serverP, bool onOffP);
|
void UseServer(cSatipServer *serverP, bool onOffP);
|
||||||
void AttachServer(cSatipServer *serverP, int deviceIdP, int transponderP);
|
|
||||||
void DetachServer(cSatipServer *serverP, int deviceIdP, int transponderP);
|
|
||||||
bool IsServerQuirk(cSatipServer *serverP, int quirkP);
|
|
||||||
bool HasServerCI(cSatipServer *serverP);
|
|
||||||
cString GetServerAddress(cSatipServer *serverP);
|
|
||||||
cString GetSourceAddress(cSatipServer *serverP);
|
|
||||||
int GetServerPort(cSatipServer *serverP);
|
|
||||||
cString GetServerList(void);
|
cString GetServerList(void);
|
||||||
int NumProvidedSystems(void);
|
int NumProvidedSystems(void);
|
||||||
|
|
||||||
// for internal discover interface
|
|
||||||
public:
|
|
||||||
virtual void SetUrl(const char *urlP);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // __SATIP_DISCOVER_H
|
#endif // __SATIP_DISCOVER_H
|
||||||
|
22
discoverif.h
22
discoverif.h
@ -1,22 +0,0 @@
|
|||||||
/*
|
|
||||||
* discoverif.h: SAT>IP plugin for the Video Disk Recorder
|
|
||||||
*
|
|
||||||
* See the README file for copyright information and how to reach the author.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef __SATIP_DISCOVERIF_H
|
|
||||||
#define __SATIP_DISCOVERIF_H
|
|
||||||
|
|
||||||
class cSatipDiscoverIf {
|
|
||||||
public:
|
|
||||||
cSatipDiscoverIf() {}
|
|
||||||
virtual ~cSatipDiscoverIf() {}
|
|
||||||
virtual void SetUrl(const char *urlP) = 0;
|
|
||||||
|
|
||||||
private:
|
|
||||||
explicit cSatipDiscoverIf(const cSatipDiscoverIf&);
|
|
||||||
cSatipDiscoverIf& operator=(const cSatipDiscoverIf&);
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // __SATIP_DISCOVERIF_H
|
|
48
log.h
48
log.h
@ -1,48 +0,0 @@
|
|||||||
/*
|
|
||||||
* log.h: SAT>IP plugin for the Video Disk Recorder
|
|
||||||
*
|
|
||||||
* See the README file for copyright information and how to reach the author.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef __SATIP_LOG_H
|
|
||||||
#define __SATIP_LOG_H
|
|
||||||
|
|
||||||
#include "config.h"
|
|
||||||
|
|
||||||
#define error(x...) esyslog("SATIP-ERROR: " x)
|
|
||||||
#define info(x...) isyslog("SATIP: " x)
|
|
||||||
// 0x0001: Generic call stack
|
|
||||||
#define debug1(x...) void( SatipConfig.IsTraceMode(cSatipConfig::eTraceModeDebug1) ? dsyslog("SATIP1: " x) : void() )
|
|
||||||
// 0x0002: CURL data flow
|
|
||||||
#define debug2(x...) void( SatipConfig.IsTraceMode(cSatipConfig::eTraceModeDebug2) ? dsyslog("SATIP2: " x) : void() )
|
|
||||||
// 0x0004: Data parsing
|
|
||||||
#define debug3(x...) void( SatipConfig.IsTraceMode(cSatipConfig::eTraceModeDebug3) ? dsyslog("SATIP3: " x) : void() )
|
|
||||||
// 0x0008: Tuner state machine
|
|
||||||
#define debug4(x...) void( SatipConfig.IsTraceMode(cSatipConfig::eTraceModeDebug4) ? dsyslog("SATIP4: " x) : void() )
|
|
||||||
// 0x0010: RTSP responses
|
|
||||||
#define debug5(x...) void( SatipConfig.IsTraceMode(cSatipConfig::eTraceModeDebug5) ? dsyslog("SATIP5: " x) : void() )
|
|
||||||
// 0x0020: RTP throughput performance
|
|
||||||
#define debug6(x...) void( SatipConfig.IsTraceMode(cSatipConfig::eTraceModeDebug6) ? dsyslog("SATIP6: " x) : void() )
|
|
||||||
// 0x0040: RTP packet internals
|
|
||||||
#define debug7(x...) void( SatipConfig.IsTraceMode(cSatipConfig::eTraceModeDebug7) ? dsyslog("SATIP7: " x) : void() )
|
|
||||||
// 0x0080: Section filtering
|
|
||||||
#define debug8(x...) void( SatipConfig.IsTraceMode(cSatipConfig::eTraceModeDebug8) ? dsyslog("SATIP8: " x) : void() )
|
|
||||||
// 0x0100: Channel switching
|
|
||||||
#define debug9(x...) void( SatipConfig.IsTraceMode(cSatipConfig::eTraceModeDebug9) ? dsyslog("SATIP9: " x) : void() )
|
|
||||||
// 0x0200: RTCP packets
|
|
||||||
#define debug10(x...) void( SatipConfig.IsTraceMode(cSatipConfig::eTraceModeDebug10) ? dsyslog("SATIP10: " x) : void() )
|
|
||||||
// 0x0400: CI
|
|
||||||
#define debug11(x...) void( SatipConfig.IsTraceMode(cSatipConfig::eTraceModeDebug11) ? dsyslog("SATIP11: " x) : void() )
|
|
||||||
// 0x0800: Pids
|
|
||||||
#define debug12(x...) void( SatipConfig.IsTraceMode(cSatipConfig::eTraceModeDebug12) ? dsyslog("SATIP12: " x) : void() )
|
|
||||||
// 0x1000: Discovery
|
|
||||||
#define debug13(x...) void( SatipConfig.IsTraceMode(cSatipConfig::eTraceModeDebug13) ? dsyslog("SATIP13: " x) : void() )
|
|
||||||
// 0x2000: TBD
|
|
||||||
#define debug14(x...) void( SatipConfig.IsTraceMode(cSatipConfig::eTraceModeDebug14) ? dsyslog("SATIP14: " x) : void() )
|
|
||||||
// 0x4000: TBD
|
|
||||||
#define debug15(x...) void( SatipConfig.IsTraceMode(cSatipConfig::eTraceModeDebug15) ? dsyslog("SATIP15: " x) : void() )
|
|
||||||
// 0x8000; Extra call stack
|
|
||||||
#define debug16(x...) void( SatipConfig.IsTraceMode(cSatipConfig::eTraceModeDebug16) ? dsyslog("SATIP16: " x) : void() )
|
|
||||||
|
|
||||||
#endif // __SATIP_LOG_H
|
|
111
msearch.c
111
msearch.c
@ -1,111 +0,0 @@
|
|||||||
/*
|
|
||||||
* msearch.c: SAT>IP plugin for the Video Disk Recorder
|
|
||||||
*
|
|
||||||
* See the README file for copyright information and how to reach the author.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "config.h"
|
|
||||||
#include "common.h"
|
|
||||||
#include "discover.h"
|
|
||||||
#include "log.h"
|
|
||||||
#include "poller.h"
|
|
||||||
#include "msearch.h"
|
|
||||||
|
|
||||||
const char *cSatipMsearch::bcastAddressS = "239.255.255.250";
|
|
||||||
const char *cSatipMsearch::bcastMessageS = "M-SEARCH * HTTP/1.1\r\n" \
|
|
||||||
"HOST: 239.255.255.250:1900\r\n" \
|
|
||||||
"MAN: \"ssdp:discover\"\r\n" \
|
|
||||||
"ST: urn:ses-com:device:SatIPServer:1\r\n" \
|
|
||||||
"MX: 2\r\n\r\n";
|
|
||||||
|
|
||||||
cSatipMsearch::cSatipMsearch(cSatipDiscoverIf &discoverP)
|
|
||||||
: discoverM(discoverP),
|
|
||||||
bufferLenM(eProbeBufferSize),
|
|
||||||
bufferM(MALLOC(unsigned char, bufferLenM)),
|
|
||||||
registeredM(false)
|
|
||||||
{
|
|
||||||
if (bufferM)
|
|
||||||
memset(bufferM, 0, bufferLenM);
|
|
||||||
else
|
|
||||||
error("Cannot create Msearch buffer!");
|
|
||||||
if (!Open(eDiscoveryPort, true))
|
|
||||||
error("Cannot open Msearch port!");
|
|
||||||
}
|
|
||||||
|
|
||||||
cSatipMsearch::~cSatipMsearch()
|
|
||||||
{
|
|
||||||
FREE_POINTER(bufferM);
|
|
||||||
}
|
|
||||||
|
|
||||||
void cSatipMsearch::Probe(void)
|
|
||||||
{
|
|
||||||
debug1("%s", __PRETTY_FUNCTION__);
|
|
||||||
if (!registeredM) {
|
|
||||||
cSatipPoller::GetInstance()->Register(*this);
|
|
||||||
registeredM = true;
|
|
||||||
}
|
|
||||||
// Send two queries with one second interval
|
|
||||||
Write(bcastAddressS, reinterpret_cast<const unsigned char *>(bcastMessageS), strlen(bcastMessageS));
|
|
||||||
cCondWait::SleepMs(1000);
|
|
||||||
Write(bcastAddressS, reinterpret_cast<const unsigned char *>(bcastMessageS), strlen(bcastMessageS));
|
|
||||||
}
|
|
||||||
|
|
||||||
int cSatipMsearch::GetFd(void)
|
|
||||||
{
|
|
||||||
return Fd();
|
|
||||||
}
|
|
||||||
|
|
||||||
void cSatipMsearch::Process(void)
|
|
||||||
{
|
|
||||||
debug16("%s", __PRETTY_FUNCTION__);
|
|
||||||
if (bufferM) {
|
|
||||||
int length;
|
|
||||||
while ((length = Read(bufferM, bufferLenM)) > 0) {
|
|
||||||
bufferM[min(length, int(bufferLenM - 1))] = 0;
|
|
||||||
debug13("%s len=%d buf=%s", __PRETTY_FUNCTION__, length, bufferM);
|
|
||||||
bool status = false, valid = false;
|
|
||||||
char *s, *p = reinterpret_cast<char *>(bufferM), *location = NULL;
|
|
||||||
char *r = strtok_r(p, "\r\n", &s);
|
|
||||||
while (r) {
|
|
||||||
debug13("%s r=%s", __PRETTY_FUNCTION__, r);
|
|
||||||
// Check the status code
|
|
||||||
// HTTP/1.1 200 OK
|
|
||||||
if (!status && startswith(r, "HTTP/1.1 200 OK"))
|
|
||||||
status = true;
|
|
||||||
if (status) {
|
|
||||||
// Check the location data
|
|
||||||
// LOCATION: http://192.168.0.115:8888/octonet.xml
|
|
||||||
if (strcasestr(r, "LOCATION:") == r) {
|
|
||||||
location = compactspace(r + 9);
|
|
||||||
debug1("%s location='%s'", __PRETTY_FUNCTION__, location);
|
|
||||||
}
|
|
||||||
// Check the source type
|
|
||||||
// ST: urn:ses-com:device:SatIPServer:1
|
|
||||||
else if (strcasestr(r, "ST:") == r) {
|
|
||||||
char *st = compactspace(r + 3);
|
|
||||||
if (strstr(st, "urn:ses-com:device:SatIPServer:1"))
|
|
||||||
valid = true;
|
|
||||||
debug1("%s st='%s'", __PRETTY_FUNCTION__, st);
|
|
||||||
}
|
|
||||||
// Check whether all the required data is found
|
|
||||||
if (valid && !isempty(location)) {
|
|
||||||
discoverM.SetUrl(location);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
r = strtok_r(NULL, "\r\n", &s);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void cSatipMsearch::Process(unsigned char *dataP, int lengthP)
|
|
||||||
{
|
|
||||||
debug16("%s", __PRETTY_FUNCTION__);
|
|
||||||
}
|
|
||||||
|
|
||||||
cString cSatipMsearch::ToString(void) const
|
|
||||||
{
|
|
||||||
return "MSearch";
|
|
||||||
}
|
|
41
msearch.h
41
msearch.h
@ -1,41 +0,0 @@
|
|||||||
/*
|
|
||||||
* msearch.h: SAT>IP plugin for the Video Disk Recorder
|
|
||||||
*
|
|
||||||
* See the README file for copyright information and how to reach the author.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef __SATIP_MSEARCH_H_
|
|
||||||
#define __SATIP_MSEARCH_H_
|
|
||||||
|
|
||||||
#include "discoverif.h"
|
|
||||||
#include "socket.h"
|
|
||||||
#include "pollerif.h"
|
|
||||||
|
|
||||||
class cSatipMsearch : public cSatipSocket, public cSatipPollerIf {
|
|
||||||
private:
|
|
||||||
enum {
|
|
||||||
eProbeBufferSize = 1024, // in bytes
|
|
||||||
eDiscoveryPort = 1900,
|
|
||||||
};
|
|
||||||
static const char *bcastAddressS;
|
|
||||||
static const char *bcastMessageS;
|
|
||||||
cSatipDiscoverIf &discoverM;
|
|
||||||
unsigned int bufferLenM;
|
|
||||||
unsigned char *bufferM;
|
|
||||||
bool registeredM;
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit cSatipMsearch(cSatipDiscoverIf &discoverP);
|
|
||||||
virtual ~cSatipMsearch();
|
|
||||||
void Probe(void);
|
|
||||||
|
|
||||||
// for internal poller interface
|
|
||||||
public:
|
|
||||||
virtual int GetFd(void);
|
|
||||||
virtual void Process(void);
|
|
||||||
virtual void Process(unsigned char *dataP, int lengthP);
|
|
||||||
virtual cString ToString(void) const;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif /* __SATIP_MSEARCH_H_ */
|
|
426
param.c
426
param.c
@ -24,24 +24,24 @@ static const tSatipParameterMap SatipBandwidthValues[] = {
|
|||||||
{ 8000000, "&bw=8" },
|
{ 8000000, "&bw=8" },
|
||||||
{ 10000000, "&bw=10" },
|
{ 10000000, "&bw=10" },
|
||||||
{ 1712000, "&bw=1.712" },
|
{ 1712000, "&bw=1.712" },
|
||||||
{ -1, NULL }
|
{ -1, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
static const tSatipParameterMap SatipPilotValues[] = {
|
static const tSatipParameterMap SatipPilotValues[] = {
|
||||||
{ PILOT_OFF, "&plts=off" },
|
{ PILOT_OFF, "&plts=off" },
|
||||||
{ PILOT_ON, "&plts=on" },
|
{ PILOT_ON, "&plts=on" },
|
||||||
{ PILOT_AUTO, "" },
|
{ PILOT_AUTO, "" },
|
||||||
{ -1, NULL }
|
{ -1, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
static const tSatipParameterMap SatipSisoMisoValues[] = {
|
static const tSatipParameterMap SatipSisoMisoValues[] = {
|
||||||
{ 0, "&sm=0" },
|
{ 0, "&sm=0" },
|
||||||
{ 1, "&sm=1" },
|
{ 1, "&sm=1" },
|
||||||
{ -1, NULL }
|
{ -1, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
static const tSatipParameterMap SatipCodeRateValues[] = {
|
static const tSatipParameterMap SatipCodeRateValues[] = {
|
||||||
{ FEC_NONE, "" },
|
{ FEC_NONE, "" },
|
||||||
{ FEC_1_2, "&fec=12" },
|
{ FEC_1_2, "&fec=12" },
|
||||||
{ FEC_2_3, "&fec=23" },
|
{ FEC_2_3, "&fec=23" },
|
||||||
{ FEC_3_4, "&fec=34" },
|
{ FEC_3_4, "&fec=34" },
|
||||||
@ -52,45 +52,36 @@ static const tSatipParameterMap SatipCodeRateValues[] = {
|
|||||||
{ FEC_7_8, "&fec=78" },
|
{ FEC_7_8, "&fec=78" },
|
||||||
{ FEC_8_9, "&fec=89" },
|
{ FEC_8_9, "&fec=89" },
|
||||||
{ FEC_9_10, "&fec=910" },
|
{ FEC_9_10, "&fec=910" },
|
||||||
{ FEC_AUTO, "" },
|
{ FEC_AUTO, "" },
|
||||||
{ -1, NULL }
|
{ -1, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
static const tSatipParameterMap SatipModulationValues[] = {
|
static const tSatipParameterMap SatipModulationValues[] = {
|
||||||
{ QPSK, "&mtype=qpsk" },
|
{ QPSK, "&mtype=qpsk" },
|
||||||
{ PSK_8, "&mtype=8psk" },
|
{ PSK_8, "&mtype=8psk" },
|
||||||
{ APSK_16, "&mtype=16apsk" },
|
|
||||||
{ APSK_32, "&mtype=32apsk" },
|
|
||||||
{ VSB_8, "&mtype=8vsb" },
|
|
||||||
{ VSB_16, "&mtype=16vsb" },
|
|
||||||
{ QAM_16, "&mtype=16qam" },
|
{ QAM_16, "&mtype=16qam" },
|
||||||
{ QAM_64, "&mtype=64qam" },
|
{ QAM_64, "&mtype=64qam" },
|
||||||
{ QAM_128, "&mtype=128qam" },
|
{ QAM_128, "&mtype=128qam" },
|
||||||
{ QAM_256, "&mtype=256qam" },
|
{ QAM_256, "&mtype=256qam" },
|
||||||
{ QAM_AUTO, "" },
|
{ QAM_AUTO, "" },
|
||||||
{ -1, NULL }
|
{ -1, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
static const tSatipParameterMap SatipSystemValuesSat[] = {
|
static const tSatipParameterMap SatipSystemValuesSat[] = {
|
||||||
{ 0, "&msys=dvbs" },
|
{ 0, "&msys=dvbs" },
|
||||||
{ 1, "&msys=dvbs2" },
|
{ 1, "&msys=dvbs2" },
|
||||||
{ -1, NULL }
|
{ -1, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
static const tSatipParameterMap SatipSystemValuesTerrestrial[] = {
|
static const tSatipParameterMap SatipSystemValuesTerrestrial[] = {
|
||||||
{ 0, "&msys=dvbt" },
|
{ 0, "&msys=dvbt" },
|
||||||
{ 1, "&msys=dvbt2" },
|
{ 1, "&msys=dvbt2" },
|
||||||
{ -1, NULL }
|
{ -1, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
static const tSatipParameterMap SatipSystemValuesCable[] = {
|
static const tSatipParameterMap SatipSystemValuesCable[] = {
|
||||||
{ 0, "&msys=dvbc" },
|
{ 0, "&msys=dvbc" },
|
||||||
{ 1, "&msys=dvbc2" },
|
{ 1, "&msys=dvbc2" },
|
||||||
{ -1, NULL }
|
|
||||||
};
|
|
||||||
|
|
||||||
static const tSatipParameterMap SatipSystemValuesAtsc[] = {
|
|
||||||
{ 0, "&msys=atsc" },
|
|
||||||
{ -1, NULL }
|
{ -1, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -101,8 +92,8 @@ static const tSatipParameterMap SatipTransmissionValues[] = {
|
|||||||
{ TRANSMISSION_MODE_8K, "&tmode=8k" },
|
{ TRANSMISSION_MODE_8K, "&tmode=8k" },
|
||||||
{ TRANSMISSION_MODE_16K, "&tmode=16k" },
|
{ TRANSMISSION_MODE_16K, "&tmode=16k" },
|
||||||
{ TRANSMISSION_MODE_32K, "&tmode=32k" },
|
{ TRANSMISSION_MODE_32K, "&tmode=32k" },
|
||||||
{ TRANSMISSION_MODE_AUTO, "" },
|
{ TRANSMISSION_MODE_AUTO, "" },
|
||||||
{ -1, NULL }
|
{ -1, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
static const tSatipParameterMap SatipGuardValues[] = {
|
static const tSatipParameterMap SatipGuardValues[] = {
|
||||||
@ -113,23 +104,16 @@ static const tSatipParameterMap SatipGuardValues[] = {
|
|||||||
{ GUARD_INTERVAL_1_128, "&gi=1128" },
|
{ GUARD_INTERVAL_1_128, "&gi=1128" },
|
||||||
{ GUARD_INTERVAL_19_128, "&gi=19128" },
|
{ GUARD_INTERVAL_19_128, "&gi=19128" },
|
||||||
{ GUARD_INTERVAL_19_256, "&gi=19256" },
|
{ GUARD_INTERVAL_19_256, "&gi=19256" },
|
||||||
{ GUARD_INTERVAL_AUTO, "" },
|
{ GUARD_INTERVAL_AUTO, "" },
|
||||||
{ -1, NULL }
|
{ -1, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
static const tSatipParameterMap SatipRollOffValues[] = {
|
static const tSatipParameterMap SatipRollOffValues[] = {
|
||||||
{ ROLLOFF_AUTO, "" },
|
{ ROLLOFF_AUTO, "" },
|
||||||
{ ROLLOFF_20, "&ro=0.20" },
|
{ ROLLOFF_20, "&ro=0.20" },
|
||||||
{ ROLLOFF_25, "&ro=0.25" },
|
{ ROLLOFF_25, "&ro=0.25" },
|
||||||
{ ROLLOFF_35, "&ro=0.35" },
|
{ ROLLOFF_35, "&ro=0.35" },
|
||||||
{ -1, NULL }
|
{ -1, NULL }
|
||||||
};
|
|
||||||
|
|
||||||
static const tSatipParameterMap SatipInversionValues[] = {
|
|
||||||
{ INVERSION_AUTO, "" },
|
|
||||||
{ INVERSION_OFF, "&specinv=0" },
|
|
||||||
{ INVERSION_ON, "&specinv=1" },
|
|
||||||
{ -1, NULL }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static int SatipUserIndex(int valueP, const tSatipParameterMap *mapP)
|
static int SatipUserIndex(int valueP, const tSatipParameterMap *mapP)
|
||||||
@ -154,8 +138,15 @@ cString GetTransponderUrlParameters(const cChannel *channelP)
|
|||||||
if (channelP) {
|
if (channelP) {
|
||||||
char buffer[255];
|
char buffer[255];
|
||||||
cDvbTransponderParameters dtp(channelP->Parameters());
|
cDvbTransponderParameters dtp(channelP->Parameters());
|
||||||
int DataSlice = 0;
|
#if defined(APIVERSNUM) && APIVERSNUM < 20106
|
||||||
int C2TuningFrequencyType = 0;
|
int Pilot = PILOT_AUTO;
|
||||||
|
int T2SystemId = 0;
|
||||||
|
int SisoMiso = 0;
|
||||||
|
#else
|
||||||
|
int Pilot = dtp.Pilot();
|
||||||
|
int T2SystemId = dtp.T2SystemId();
|
||||||
|
int SisoMiso = dtp.SisoMiso();
|
||||||
|
#endif
|
||||||
float freq = channelP->Frequency();
|
float freq = channelP->Frequency();
|
||||||
char type = cSource::ToChar(channelP->Source());
|
char type = cSource::ToChar(channelP->Source());
|
||||||
cSource *source = Sources.Get(channelP->Source());
|
cSource *source = Sources.Get(channelP->Source());
|
||||||
@ -167,353 +158,26 @@ cString GetTransponderUrlParameters(const cChannel *channelP)
|
|||||||
freq /= 1000L;
|
freq /= 1000L;
|
||||||
#define ST(s) if (strchr(s, type) && (strchr(s, '0' + dtp.System() + 1) || strchr(s, '*')))
|
#define ST(s) if (strchr(s, type) && (strchr(s, '0' + dtp.System() + 1) || strchr(s, '*')))
|
||||||
#define STBUFLEFT (sizeof(buffer) - (q - buffer))
|
#define STBUFLEFT (sizeof(buffer) - (q - buffer))
|
||||||
ST(" S 1") { // to comply with SAT>IP protocol specification 1.2.2
|
q += snprintf(q, STBUFLEFT, "freq=%s", *dtoa(freq, "%lg"));
|
||||||
dtp.SetPilot(PILOT_OFF);
|
ST(" S *") q += snprintf(q, STBUFLEFT, "&src=%d", ((src > 0) && (src <= 255)) ? src : 1);
|
||||||
dtp.SetModulation(QPSK);
|
ST("CS *") q += snprintf(q, STBUFLEFT, "&sr=%d", channelP->Srate());
|
||||||
dtp.SetRollOff(ROLLOFF_35);
|
ST(" S *") q += snprintf(q, STBUFLEFT, "&pol=%c", tolower(dtp.Polarization()));
|
||||||
}
|
ST("C T2") q += snprintf(q, STBUFLEFT, "&plp=%d", dtp.StreamId());
|
||||||
if ((channelP->Rid() % 100) > 0)
|
ST(" T2") q += snprintf(q, STBUFLEFT, "&t2id=%d", T2SystemId);
|
||||||
q += snprintf(q, STBUFLEFT, "&fe=%d", channelP->Rid() % 100);
|
ST(" T2") q += PrintUrlString(q, STBUFLEFT, SisoMiso, SatipSisoMisoValues);
|
||||||
ST(" S *") q += snprintf(q, STBUFLEFT, "&src=%d", ((src > 0) && (src <= 255)) ? src : 1);
|
ST(" T*") q += PrintUrlString(q, STBUFLEFT, dtp.Bandwidth(), SatipBandwidthValues);
|
||||||
if (freq >= 0L)
|
ST(" T*") q += PrintUrlString(q, STBUFLEFT, dtp.Guard(), SatipGuardValues);
|
||||||
q += snprintf(q, STBUFLEFT, "&freq=%s", *dtoa(freq, "%lg"));
|
ST("CST*") q += PrintUrlString(q, STBUFLEFT, dtp.CoderateH(), SatipCodeRateValues);
|
||||||
ST(" S *") q += snprintf(q, STBUFLEFT, "&pol=%c", tolower(dtp.Polarization()));
|
ST(" S 2") q += PrintUrlString(q, STBUFLEFT, Pilot, SatipPilotValues);
|
||||||
ST(" S *") q += PrintUrlString(q, STBUFLEFT, dtp.RollOff(), SatipRollOffValues);
|
ST(" S 2") q += PrintUrlString(q, STBUFLEFT, dtp.Modulation(), SatipModulationValues);
|
||||||
ST(" C 2") q += snprintf(q, STBUFLEFT, "&c2tft=%d", C2TuningFrequencyType);
|
ST("C T*") q += PrintUrlString(q, STBUFLEFT, dtp.Modulation(), SatipModulationValues);
|
||||||
ST(" T*") q += PrintUrlString(q, STBUFLEFT, dtp.Bandwidth(), SatipBandwidthValues);
|
ST(" S 2") q += PrintUrlString(q, STBUFLEFT, dtp.RollOff(), SatipRollOffValues);
|
||||||
ST(" C 2") q += PrintUrlString(q, STBUFLEFT, dtp.Bandwidth(), SatipBandwidthValues);
|
ST(" S *") q += PrintUrlString(q, STBUFLEFT, dtp.System(), SatipSystemValuesSat);
|
||||||
ST(" S *") q += PrintUrlString(q, STBUFLEFT, dtp.System(), SatipSystemValuesSat);
|
ST("C *") q += PrintUrlString(q, STBUFLEFT, dtp.System(), SatipSystemValuesCable);
|
||||||
ST(" C *") q += PrintUrlString(q, STBUFLEFT, dtp.System(), SatipSystemValuesCable);
|
ST(" T*") q += PrintUrlString(q, STBUFLEFT, dtp.System(), SatipSystemValuesTerrestrial);
|
||||||
ST(" T*") q += PrintUrlString(q, STBUFLEFT, dtp.System(), SatipSystemValuesTerrestrial);
|
ST(" T*") q += PrintUrlString(q, STBUFLEFT, dtp.Transmission(), SatipTransmissionValues);
|
||||||
ST("A *") q += PrintUrlString(q, STBUFLEFT, dtp.System(), SatipSystemValuesAtsc);
|
|
||||||
ST(" T*") q += PrintUrlString(q, STBUFLEFT, dtp.Transmission(), SatipTransmissionValues);
|
|
||||||
ST(" S *") q += PrintUrlString(q, STBUFLEFT, dtp.Modulation(), SatipModulationValues);
|
|
||||||
ST(" T*") q += PrintUrlString(q, STBUFLEFT, dtp.Modulation(), SatipModulationValues);
|
|
||||||
ST(" C 1") q += PrintUrlString(q, STBUFLEFT, dtp.Modulation(), SatipModulationValues);
|
|
||||||
ST("A *") q += PrintUrlString(q, STBUFLEFT, dtp.Modulation(), SatipModulationValues);
|
|
||||||
ST(" S *") q += PrintUrlString(q, STBUFLEFT, dtp.Pilot(), SatipPilotValues);
|
|
||||||
ST(" S *") q += snprintf(q, STBUFLEFT, "&sr=%d", channelP->Srate());
|
|
||||||
ST(" C 1") q += snprintf(q, STBUFLEFT, "&sr=%d", channelP->Srate());
|
|
||||||
ST(" T*") q += PrintUrlString(q, STBUFLEFT, dtp.Guard(), SatipGuardValues);
|
|
||||||
ST(" CST*") q += PrintUrlString(q, STBUFLEFT, dtp.CoderateH(), SatipCodeRateValues);
|
|
||||||
ST(" C 2") q += snprintf(q, STBUFLEFT, "&ds=%d", DataSlice);
|
|
||||||
ST(" C T2") q += snprintf(q, STBUFLEFT, "&plp=%d", dtp.StreamId());
|
|
||||||
ST(" T2") q += snprintf(q, STBUFLEFT, "&t2id=%d", dtp.T2SystemId());
|
|
||||||
ST(" T2") q += PrintUrlString(q, STBUFLEFT, dtp.SisoMiso(), SatipSisoMisoValues);
|
|
||||||
ST(" C 1") q += PrintUrlString(q, STBUFLEFT, dtp.Inversion(), SatipInversionValues);
|
|
||||||
ST("A *") q += PrintUrlString(q, STBUFLEFT, dtp.Inversion(), SatipInversionValues);
|
|
||||||
#undef ST
|
#undef ST
|
||||||
return &buffer[1];
|
return buffer;
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
cString GetTnrUrlParameters(const cChannel *channelP)
|
|
||||||
{
|
|
||||||
if (channelP) {
|
|
||||||
cDvbTransponderParameters dtp(channelP->Parameters());
|
|
||||||
eTrackType track = cDevice::PrimaryDevice()->GetCurrentAudioTrack();
|
|
||||||
|
|
||||||
// TunerType: Byte;
|
|
||||||
// 0 = cable, 1 = satellite, 2 = terrestrial, 3 = atsc, 4 = iptv, 5 = stream (URL, DVBViewer GE)
|
|
||||||
int TunerType = 0;
|
|
||||||
if (channelP->IsCable())
|
|
||||||
TunerType = 0;
|
|
||||||
else if (channelP->IsSat())
|
|
||||||
TunerType = 1;
|
|
||||||
else if (channelP->IsTerr())
|
|
||||||
TunerType = 2;
|
|
||||||
else if (channelP->IsAtsc())
|
|
||||||
TunerType = 3;
|
|
||||||
|
|
||||||
// Frequency: DWord;
|
|
||||||
// DVB-S: MHz if < 1000000, kHz if >= 1000000
|
|
||||||
// DVB-T/C, ATSC: kHz
|
|
||||||
// IPTV: IP address Byte3.Byte2.Byte1.Byte0
|
|
||||||
int Frequency = channelP->Frequency() / 1000;
|
|
||||||
|
|
||||||
// Symbolrate: DWord;
|
|
||||||
// DVB S/C: in kSym/s
|
|
||||||
// DVB-T, ATSC: 0
|
|
||||||
// IPTV: Port
|
|
||||||
int Symbolrate = (channelP->IsSat() || channelP->IsCable()) ? channelP->Srate() : 0;
|
|
||||||
|
|
||||||
// LNB_LOF: Word;
|
|
||||||
// DVB-S: Local oscillator frequency of the LNB
|
|
||||||
// DVB-T/C, ATSC: 0
|
|
||||||
// IPTV: Byte0 and Byte1 of Source IP
|
|
||||||
int LNB_LOF = channelP->IsSat() ? Setup.LnbSLOF : 0;
|
|
||||||
|
|
||||||
// Tone: Byte;
|
|
||||||
// 0 = off, 1 = 22 khz
|
|
||||||
int Tone = (channelP->Frequency() < Setup.LnbSLOF) ? 0 : 1;
|
|
||||||
|
|
||||||
// Polarity: Byte;
|
|
||||||
// DVB-S polarity: 0 = horizontal, 1 = vertical, 2 = circular left, 3 = circular right
|
|
||||||
// DVB-C modulation: 0 = Auto, 1 = 16QAM, 2 = 32QAM, 3 = 64QAM, 4 = 128QAM, 5 = 256 QAM
|
|
||||||
// DVB-T bandwidth: 0 = 6 MHz, 1 = 7 MHz, 2 = 8 MHz
|
|
||||||
// IPTV: Byte3 of SourceIP
|
|
||||||
int Polarity = 0;
|
|
||||||
if (channelP->IsSat()) {
|
|
||||||
switch (tolower(dtp.Polarization())) {
|
|
||||||
case 'h':
|
|
||||||
Polarity = 0;
|
|
||||||
break;
|
|
||||||
case 'v':
|
|
||||||
Polarity = 1;
|
|
||||||
break;
|
|
||||||
case 'l':
|
|
||||||
Polarity = 2;
|
|
||||||
break;
|
|
||||||
case 'r':
|
|
||||||
Polarity = 3;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (channelP->IsCable()) {
|
|
||||||
switch (dtp.Modulation()) {
|
|
||||||
case 999:
|
|
||||||
Polarity = 0;
|
|
||||||
break;
|
|
||||||
case 16:
|
|
||||||
Polarity = 1;
|
|
||||||
break;
|
|
||||||
case 32:
|
|
||||||
Polarity = 2;
|
|
||||||
break;
|
|
||||||
case 64:
|
|
||||||
Polarity = 3;
|
|
||||||
break;
|
|
||||||
case 128:
|
|
||||||
Polarity = 4;
|
|
||||||
break;
|
|
||||||
case 256:
|
|
||||||
Polarity = 5;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (channelP->IsTerr()) {
|
|
||||||
switch (dtp.Bandwidth()) {
|
|
||||||
case 6:
|
|
||||||
Polarity = 0;
|
|
||||||
break;
|
|
||||||
case 7:
|
|
||||||
Polarity = 1;
|
|
||||||
break;
|
|
||||||
case 8:
|
|
||||||
Polarity = 2;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// DiSEqC: Byte;
|
|
||||||
// 0 = None
|
|
||||||
// 1 = Pos A (mostly translated to PosA/OptA)
|
|
||||||
// 2 = Pos B (mostly translated to PosB/OptA)
|
|
||||||
// 3 = PosA/OptA
|
|
||||||
// 4 = PosB/OptA
|
|
||||||
// 5 = PosA/OptB
|
|
||||||
// 6 = PosB/OptB
|
|
||||||
// 7 = Preset Position (DiSEqC 1.2, see DiSEqCExt)
|
|
||||||
// 8 = Angular Position (DiSEqC 1.2, see DiSEqCExt)
|
|
||||||
// 9 = DiSEqC Command Sequence (see DiSEqCExt)
|
|
||||||
int DiSEqC = 0;
|
|
||||||
|
|
||||||
// FEC: Byte;
|
|
||||||
// 0 = Auto
|
|
||||||
// 1 = 1/2
|
|
||||||
// 2 = 2/3
|
|
||||||
// 3 = 3/4
|
|
||||||
// 4 = 5/6
|
|
||||||
// 5 = 7/8
|
|
||||||
// 6 = 8/9
|
|
||||||
// 7 = 3/5
|
|
||||||
// 8 = 4/5
|
|
||||||
// 9 = 9/10
|
|
||||||
// IPTV: Byte2 of SourceIP
|
|
||||||
// DVB C/T, ATSC: 0
|
|
||||||
int FEC = 0;
|
|
||||||
if (channelP->IsSat()) {
|
|
||||||
switch (dtp.CoderateH()) {
|
|
||||||
case 999:
|
|
||||||
FEC = 0;
|
|
||||||
break;
|
|
||||||
case 12:
|
|
||||||
FEC = 1;
|
|
||||||
break;
|
|
||||||
case 23:
|
|
||||||
FEC = 2;
|
|
||||||
break;
|
|
||||||
case 34:
|
|
||||||
FEC = 3;
|
|
||||||
break;
|
|
||||||
case 56:
|
|
||||||
FEC = 4;
|
|
||||||
break;
|
|
||||||
case 78:
|
|
||||||
FEC = 5;
|
|
||||||
break;
|
|
||||||
case 89:
|
|
||||||
FEC = 6;
|
|
||||||
break;
|
|
||||||
case 35:
|
|
||||||
FEC = 7;
|
|
||||||
break;
|
|
||||||
case 45:
|
|
||||||
FEC = 8;
|
|
||||||
break;
|
|
||||||
case 910:
|
|
||||||
FEC = 9;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Audio_PID: Word;
|
|
||||||
int Audio_PID = channelP->Apid(0);
|
|
||||||
if (IS_AUDIO_TRACK(track))
|
|
||||||
Audio_PID = channelP->Apid(int(track - ttAudioFirst));
|
|
||||||
else if (IS_DOLBY_TRACK(track))
|
|
||||||
Audio_PID = channelP->Dpid(int(track - ttDolbyFirst));
|
|
||||||
|
|
||||||
// Video_PID: Word;
|
|
||||||
int Video_PID = channelP->Vpid();
|
|
||||||
|
|
||||||
// PMT_PID: Word;
|
|
||||||
int PMT_PID = channelP->Ppid();
|
|
||||||
|
|
||||||
// Service_ID: Word;
|
|
||||||
int Service_ID = channelP->Sid();
|
|
||||||
|
|
||||||
// SatModulation: Byte;
|
|
||||||
// Bit 0..1: satellite modulation. 0 = Auto, 1 = QPSK, 2 = 8PSK, 3 = 16QAM or APSK for DVB-S2
|
|
||||||
// Bit 2: modulation system. 0 = DVB-S/T/C, 1 = DVB-S2/T2/C2
|
|
||||||
// Bit 3..4: DVB-S2: roll-off. 0 = 0.35, 1 = 0.25, 2 = 0.20, 3 = reserved
|
|
||||||
// Bit 5..6: spectral inversion, 0 = undefined, 1 = auto, 2 = normal, 3 = inverted
|
|
||||||
// Bit 7: DVB-S2: pilot symbols, 0 = off, 1 = on
|
|
||||||
// DVB-T2: DVB-T2 Lite, 0 = off, 1 = on
|
|
||||||
int SatModulation = 0;
|
|
||||||
if (channelP->IsSat() && dtp.System()) {
|
|
||||||
switch (dtp.Modulation()) {
|
|
||||||
case 999:
|
|
||||||
SatModulation |= (0 & 0x3) << 0;
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
SatModulation |= (1 & 0x3) << 0;
|
|
||||||
break;
|
|
||||||
case 5:
|
|
||||||
SatModulation |= (2 & 0x3) << 0;
|
|
||||||
break;
|
|
||||||
case 6:
|
|
||||||
SatModulation |= (3 & 0x3) << 0;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
SatModulation |= (dtp.System() & 0x1) << 2;
|
|
||||||
if (channelP->IsSat() && dtp.System()) {
|
|
||||||
switch (dtp.RollOff()) {
|
|
||||||
case 35:
|
|
||||||
SatModulation |= (0 & 0x3) << 3;
|
|
||||||
break;
|
|
||||||
case 25:
|
|
||||||
SatModulation |= (1 & 0x3) << 3;
|
|
||||||
break;
|
|
||||||
case 20:
|
|
||||||
SatModulation |= (2 & 0x3) << 3;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
switch (dtp.Inversion()) {
|
|
||||||
case 999:
|
|
||||||
SatModulation |= (1 & 0x3) << 5;
|
|
||||||
break;
|
|
||||||
case 0:
|
|
||||||
SatModulation |= (2 & 0x3) << 5;
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
SatModulation |= (3 & 0x3) << 5;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (channelP->IsSat() && dtp.System()) {
|
|
||||||
switch (dtp.Pilot()) {
|
|
||||||
case 0:
|
|
||||||
SatModulation |= (0 & 0x1) << 7;
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
SatModulation |= (1 & 0x1) << 7;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// DiSEqCExt: Word;
|
|
||||||
// DiSEqC Extension, meaning depends on DiSEqC
|
|
||||||
// DiSEqC = 0..6: 0
|
|
||||||
// DiSEqC = 7: Preset Position (DiSEqC 1.2)
|
|
||||||
// DiSEqC = 8: Orbital Position (DiSEqC 1.2, USALS, for calculating motor angle)
|
|
||||||
// Same format as OrbitalPos above
|
|
||||||
// DiSEQC = 9: Orbital Position referencing DiSEqC sequence defined in DiSEqC.xml/ini
|
|
||||||
// Same format as OrbitalPos above
|
|
||||||
int DiSEqCExt = 0;
|
|
||||||
|
|
||||||
// Flags: Byte;
|
|
||||||
// Bit 0: 1 = encrypted channel
|
|
||||||
// Bit 1: reserved, set to 0
|
|
||||||
// Bit 2: 1 = channel broadcasts RDS data
|
|
||||||
// Bit 3: 1 = channel is a video service (even if the Video PID is temporarily = 0)
|
|
||||||
// Bit 4: 1 = channel is an audio service (even if the Audio PID is temporarily = 0)
|
|
||||||
// Bit 5: 1 = audio has a different samplerate than 48 KHz
|
|
||||||
// Bit 6: 1 = bandstacking, internally polarisation is always set to H
|
|
||||||
// Bit 7: 1 = channel entry is an additional audio track of the preceding
|
|
||||||
// channel with bit 7 = 0
|
|
||||||
int Flags = (channelP->Ca() > 0xFF) ? 1 : 0;
|
|
||||||
|
|
||||||
// ChannelGroup: Byte;
|
|
||||||
// 0 = Group A, 1 = Group B, 2 = Group C etc.
|
|
||||||
int ChannelGroup = 0;
|
|
||||||
|
|
||||||
// TransportStream_ID: Word;
|
|
||||||
int TransportStream_ID = channelP->Tid();
|
|
||||||
|
|
||||||
// OriginalNetwork_ID: Word;
|
|
||||||
int OriginalNetwork_ID = channelP->Nid();
|
|
||||||
|
|
||||||
// Substream: Word;
|
|
||||||
// DVB-S/C/T, ATSC, IPTV: 0
|
|
||||||
// DVB-T2: 0 = PLP_ID not set, 1..256: PLP_ID + 1, 257... reserved
|
|
||||||
int Substream = (channelP->IsTerr() && dtp.System()) ? dtp.StreamId() - 1 : 0;
|
|
||||||
|
|
||||||
// OrbitalPos: Word;
|
|
||||||
// DVB-S: orbital position x 10, 0 = undefined, 1..1800 east, 1801..3599 west (1°W = 3599)
|
|
||||||
// DVB-C: 4000..4999
|
|
||||||
// DVB-T: 5000..5999
|
|
||||||
// ATSC: 6000..6999
|
|
||||||
// IPTV: 7000..7999
|
|
||||||
// Stream: 8000..8999
|
|
||||||
int OrbitalPos = 0;
|
|
||||||
if (channelP->IsSat()) {
|
|
||||||
OrbitalPos = cSource::Position(channelP->Source());
|
|
||||||
if (OrbitalPos != 3600)
|
|
||||||
OrbitalPos += 1800;
|
|
||||||
}
|
|
||||||
|
|
||||||
return cString::sprintf("%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d",
|
|
||||||
TunerType, Frequency, Symbolrate, LNB_LOF, Tone, Polarity, DiSEqC, FEC, Audio_PID, Video_PID, PMT_PID, Service_ID,
|
|
||||||
SatModulation, DiSEqCExt, Flags, ChannelGroup, TransportStream_ID, OriginalNetwork_ID, Substream, OrbitalPos);
|
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
1
param.h
1
param.h
@ -11,6 +11,5 @@
|
|||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
|
||||||
cString GetTransponderUrlParameters(const cChannel *channelP);
|
cString GetTransponderUrlParameters(const cChannel *channelP);
|
||||||
cString GetTnrUrlParameters(const cChannel *channelP);
|
|
||||||
|
|
||||||
#endif // __SATIP_PARAM_H
|
#endif // __SATIP_PARAM_H
|
||||||
|
104
po/ca_ES.po
104
po/ca_ES.po
@ -1,14 +1,14 @@
|
|||||||
# VDR plugin language source file.
|
# VDR plugin language source file.
|
||||||
# Copyright (C) 2007-2019 Rolf Ahrenberg
|
# Copyright (C) 2007-2014 Rolf Ahrenberg
|
||||||
# This file is distributed under the same license as the satip package.
|
# This file is distributed under the same license as the satip package.
|
||||||
# Gabriel Bonich, 2014-2017
|
# Gabriel Bonich, 2014
|
||||||
#
|
#
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: vdr-satip 2.4.0\n"
|
"Project-Id-Version: vdr-satip 0.3.2\n"
|
||||||
"Report-Msgid-Bugs-To: <see README>\n"
|
"Report-Msgid-Bugs-To: <see README>\n"
|
||||||
"POT-Creation-Date: 2019-10-27 19:12+0200\n"
|
"POT-Creation-Date: 2014-05-10 05:10+0200\n"
|
||||||
"PO-Revision-Date: 2019-10-27 10:27+0200\n"
|
"PO-Revision-Date: 2014-05-10 05:10+0200\n"
|
||||||
"Last-Translator: Gabriel Bonich <gbonich@gmail.com>\n"
|
"Last-Translator: Gabriel Bonich <gbonich@gmail.com>\n"
|
||||||
"Language-Team: Catalan <vdr@linuxtv.org>\n"
|
"Language-Team: Catalan <vdr@linuxtv.org>\n"
|
||||||
"Language: ca\n"
|
"Language: ca\n"
|
||||||
@ -31,14 +31,11 @@ msgstr "EIT (0x4E/0x4F/0x5X/0x6X)"
|
|||||||
msgid "TDT (0x70)"
|
msgid "TDT (0x70)"
|
||||||
msgstr "TDT (0x70)"
|
msgstr "TDT (0x70)"
|
||||||
|
|
||||||
msgid "SAT>IP information not available!"
|
|
||||||
msgstr "SAT>IP Informació no disponible!"
|
|
||||||
|
|
||||||
msgid "SAT>IP Devices"
|
msgid "SAT>IP Devices"
|
||||||
msgstr "SAT>IP Dispositius"
|
msgstr "SAT>IP Dispositius"
|
||||||
|
|
||||||
msgid "SAT>IP Server"
|
msgid "SAT>IP Device"
|
||||||
msgstr "SAT>IP Server"
|
msgstr "SAT>IP Dispositiu"
|
||||||
|
|
||||||
msgid "Address"
|
msgid "Address"
|
||||||
msgstr "Adressa"
|
msgstr "Adressa"
|
||||||
@ -49,15 +46,9 @@ msgstr "Model"
|
|||||||
msgid "Description"
|
msgid "Description"
|
||||||
msgstr "Descripció"
|
msgstr "Descripció"
|
||||||
|
|
||||||
msgid "CI extension"
|
|
||||||
msgstr "Extensió CI"
|
|
||||||
|
|
||||||
msgid "Creation date"
|
msgid "Creation date"
|
||||||
msgstr "Creació de data"
|
msgstr "Creació de data"
|
||||||
|
|
||||||
msgid "SAT>IP Device Status"
|
|
||||||
msgstr "SAT>IP Estat Dispositiu"
|
|
||||||
|
|
||||||
msgid "SAT>IP Information"
|
msgid "SAT>IP Information"
|
||||||
msgstr "SAT>IP Informació"
|
msgstr "SAT>IP Informació"
|
||||||
|
|
||||||
@ -73,6 +64,9 @@ msgstr "Filtres"
|
|||||||
msgid "Bits/bytes"
|
msgid "Bits/bytes"
|
||||||
msgstr "Bits/Bytes"
|
msgstr "Bits/Bytes"
|
||||||
|
|
||||||
|
msgid "SAT>IP information not available!"
|
||||||
|
msgstr "SAT>IP Informació no disponible!"
|
||||||
|
|
||||||
msgid "off"
|
msgid "off"
|
||||||
msgstr "Apagat"
|
msgstr "Apagat"
|
||||||
|
|
||||||
@ -85,18 +79,6 @@ msgstr "Normal"
|
|||||||
msgid "high"
|
msgid "high"
|
||||||
msgstr "Alt"
|
msgstr "Alt"
|
||||||
|
|
||||||
msgid "Unicast"
|
|
||||||
msgstr "Unicast"
|
|
||||||
|
|
||||||
msgid "Multicast"
|
|
||||||
msgstr "Multicast"
|
|
||||||
|
|
||||||
msgid "RTP-over-TCP"
|
|
||||||
msgstr "RTP-per sobre-TCP"
|
|
||||||
|
|
||||||
msgid "Button$Devices"
|
|
||||||
msgstr "Dispositius"
|
|
||||||
|
|
||||||
msgid "Operating mode"
|
msgid "Operating mode"
|
||||||
msgstr "Mode de operació"
|
msgstr "Mode de operació"
|
||||||
|
|
||||||
@ -108,37 +90,13 @@ msgid ""
|
|||||||
"normal - devices are working within normal parameters\n"
|
"normal - devices are working within normal parameters\n"
|
||||||
"high - devices are working at the highest priority"
|
"high - devices are working at the highest priority"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Defineig la manera de operar els Dispositius SAT>IP:\n"
|
"Defineig la manera de operar els Disposituis SAT>IP:\n"
|
||||||
"\n"
|
"\n"
|
||||||
"Apagat - Dispositius desactivats\n"
|
"Apagat - Dispositius desactivats\n"
|
||||||
"Baix - Dispositius treballan a baixa prioritat\n"
|
"Baix - Dispositius treballan a baixa prioritat\n"
|
||||||
"Normal - Dispositius treballan en parametres normals\n"
|
"Normal - Dispositius treballan en parametres normals\n"
|
||||||
"Alta - Dispositius treballan a prioritat Alta"
|
"Alta - Dispositius treballan a prioritat Alta"
|
||||||
|
|
||||||
msgid "Enable CI extension"
|
|
||||||
msgstr "Habilita la extenció CI"
|
|
||||||
|
|
||||||
msgid ""
|
|
||||||
"Define whether a CI extension shall be used.\n"
|
|
||||||
"\n"
|
|
||||||
"This setting enables integrated CI/CAM handling found in some SAT>IP hardware (e.g. Digital Devices OctopusNet)."
|
|
||||||
msgstr ""
|
|
||||||
"Definir si s'utilitzarà una extensió de CI.\n"
|
|
||||||
"\n"
|
|
||||||
"Aquesta configuració permet utilitzar CI/CAM integrat que es troba en alguns equips SAT>IP (ex. Digital Devices OctopusNet)."
|
|
||||||
|
|
||||||
msgid "CI/CAM"
|
|
||||||
msgstr "CI/CAM"
|
|
||||||
|
|
||||||
msgid ""
|
|
||||||
"Define a desired CAM type for the CI slot.\n"
|
|
||||||
"\n"
|
|
||||||
"The '---' option lets SAT>IP hardware do the auto-selection."
|
|
||||||
msgstr ""
|
|
||||||
"Definir quin tipus de CAM vols per a la ranura CI.\n"
|
|
||||||
"\n"
|
|
||||||
"L'opció '---' permet l'equip SAT>IP fer la selecció automàtica."
|
|
||||||
|
|
||||||
msgid "Enable EPG scanning"
|
msgid "Enable EPG scanning"
|
||||||
msgstr "Activa Escanneig EPG"
|
msgstr "Activa Escanneig EPG"
|
||||||
|
|
||||||
@ -151,31 +109,16 @@ msgstr ""
|
|||||||
"\n"
|
"\n"
|
||||||
"Aquesta configuració desactiva la funcionalitat d'escaneig EIT automàtica per a tots els dispositius SAT>IP."
|
"Aquesta configuració desactiva la funcionalitat d'escaneig EIT automàtica per a tots els dispositius SAT>IP."
|
||||||
|
|
||||||
msgid "Disabled sources"
|
msgid "Disabled filters"
|
||||||
msgstr "Desactiva entrades"
|
msgstr "Desactiva filtres"
|
||||||
|
|
||||||
msgid "none"
|
msgid "none"
|
||||||
msgstr "no"
|
msgstr "no"
|
||||||
|
|
||||||
msgid ""
|
|
||||||
"Define number of sources to be disabled.\n"
|
|
||||||
"\n"
|
|
||||||
"SAT>IP servers might not have all satellite positions available and such sources can be blacklisted here."
|
|
||||||
msgstr ""
|
|
||||||
"Definir nombre de entrades que es desactiven.\n"
|
|
||||||
"\n"
|
|
||||||
"SAT>IP els servidors podrien no tenir totes les posicions dels satèl·lits disponibles i aquestes entrades poden ser la llista negra."
|
|
||||||
|
|
||||||
msgid "Define a source to be blacklisted."
|
|
||||||
msgstr "Definir una entrada a la llista negra"
|
|
||||||
|
|
||||||
msgid "Disabled filters"
|
|
||||||
msgstr "Desactiva filtres"
|
|
||||||
|
|
||||||
msgid ""
|
msgid ""
|
||||||
"Define number of section filters to be disabled.\n"
|
"Define number of section filters to be disabled.\n"
|
||||||
"\n"
|
"\n"
|
||||||
"Certain section filters might cause some unwanted behaviour to VDR such as time being falsely synchronized. By blacklisting the filters here, useful section data can be left intact for VDR to process."
|
"Certain section filters might cause some unwanted behaviour to VDR such as time being falsely synchronized. By black-listing the filters here useful section data can be left intact for VDR to process."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Defineix el numero de filtres de secció que seran deshabilitats.\n"
|
"Defineix el numero de filtres de secció que seran deshabilitats.\n"
|
||||||
"\n"
|
"\n"
|
||||||
@ -187,23 +130,8 @@ msgstr "Filtra"
|
|||||||
msgid "Define an ill-behaving filter to be blacklisted."
|
msgid "Define an ill-behaving filter to be blacklisted."
|
||||||
msgstr "Definir un filtre mal comportar a la llista negra."
|
msgstr "Definir un filtre mal comportar a la llista negra."
|
||||||
|
|
||||||
msgid "Transport mode"
|
msgid "Active SAT>IP devices:"
|
||||||
msgstr "Tipus de Transmissió"
|
msgstr "Dispositius SAT>IP actius:"
|
||||||
|
|
||||||
msgid ""
|
|
||||||
"Define which transport mode shall be used.\n"
|
|
||||||
"\n"
|
|
||||||
"Unicast, Multicast, RTP-over-TCP"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "Enable frontend reuse"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "Define whether reusing a frontend for multiple channels in a transponder should be enabled."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "Active SAT>IP servers:"
|
|
||||||
msgstr "Activa SAT>IP servers:"
|
|
||||||
|
|
||||||
msgid "Help"
|
msgid "Help"
|
||||||
msgstr "Ajuda"
|
msgstr "Ajuda"
|
||||||
|
121
po/de_DE.po
121
po/de_DE.po
@ -1,14 +1,14 @@
|
|||||||
# VDR plugin language source file.
|
# VDR plugin language source file.
|
||||||
# Copyright (C) 2007-2019 Rolf Ahrenberg
|
# Copyright (C) 2007-2014 Rolf Ahrenberg
|
||||||
# This file is distributed under the same license as the satip package.
|
# This file is distributed under the same license as the satip package.
|
||||||
# Frank Neumann, 2014-2017
|
# Frank Neumann, 2014
|
||||||
#
|
#
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: vdr-satip 2.4.0\n"
|
"Project-Id-Version: vdr-satip 0.3.2\n"
|
||||||
"Report-Msgid-Bugs-To: <see README>\n"
|
"Report-Msgid-Bugs-To: <see README>\n"
|
||||||
"POT-Creation-Date: 2019-10-27 19:12+0200\n"
|
"POT-Creation-Date: 2014-05-10 05:10+0200\n"
|
||||||
"PO-Revision-Date: 2019-10-27 10:27+0200\n"
|
"PO-Revision-Date: 2014-05-10 05:10+0200\n"
|
||||||
"Last-Translator: Frank Neumann <fnu@yavdr.org>\n"
|
"Last-Translator: Frank Neumann <fnu@yavdr.org>\n"
|
||||||
"Language-Team: German <vdr@linuxtv.org>\n"
|
"Language-Team: German <vdr@linuxtv.org>\n"
|
||||||
"Language: de\n"
|
"Language: de\n"
|
||||||
@ -31,14 +31,11 @@ msgstr "EIT (0x4E/0x4F/0x5X/0x6X)"
|
|||||||
msgid "TDT (0x70)"
|
msgid "TDT (0x70)"
|
||||||
msgstr "TDT (0x70)"
|
msgstr "TDT (0x70)"
|
||||||
|
|
||||||
msgid "SAT>IP information not available!"
|
|
||||||
msgstr "Keine SAT>IP Informationen verfügbar!"
|
|
||||||
|
|
||||||
msgid "SAT>IP Devices"
|
msgid "SAT>IP Devices"
|
||||||
msgstr "SAT>IP Geräte"
|
msgstr "SAT>IP Geräte"
|
||||||
|
|
||||||
msgid "SAT>IP Server"
|
msgid "SAT>IP Device"
|
||||||
msgstr "SAT>IP Server"
|
msgstr "SAT>IP Gerät"
|
||||||
|
|
||||||
msgid "Address"
|
msgid "Address"
|
||||||
msgstr "Adresse"
|
msgstr "Adresse"
|
||||||
@ -49,15 +46,9 @@ msgstr "Modell"
|
|||||||
msgid "Description"
|
msgid "Description"
|
||||||
msgstr "Beschreibung"
|
msgstr "Beschreibung"
|
||||||
|
|
||||||
msgid "CI extension"
|
|
||||||
msgstr "CI Erweiterung"
|
|
||||||
|
|
||||||
msgid "Creation date"
|
msgid "Creation date"
|
||||||
msgstr "Zeitpunkt der Erstellung"
|
msgstr "Zeitpunkt der Erstellung"
|
||||||
|
|
||||||
msgid "SAT>IP Device Status"
|
|
||||||
msgstr "SAT>IP Gerätestatus"
|
|
||||||
|
|
||||||
msgid "SAT>IP Information"
|
msgid "SAT>IP Information"
|
||||||
msgstr "SAT>IP Informationen"
|
msgstr "SAT>IP Informationen"
|
||||||
|
|
||||||
@ -73,6 +64,9 @@ msgstr "Filter"
|
|||||||
msgid "Bits/bytes"
|
msgid "Bits/bytes"
|
||||||
msgstr "Bits/Bytes"
|
msgstr "Bits/Bytes"
|
||||||
|
|
||||||
|
msgid "SAT>IP information not available!"
|
||||||
|
msgstr "Keine SAT>IP Informationen verfügbar!"
|
||||||
|
|
||||||
msgid "off"
|
msgid "off"
|
||||||
msgstr "aus"
|
msgstr "aus"
|
||||||
|
|
||||||
@ -85,20 +79,8 @@ msgstr "normal"
|
|||||||
msgid "high"
|
msgid "high"
|
||||||
msgstr "hoch"
|
msgstr "hoch"
|
||||||
|
|
||||||
msgid "Unicast"
|
|
||||||
msgstr "Unicast"
|
|
||||||
|
|
||||||
msgid "Multicast"
|
|
||||||
msgstr "Multicast"
|
|
||||||
|
|
||||||
msgid "RTP-over-TCP"
|
|
||||||
msgstr "RTP-over-TCP"
|
|
||||||
|
|
||||||
msgid "Button$Devices"
|
|
||||||
msgstr "Geräte"
|
|
||||||
|
|
||||||
msgid "Operating mode"
|
msgid "Operating mode"
|
||||||
msgstr "Betriebsart"
|
msgstr "Betriebsmodus"
|
||||||
|
|
||||||
msgid ""
|
msgid ""
|
||||||
"Define the used operating mode for all SAT>IP devices:\n"
|
"Define the used operating mode for all SAT>IP devices:\n"
|
||||||
@ -108,36 +90,12 @@ msgid ""
|
|||||||
"normal - devices are working within normal parameters\n"
|
"normal - devices are working within normal parameters\n"
|
||||||
"high - devices are working at the highest priority"
|
"high - devices are working at the highest priority"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Bestimme die Betriebsart für alle SAT>IP Geräte:\n"
|
"Bestimme den Betriebsmodus für alle SAT>IP Geräte:\n"
|
||||||
"\n"
|
"\n"
|
||||||
"aus - Geräte sind deaktiviert\n"
|
"aus - Geräte sind abgeschaltet\n"
|
||||||
"niedrig - Geräte arbeiten mit geringster Priorität\n"
|
"niedrig - Geräte arbeiten mit geringster Priorität\n"
|
||||||
"normal - Geräte arbeiten innerhalb der gewöhnlichen Parameter\n"
|
"normal - Geräte arbeiten innerhalb der gewöhnlichen Parameter\n"
|
||||||
"hoch - Geräte arbeiten mit höchster Priorität"
|
"hoch - Geräte arbeiten mit höchste Priorität"
|
||||||
|
|
||||||
msgid "Enable CI extension"
|
|
||||||
msgstr "Aktiviere CI Erweiterung"
|
|
||||||
|
|
||||||
msgid ""
|
|
||||||
"Define whether a CI extension shall be used.\n"
|
|
||||||
"\n"
|
|
||||||
"This setting enables integrated CI/CAM handling found in some SAT>IP hardware (e.g. Digital Devices OctopusNet)."
|
|
||||||
msgstr ""
|
|
||||||
"Legt fest ob eine CI Erweiterung genutzt werden soll.\n"
|
|
||||||
"\n"
|
|
||||||
"Diese Einstellung aktiviert die Nutzung des integrierten CI/CAM einiger SAT>IP Geräte (z.B. Digital Devices OctopusNet)."
|
|
||||||
|
|
||||||
msgid "CI/CAM"
|
|
||||||
msgstr "CI/CAM"
|
|
||||||
|
|
||||||
msgid ""
|
|
||||||
"Define a desired CAM type for the CI slot.\n"
|
|
||||||
"\n"
|
|
||||||
"The '---' option lets SAT>IP hardware do the auto-selection."
|
|
||||||
msgstr ""
|
|
||||||
"Bestimmt welcher CI Einschub für ein CAM genutzt werden soll.\n"
|
|
||||||
"\n"
|
|
||||||
"Die Option '---' überlässt der SAT>IP Hardware die automatische Auswahl."
|
|
||||||
|
|
||||||
msgid "Enable EPG scanning"
|
msgid "Enable EPG scanning"
|
||||||
msgstr "Aktiviere EPG Aktualisierung"
|
msgstr "Aktiviere EPG Aktualisierung"
|
||||||
@ -147,66 +105,33 @@ msgid ""
|
|||||||
"\n"
|
"\n"
|
||||||
"This setting disables the automatic EIT scanning functionality for all SAT>IP devices."
|
"This setting disables the automatic EIT scanning functionality for all SAT>IP devices."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Legt fest ob EPG im Hintergrund aktualisiert werden soll oder nicht.\n"
|
"Definiert ob EPG im Hintergrund aktualisiert werden soll oder nicht.\n"
|
||||||
"\n"
|
"\n"
|
||||||
"Diese Einstellung schaltet die automatische EIT Aktualisierung für alle SAT>IP Geräte aus."
|
"Diese Einstellung schaltet die automatische EIT Aktualisierung für alle SAT>IP Geräte."
|
||||||
|
|
||||||
msgid "Disabled sources"
|
msgid "Disabled filters"
|
||||||
msgstr "Deaktivierte Quellen"
|
msgstr "Deaktivierte Filter"
|
||||||
|
|
||||||
msgid "none"
|
msgid "none"
|
||||||
msgstr "keine"
|
msgstr "keine"
|
||||||
|
|
||||||
msgid ""
|
|
||||||
"Define number of sources to be disabled.\n"
|
|
||||||
"\n"
|
|
||||||
"SAT>IP servers might not have all satellite positions available and such sources can be blacklisted here."
|
|
||||||
msgstr ""
|
|
||||||
"Legt die Anzahl der deaktivierten Quellen fest.\n"
|
|
||||||
"\n"
|
|
||||||
"Für einige SAT>IP server sind nicht alle Satellitenpositionen verfügbar, nicht verfügbare Quellen können hier ausgeblendet werden"
|
|
||||||
|
|
||||||
msgid "Define a source to be blacklisted."
|
|
||||||
msgstr "Bestimme eine Quelle, die ausgeblendet wird"
|
|
||||||
|
|
||||||
msgid "Disabled filters"
|
|
||||||
msgstr "Deaktivierte Filter"
|
|
||||||
|
|
||||||
msgid ""
|
msgid ""
|
||||||
"Define number of section filters to be disabled.\n"
|
"Define number of section filters to be disabled.\n"
|
||||||
"\n"
|
"\n"
|
||||||
"Certain section filters might cause some unwanted behaviour to VDR such as time being falsely synchronized. By blacklisting the filters here, useful section data can be left intact for VDR to process."
|
"Certain section filters might cause some unwanted behaviour to VDR such as time being falsely synchronized. By black-listing the filters here useful section data can be left intact for VDR to process."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Bestimme die Anzahl der Abschnittsfilter die deaktiviert werden sollen.\n"
|
"Bestimme die Anzahl der Abschnittsfilter die deaktiviert werden sollen.\n"
|
||||||
"\n"
|
"\n"
|
||||||
"Bestimmte Abschnittsfilter können unerwünschtes Verhalten mit VDR, z.B. falsche Zeit-Synchronisation, verursachen. Durch das Ausblenden einzelner Filter können nützliche Daten dieser Abschnitte für den VDR erhalten bleiben."
|
"Bestimmte Abschnittsfilter können unerwünschtes Verhalten mit VDR, z.B. falsche Zeit-Synchronisation, verursachen. Durch das Ausblenden einzelner Filter können nützliche Daten dieser Abschnitte für den VDR erhalten werden."
|
||||||
|
|
||||||
msgid "Filter"
|
msgid "Filter"
|
||||||
msgstr "Filter"
|
msgstr "Filter"
|
||||||
|
|
||||||
msgid "Define an ill-behaving filter to be blacklisted."
|
msgid "Define an ill-behaving filter to be blacklisted."
|
||||||
msgstr "Bestimme fehlerhafte Filter die ausgeblendet werden sollen."
|
msgstr "Bestimme einen fehlerhaften Filter der ausgeblendet werden soll."
|
||||||
|
|
||||||
msgid "Transport mode"
|
msgid "Active SAT>IP devices:"
|
||||||
msgstr "Übertragungsart"
|
msgstr "Aktive SAT>IP Geräte:"
|
||||||
|
|
||||||
msgid ""
|
|
||||||
"Define which transport mode shall be used.\n"
|
|
||||||
"\n"
|
|
||||||
"Unicast, Multicast, RTP-over-TCP"
|
|
||||||
msgstr ""
|
|
||||||
"Lege die gewünschte Übertragungsart fest.\n"
|
|
||||||
"\n"
|
|
||||||
"Unicast, Multicast, RTP-over-TCP"
|
|
||||||
|
|
||||||
msgid "Enable frontend reuse"
|
|
||||||
msgstr "Frontend Mehrfachnutzung aktivieren"
|
|
||||||
|
|
||||||
msgid "Define whether reusing a frontend for multiple channels in a transponder should be enabled."
|
|
||||||
msgstr "Festlegung ob ein Tuner-Frontend für mehrere Kanäle genutzt wird."
|
|
||||||
|
|
||||||
msgid "Active SAT>IP servers:"
|
|
||||||
msgstr "Aktive SAT>IP Server:"
|
|
||||||
|
|
||||||
msgid "Help"
|
msgid "Help"
|
||||||
msgstr "Hilfe"
|
msgstr "Hilfe"
|
||||||
|
102
po/es_ES.po
102
po/es_ES.po
@ -1,14 +1,14 @@
|
|||||||
# VDR plugin language source file.
|
# VDR plugin language source file.
|
||||||
# Copyright (C) 2007-2019 Rolf Ahrenberg
|
# Copyright (C) 2007-2014 Rolf Ahrenberg
|
||||||
# This file is distributed under the same license as the satip package.
|
# This file is distributed under the same license as the satip package.
|
||||||
# Gabriel Bonich, 2014-2017
|
# Gabriel Bonich, 2014
|
||||||
#
|
#
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: vdr-satip 2.4.0\n"
|
"Project-Id-Version: vdr-satip 0.3.2\n"
|
||||||
"Report-Msgid-Bugs-To: <see README>\n"
|
"Report-Msgid-Bugs-To: <see README>\n"
|
||||||
"POT-Creation-Date: 2019-10-27 19:12+0200\n"
|
"POT-Creation-Date: 2014-05-10 05:10+0200\n"
|
||||||
"PO-Revision-Date: 2019-10-27 10:27+0200\n"
|
"PO-Revision-Date: 2014-05-10 05:10+0200\n"
|
||||||
"Last-Translator: Gabriel Bonich <gbonich@gmail.com>\n"
|
"Last-Translator: Gabriel Bonich <gbonich@gmail.com>\n"
|
||||||
"Language-Team: Spanish <vdr@linuxtv.org>\n"
|
"Language-Team: Spanish <vdr@linuxtv.org>\n"
|
||||||
"Language: es\n"
|
"Language: es\n"
|
||||||
@ -31,14 +31,11 @@ msgstr "EIT (0x4E/0x4F/0x5X/0x6X)"
|
|||||||
msgid "TDT (0x70)"
|
msgid "TDT (0x70)"
|
||||||
msgstr "TDT (0x70)"
|
msgstr "TDT (0x70)"
|
||||||
|
|
||||||
msgid "SAT>IP information not available!"
|
|
||||||
msgstr "SAT>IP Información no disponible!"
|
|
||||||
|
|
||||||
msgid "SAT>IP Devices"
|
msgid "SAT>IP Devices"
|
||||||
msgstr "SAT>IP Dispositivos"
|
msgstr "SAT>IP Dispositivos"
|
||||||
|
|
||||||
msgid "SAT>IP Server"
|
msgid "SAT>IP Device"
|
||||||
msgstr "SAT>IP Server"
|
msgstr "SAT>IP Dispositivo"
|
||||||
|
|
||||||
msgid "Address"
|
msgid "Address"
|
||||||
msgstr "Dirección"
|
msgstr "Dirección"
|
||||||
@ -49,15 +46,9 @@ msgstr "Modelo"
|
|||||||
msgid "Description"
|
msgid "Description"
|
||||||
msgstr "Descripción"
|
msgstr "Descripción"
|
||||||
|
|
||||||
msgid "CI extension"
|
|
||||||
msgstr "Extensión CI"
|
|
||||||
|
|
||||||
msgid "Creation date"
|
msgid "Creation date"
|
||||||
msgstr "Fecha creación"
|
msgstr "Fecha creación"
|
||||||
|
|
||||||
msgid "SAT>IP Device Status"
|
|
||||||
msgstr "SAT>IP Estado del Dispositivo"
|
|
||||||
|
|
||||||
msgid "SAT>IP Information"
|
msgid "SAT>IP Information"
|
||||||
msgstr "SAT>IP Información"
|
msgstr "SAT>IP Información"
|
||||||
|
|
||||||
@ -73,6 +64,9 @@ msgstr "Filtros"
|
|||||||
msgid "Bits/bytes"
|
msgid "Bits/bytes"
|
||||||
msgstr "Bits/Bytes"
|
msgstr "Bits/Bytes"
|
||||||
|
|
||||||
|
msgid "SAT>IP information not available!"
|
||||||
|
msgstr "SAT>IP Información no disponible!"
|
||||||
|
|
||||||
msgid "off"
|
msgid "off"
|
||||||
msgstr "Apagado"
|
msgstr "Apagado"
|
||||||
|
|
||||||
@ -85,18 +79,6 @@ msgstr "Normal"
|
|||||||
msgid "high"
|
msgid "high"
|
||||||
msgstr "Alto"
|
msgstr "Alto"
|
||||||
|
|
||||||
msgid "Unicast"
|
|
||||||
msgstr "Unicast"
|
|
||||||
|
|
||||||
msgid "Multicast"
|
|
||||||
msgstr "Multicast"
|
|
||||||
|
|
||||||
msgid "RTP-over-TCP"
|
|
||||||
msgstr "RTP-antes que-TCP"
|
|
||||||
|
|
||||||
msgid "Button$Devices"
|
|
||||||
msgstr "Dispositivos"
|
|
||||||
|
|
||||||
msgid "Operating mode"
|
msgid "Operating mode"
|
||||||
msgstr "Modo de operación"
|
msgstr "Modo de operación"
|
||||||
|
|
||||||
@ -115,30 +97,6 @@ msgstr ""
|
|||||||
"Normal - Dispositivos trabajando con prioridad Normal\n"
|
"Normal - Dispositivos trabajando con prioridad Normal\n"
|
||||||
"Alta - Dispositivos trabajando con prioridad Alta"
|
"Alta - Dispositivos trabajando con prioridad Alta"
|
||||||
|
|
||||||
msgid "Enable CI extension"
|
|
||||||
msgstr "Habilitar extensión CI"
|
|
||||||
|
|
||||||
msgid ""
|
|
||||||
"Define whether a CI extension shall be used.\n"
|
|
||||||
"\n"
|
|
||||||
"This setting enables integrated CI/CAM handling found in some SAT>IP hardware (e.g. Digital Devices OctopusNet)."
|
|
||||||
msgstr ""
|
|
||||||
"Definir si se utilizará una extensión de CI.\n"
|
|
||||||
"\n"
|
|
||||||
"Esto permite la configuración CI/CAM integrado que se encuentra en algunos equipos SAT>IP (ej. Digital Devices OctopusNet)."
|
|
||||||
|
|
||||||
msgid "CI/CAM"
|
|
||||||
msgstr "CI/CAM"
|
|
||||||
|
|
||||||
msgid ""
|
|
||||||
"Define a desired CAM type for the CI slot.\n"
|
|
||||||
"\n"
|
|
||||||
"The '---' option lets SAT>IP hardware do the auto-selection."
|
|
||||||
msgstr ""
|
|
||||||
"Definir el tipo de CAM para la ranura CI.\n"
|
|
||||||
"\n"
|
|
||||||
"La opción '---' permite al equipo SAT>IP hacer la selección automática."
|
|
||||||
|
|
||||||
msgid "Enable EPG scanning"
|
msgid "Enable EPG scanning"
|
||||||
msgstr "Activa Escaneo EPG"
|
msgstr "Activa Escaneo EPG"
|
||||||
|
|
||||||
@ -151,31 +109,16 @@ msgstr ""
|
|||||||
"\n"
|
"\n"
|
||||||
"Esta configuración desactiva la funcionalidad del escaneo EIT automática para todos los Dispositivos SAT>IP."
|
"Esta configuración desactiva la funcionalidad del escaneo EIT automática para todos los Dispositivos SAT>IP."
|
||||||
|
|
||||||
msgid "Disabled sources"
|
msgid "Disabled filters"
|
||||||
msgstr "Desactiva fuentes"
|
msgstr "Desactiva filtros"
|
||||||
|
|
||||||
msgid "none"
|
msgid "none"
|
||||||
msgstr "no"
|
msgstr "no"
|
||||||
|
|
||||||
msgid ""
|
|
||||||
"Define number of sources to be disabled.\n"
|
|
||||||
"\n"
|
|
||||||
"SAT>IP servers might not have all satellite positions available and such sources can be blacklisted here."
|
|
||||||
msgstr ""
|
|
||||||
"Definir número de fuentes desactivadas.\n"
|
|
||||||
"\n"
|
|
||||||
"SAT>IP servidores que no tenga todas las posiciones de los satélites disponibles y estas se ponen en la lista negra."
|
|
||||||
|
|
||||||
msgid "Define a source to be blacklisted."
|
|
||||||
msgstr "Define fuentes de la lista negra"
|
|
||||||
|
|
||||||
msgid "Disabled filters"
|
|
||||||
msgstr "Desactiva filtros"
|
|
||||||
|
|
||||||
msgid ""
|
msgid ""
|
||||||
"Define number of section filters to be disabled.\n"
|
"Define number of section filters to be disabled.\n"
|
||||||
"\n"
|
"\n"
|
||||||
"Certain section filters might cause some unwanted behaviour to VDR such as time being falsely synchronized. By blacklisting the filters here, useful section data can be left intact for VDR to process."
|
"Certain section filters might cause some unwanted behaviour to VDR such as time being falsely synchronized. By black-listing the filters here useful section data can be left intact for VDR to process."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Define el numero de filtros de sección que seran deshabilitados.\n"
|
"Define el numero de filtros de sección que seran deshabilitados.\n"
|
||||||
"\n"
|
"\n"
|
||||||
@ -187,23 +130,8 @@ msgstr "Filtra"
|
|||||||
msgid "Define an ill-behaving filter to be blacklisted."
|
msgid "Define an ill-behaving filter to be blacklisted."
|
||||||
msgstr "Define un filtro para poner en la lista negra."
|
msgstr "Define un filtro para poner en la lista negra."
|
||||||
|
|
||||||
msgid "Transport mode"
|
msgid "Active SAT>IP devices:"
|
||||||
msgstr "Tipo de Transmisión"
|
msgstr "Dispositivos SAT>IP activos:"
|
||||||
|
|
||||||
msgid ""
|
|
||||||
"Define which transport mode shall be used.\n"
|
|
||||||
"\n"
|
|
||||||
"Unicast, Multicast, RTP-over-TCP"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "Enable frontend reuse"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "Define whether reusing a frontend for multiple channels in a transponder should be enabled."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "Active SAT>IP servers:"
|
|
||||||
msgstr "Activa SAT>IP servers:"
|
|
||||||
|
|
||||||
msgid "Help"
|
msgid "Help"
|
||||||
msgstr "Ayuda"
|
msgstr "Ayuda"
|
||||||
|
105
po/fi_FI.po
105
po/fi_FI.po
@ -1,14 +1,14 @@
|
|||||||
# VDR plugin language source file.
|
# VDR plugin language source file.
|
||||||
# Copyright (C) 2007-2019 Rolf Ahrenberg
|
# Copyright (C) 2007-2014 Rolf Ahrenberg
|
||||||
# This file is distributed under the same license as the satip package.
|
# This file is distributed under the same license as the satip package.
|
||||||
# Rolf Ahrenberg, 2015-2019
|
# Rolf Ahrenberg, 2014
|
||||||
#
|
#
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: vdr-satip 2.4.0\n"
|
"Project-Id-Version: vdr-satip 0.3.2\n"
|
||||||
"Report-Msgid-Bugs-To: <see README>\n"
|
"Report-Msgid-Bugs-To: <see README>\n"
|
||||||
"POT-Creation-Date: 2019-10-27 19:12+0200\n"
|
"POT-Creation-Date: 2014-05-10 05:10+0200\n"
|
||||||
"PO-Revision-Date: 2019-10-27 10:27+0200\n"
|
"PO-Revision-Date: 2014-05-10 05:10+0200\n"
|
||||||
"Last-Translator: Rolf Ahrenberg\n"
|
"Last-Translator: Rolf Ahrenberg\n"
|
||||||
"Language-Team: Finnish <vdr@linuxtv.org>\n"
|
"Language-Team: Finnish <vdr@linuxtv.org>\n"
|
||||||
"Language: fi\n"
|
"Language: fi\n"
|
||||||
@ -31,14 +31,11 @@ msgstr "EIT (0x4E/0x4F/0x5X/0x6X)"
|
|||||||
msgid "TDT (0x70)"
|
msgid "TDT (0x70)"
|
||||||
msgstr "TDT (0x70)"
|
msgstr "TDT (0x70)"
|
||||||
|
|
||||||
msgid "SAT>IP information not available!"
|
|
||||||
msgstr "SAT>IP-tietoja ei saatavilla!"
|
|
||||||
|
|
||||||
msgid "SAT>IP Devices"
|
msgid "SAT>IP Devices"
|
||||||
msgstr "SAT>IP-laitteet"
|
msgstr "SAT>IP-laitteet"
|
||||||
|
|
||||||
msgid "SAT>IP Server"
|
msgid "SAT>IP Device"
|
||||||
msgstr "SAT>IP-palvelin"
|
msgstr "SAT>IP-laite"
|
||||||
|
|
||||||
msgid "Address"
|
msgid "Address"
|
||||||
msgstr "Osoite"
|
msgstr "Osoite"
|
||||||
@ -49,15 +46,9 @@ msgstr "Malli"
|
|||||||
msgid "Description"
|
msgid "Description"
|
||||||
msgstr "Kuvaus"
|
msgstr "Kuvaus"
|
||||||
|
|
||||||
msgid "CI extension"
|
|
||||||
msgstr "CI-laajennos"
|
|
||||||
|
|
||||||
msgid "Creation date"
|
msgid "Creation date"
|
||||||
msgstr "Luontiajankohta"
|
msgstr "Luontiajankohta"
|
||||||
|
|
||||||
msgid "SAT>IP Device Status"
|
|
||||||
msgstr "SAT>IP-laitteiden tiedot"
|
|
||||||
|
|
||||||
msgid "SAT>IP Information"
|
msgid "SAT>IP Information"
|
||||||
msgstr "SAT>IP-tiedot"
|
msgstr "SAT>IP-tiedot"
|
||||||
|
|
||||||
@ -73,6 +64,9 @@ msgstr "Suodattimet"
|
|||||||
msgid "Bits/bytes"
|
msgid "Bits/bytes"
|
||||||
msgstr "Bitit/tavut"
|
msgstr "Bitit/tavut"
|
||||||
|
|
||||||
|
msgid "SAT>IP information not available!"
|
||||||
|
msgstr "SAT>IP-tietoja ei saatavilla!"
|
||||||
|
|
||||||
msgid "off"
|
msgid "off"
|
||||||
msgstr "ei käytössä"
|
msgstr "ei käytössä"
|
||||||
|
|
||||||
@ -85,18 +79,6 @@ msgstr "normaali"
|
|||||||
msgid "high"
|
msgid "high"
|
||||||
msgstr "korkea"
|
msgstr "korkea"
|
||||||
|
|
||||||
msgid "Unicast"
|
|
||||||
msgstr "Unicast"
|
|
||||||
|
|
||||||
msgid "Multicast"
|
|
||||||
msgstr "Multicast"
|
|
||||||
|
|
||||||
msgid "RTP-over-TCP"
|
|
||||||
msgstr "RTP-over-TCP"
|
|
||||||
|
|
||||||
msgid "Button$Devices"
|
|
||||||
msgstr "Laitteet"
|
|
||||||
|
|
||||||
msgid "Operating mode"
|
msgid "Operating mode"
|
||||||
msgstr "Laitteiden toimintatapa"
|
msgstr "Laitteiden toimintatapa"
|
||||||
|
|
||||||
@ -114,30 +96,6 @@ msgstr ""
|
|||||||
"normaali - laitteet toimivat normaalilla prioriteetilla\n"
|
"normaali - laitteet toimivat normaalilla prioriteetilla\n"
|
||||||
"korkea - laitteet toimivat korkealla prioriteetilla"
|
"korkea - laitteet toimivat korkealla prioriteetilla"
|
||||||
|
|
||||||
msgid "Enable CI extension"
|
|
||||||
msgstr "Käytä CI-laajennosta"
|
|
||||||
|
|
||||||
msgid ""
|
|
||||||
"Define whether a CI extension shall be used.\n"
|
|
||||||
"\n"
|
|
||||||
"This setting enables integrated CI/CAM handling found in some SAT>IP hardware (e.g. Digital Devices OctopusNet)."
|
|
||||||
msgstr ""
|
|
||||||
"Määrittele CI-laajennoksen käyttöönotto\n"
|
|
||||||
"\n"
|
|
||||||
"Tällä asetuksella saadaan otettua käyttöön SAT>IP-laitteiden sisäinen CI-paikka (esim. Digital Devices OctopusNet)."
|
|
||||||
|
|
||||||
msgid "CI/CAM"
|
|
||||||
msgstr "CI/CAM"
|
|
||||||
|
|
||||||
msgid ""
|
|
||||||
"Define a desired CAM type for the CI slot.\n"
|
|
||||||
"\n"
|
|
||||||
"The '---' option lets SAT>IP hardware do the auto-selection."
|
|
||||||
msgstr ""
|
|
||||||
"Määrittele haluttu CAM-tyyppi CI-paikalle.\n"
|
|
||||||
"\n"
|
|
||||||
"Vaihtoehto '---' antaa SAT>IP-laitteen valita automaattisesti käytetyn CI-paikan."
|
|
||||||
|
|
||||||
msgid "Enable EPG scanning"
|
msgid "Enable EPG scanning"
|
||||||
msgstr "Käytä ohjelmaoppaan taustapäivitystä"
|
msgstr "Käytä ohjelmaoppaan taustapäivitystä"
|
||||||
|
|
||||||
@ -150,31 +108,16 @@ msgstr ""
|
|||||||
"\n"
|
"\n"
|
||||||
"Tällä asetuksella saadaan otettua automaattinen EIT-datan päivitys pois päältä kaikilta SAT>IP-laitteilta."
|
"Tällä asetuksella saadaan otettua automaattinen EIT-datan päivitys pois päältä kaikilta SAT>IP-laitteilta."
|
||||||
|
|
||||||
msgid "Disabled sources"
|
msgid "Disabled filters"
|
||||||
msgstr "Käytöstä poistetut lähteet"
|
msgstr "Käytöstä poistetut suodattimet"
|
||||||
|
|
||||||
msgid "none"
|
msgid "none"
|
||||||
msgstr "tyhjä"
|
msgstr "tyhjä"
|
||||||
|
|
||||||
msgid ""
|
|
||||||
"Define number of sources to be disabled.\n"
|
|
||||||
"\n"
|
|
||||||
"SAT>IP servers might not have all satellite positions available and such sources can be blacklisted here."
|
|
||||||
msgstr ""
|
|
||||||
"Määrittele käytöstä poistettavien lähteiden lukumäärä.\n"
|
|
||||||
"\n"
|
|
||||||
"SAT>IP-palvelimilla ei välttämättä ole kaikkia ohjelmalähteitä tarjolla."
|
|
||||||
|
|
||||||
msgid "Define a source to be blacklisted."
|
|
||||||
msgstr "Määrittele käytöstä"
|
|
||||||
|
|
||||||
msgid "Disabled filters"
|
|
||||||
msgstr "Käytöstä poistetut suodattimet"
|
|
||||||
|
|
||||||
msgid ""
|
msgid ""
|
||||||
"Define number of section filters to be disabled.\n"
|
"Define number of section filters to be disabled.\n"
|
||||||
"\n"
|
"\n"
|
||||||
"Certain section filters might cause some unwanted behaviour to VDR such as time being falsely synchronized. By blacklisting the filters here, useful section data can be left intact for VDR to process."
|
"Certain section filters might cause some unwanted behaviour to VDR such as time being falsely synchronized. By black-listing the filters here useful section data can be left intact for VDR to process."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Määrittele käytöstä poistettavien suodattimien lukumäärä sektioille.\n"
|
"Määrittele käytöstä poistettavien suodattimien lukumäärä sektioille.\n"
|
||||||
"\n"
|
"\n"
|
||||||
@ -186,26 +129,8 @@ msgstr "Suodatin"
|
|||||||
msgid "Define an ill-behaving filter to be blacklisted."
|
msgid "Define an ill-behaving filter to be blacklisted."
|
||||||
msgstr "Määrittele käytöstä poistettava suodatin, joka lisätään mustalle listalle."
|
msgstr "Määrittele käytöstä poistettava suodatin, joka lisätään mustalle listalle."
|
||||||
|
|
||||||
msgid "Transport mode"
|
msgid "Active SAT>IP devices:"
|
||||||
msgstr "Siirtoyhteystapa"
|
msgstr "Aktiiviset SAT>IP-laitteet:"
|
||||||
|
|
||||||
msgid ""
|
|
||||||
"Define which transport mode shall be used.\n"
|
|
||||||
"\n"
|
|
||||||
"Unicast, Multicast, RTP-over-TCP"
|
|
||||||
msgstr ""
|
|
||||||
"Määrittele käytettävä siirtoyhteystapa.\n"
|
|
||||||
"\n"
|
|
||||||
"Unicast, Multicast, RTP-over-TCP"
|
|
||||||
|
|
||||||
msgid "Enable frontend reuse"
|
|
||||||
msgstr "Uusiokäytä virittimiä"
|
|
||||||
|
|
||||||
msgid "Define whether reusing a frontend for multiple channels in a transponder should be enabled."
|
|
||||||
msgstr "Määrittele virittien uusiokäyttö kanaville, jotka ovat samalla transponderilla."
|
|
||||||
|
|
||||||
msgid "Active SAT>IP servers:"
|
|
||||||
msgstr "Aktiiviset SAT>IP-palvelimet:"
|
|
||||||
|
|
||||||
msgid "Help"
|
msgid "Help"
|
||||||
msgstr "Opaste"
|
msgstr "Opaste"
|
||||||
|
212
po/pl_PL.po
212
po/pl_PL.po
@ -1,212 +0,0 @@
|
|||||||
# VDR plugin language source file.
|
|
||||||
# Copyright (C) 2007-2019 Rolf Ahrenberg
|
|
||||||
# This file is distributed under the same license as the vdr-satip package.
|
|
||||||
# Tomasz Maciej Nowak, 2017
|
|
||||||
#
|
|
||||||
msgid ""
|
|
||||||
msgstr ""
|
|
||||||
"Project-Id-Version: vdr-satip 2.4.0\n"
|
|
||||||
"Report-Msgid-Bugs-To: <see README>\n"
|
|
||||||
"POT-Creation-Date: 2019-10-27 19:12+0200\n"
|
|
||||||
"PO-Revision-Date: 2019-10-27 10:27+0200\n"
|
|
||||||
"Last-Translator: Tomasz Maciej Nowak <tomek_n@o2.pl>\n"
|
|
||||||
"Language-Team: Polish <vdr@linuxtv.org>\n"
|
|
||||||
"Language: pl_PL\n"
|
|
||||||
"MIME-Version: 1.0\n"
|
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
|
||||||
"X-Generator: Poedit 1.8.11\n"
|
|
||||||
|
|
||||||
msgid "PAT (0x00)"
|
|
||||||
msgstr "PAT (0x00)"
|
|
||||||
|
|
||||||
msgid "NIT (0x40)"
|
|
||||||
msgstr "NIT (0x40)"
|
|
||||||
|
|
||||||
msgid "SDT (0x42)"
|
|
||||||
msgstr "SDT (0x42)"
|
|
||||||
|
|
||||||
msgid "EIT (0x4E/0x4F/0x5X/0x6X)"
|
|
||||||
msgstr "EIT (0x4E/0x4F/0x5X/0x6X)"
|
|
||||||
|
|
||||||
msgid "TDT (0x70)"
|
|
||||||
msgstr "TDT (0x70)"
|
|
||||||
|
|
||||||
msgid "SAT>IP information not available!"
|
|
||||||
msgstr "Informacja o SAT>IP niedostępna!"
|
|
||||||
|
|
||||||
msgid "SAT>IP Devices"
|
|
||||||
msgstr "Urządzenia SAT>IP"
|
|
||||||
|
|
||||||
msgid "SAT>IP Server"
|
|
||||||
msgstr "Serwer SAT>IP"
|
|
||||||
|
|
||||||
msgid "Address"
|
|
||||||
msgstr "Adres"
|
|
||||||
|
|
||||||
msgid "Model"
|
|
||||||
msgstr "Model"
|
|
||||||
|
|
||||||
msgid "Description"
|
|
||||||
msgstr "Opis"
|
|
||||||
|
|
||||||
msgid "CI extension"
|
|
||||||
msgstr "Rozszerzenie CI"
|
|
||||||
|
|
||||||
msgid "Creation date"
|
|
||||||
msgstr "Data produkcji"
|
|
||||||
|
|
||||||
msgid "SAT>IP Device Status"
|
|
||||||
msgstr "Status urządzenia SAT>IP"
|
|
||||||
|
|
||||||
msgid "SAT>IP Information"
|
|
||||||
msgstr "SAT>IP - informacje"
|
|
||||||
|
|
||||||
msgid "General"
|
|
||||||
msgstr "Główne"
|
|
||||||
|
|
||||||
msgid "Pids"
|
|
||||||
msgstr "Pidy"
|
|
||||||
|
|
||||||
msgid "Filters"
|
|
||||||
msgstr "Filtry"
|
|
||||||
|
|
||||||
msgid "Bits/bytes"
|
|
||||||
msgstr "Bity/bajty"
|
|
||||||
|
|
||||||
msgid "off"
|
|
||||||
msgstr "wyłączone"
|
|
||||||
|
|
||||||
msgid "low"
|
|
||||||
msgstr "niski"
|
|
||||||
|
|
||||||
msgid "normal"
|
|
||||||
msgstr "normalny"
|
|
||||||
|
|
||||||
msgid "high"
|
|
||||||
msgstr "wysoki"
|
|
||||||
|
|
||||||
msgid "Unicast"
|
|
||||||
msgstr "Unicast"
|
|
||||||
|
|
||||||
msgid "Multicast"
|
|
||||||
msgstr "Multicast"
|
|
||||||
|
|
||||||
msgid "RTP-over-TCP"
|
|
||||||
msgstr "RTP-over-TCP"
|
|
||||||
|
|
||||||
msgid "Button$Devices"
|
|
||||||
msgstr "Urządzenia"
|
|
||||||
|
|
||||||
msgid "Operating mode"
|
|
||||||
msgstr "Tryb pracy"
|
|
||||||
|
|
||||||
msgid ""
|
|
||||||
"Define the used operating mode for all SAT>IP devices:\n"
|
|
||||||
"\n"
|
|
||||||
"off - devices are disabled\n"
|
|
||||||
"low - devices are working at the lowest priority\n"
|
|
||||||
"normal - devices are working within normal parameters\n"
|
|
||||||
"high - devices are working at the highest priority"
|
|
||||||
msgstr ""
|
|
||||||
"Określa tryb pracy wszystkich urządzeń SAT>IP:\n"
|
|
||||||
"\n"
|
|
||||||
"wyłączone - urządzenia są wyłączone\n"
|
|
||||||
"niski - urządzenia pracują z najniższym priorytetem\n"
|
|
||||||
"normalny - urządzenia pracują z normalnymi parametrami\n"
|
|
||||||
"wysoki - urządzenia pracują z najwyższym priorytetem"
|
|
||||||
|
|
||||||
msgid "Enable CI extension"
|
|
||||||
msgstr "Włącz rozszerzenie CI"
|
|
||||||
|
|
||||||
msgid ""
|
|
||||||
"Define whether a CI extension shall be used.\n"
|
|
||||||
"\n"
|
|
||||||
"This setting enables integrated CI/CAM handling found in some SAT>IP hardware (e.g. Digital Devices OctopusNet)."
|
|
||||||
msgstr ""
|
|
||||||
"Określa czy korzystać z rozszerzenia CI.\n"
|
|
||||||
"\n"
|
|
||||||
"To ustawienie włącza obsługę dostępnego czytnika CI/CAM w niektórych urządzeniach SAT>IP (np. Digital Devices OctopusNet)."
|
|
||||||
|
|
||||||
msgid "CI/CAM"
|
|
||||||
msgstr "CI/CAM"
|
|
||||||
|
|
||||||
msgid ""
|
|
||||||
"Define a desired CAM type for the CI slot.\n"
|
|
||||||
"\n"
|
|
||||||
"The '---' option lets SAT>IP hardware do the auto-selection."
|
|
||||||
msgstr ""
|
|
||||||
"Określa typ modułu CAM w czytniku CI.\n"
|
|
||||||
"\n"
|
|
||||||
"Opcja '---' pozwala urządzeniu SAT>IP automatycznie wybrać typ."
|
|
||||||
|
|
||||||
msgid "Enable EPG scanning"
|
|
||||||
msgstr "Włącz skanowanie EPG"
|
|
||||||
|
|
||||||
msgid ""
|
|
||||||
"Define whether the EPG background scanning shall be used.\n"
|
|
||||||
"\n"
|
|
||||||
"This setting disables the automatic EIT scanning functionality for all SAT>IP devices."
|
|
||||||
msgstr ""
|
|
||||||
"Określa czy przeprowadzać skanowanie EPG w tle.\n"
|
|
||||||
"\n"
|
|
||||||
"To ustawienie wyłącza funkcję automatycznego skanowania EIT dla wszystkich urządzeń SAT>IP."
|
|
||||||
|
|
||||||
msgid "Disabled sources"
|
|
||||||
msgstr "Wyłączone źródła"
|
|
||||||
|
|
||||||
msgid "none"
|
|
||||||
msgstr "brak"
|
|
||||||
|
|
||||||
msgid ""
|
|
||||||
"Define number of sources to be disabled.\n"
|
|
||||||
"\n"
|
|
||||||
"SAT>IP servers might not have all satellite positions available and such sources can be blacklisted here."
|
|
||||||
msgstr ""
|
|
||||||
"Określa liczbę wyłączonych źródeł.\n"
|
|
||||||
"\n"
|
|
||||||
"Serwery SAT>IP mogą nie mieć dostępu do niektórych pozycji satelitarnych, więc tutaj można je wyłączyć."
|
|
||||||
|
|
||||||
msgid "Define a source to be blacklisted."
|
|
||||||
msgstr "Określ źródła do wyłączenia."
|
|
||||||
|
|
||||||
msgid "Disabled filters"
|
|
||||||
msgstr "Wyłączone filtry"
|
|
||||||
|
|
||||||
msgid ""
|
|
||||||
"Define number of section filters to be disabled.\n"
|
|
||||||
"\n"
|
|
||||||
"Certain section filters might cause some unwanted behaviour to VDR such as time being falsely synchronized. By blacklisting the filters here, useful section data can be left intact for VDR to process."
|
|
||||||
msgstr ""
|
|
||||||
"Określa liczbę wyłączonych filtrów sekcji.\n"
|
|
||||||
"\n"
|
|
||||||
"Niektóre filtry sekcji mogą powodować niezamierzone efekty w VDR, takie jak zły czas synchronizacji. Poprzez wyłączenie niektórych filtrów, użyteczne dane sekcji będą dostępne do przetworzenia dla VDR."
|
|
||||||
|
|
||||||
msgid "Filter"
|
|
||||||
msgstr "Filtr"
|
|
||||||
|
|
||||||
msgid "Define an ill-behaving filter to be blacklisted."
|
|
||||||
msgstr "Określa filtry powodujące zakłócenia, które mają być wyłączone."
|
|
||||||
|
|
||||||
msgid "Transport mode"
|
|
||||||
msgstr "Tryb"
|
|
||||||
|
|
||||||
msgid ""
|
|
||||||
"Define which transport mode shall be used.\n"
|
|
||||||
"\n"
|
|
||||||
"Unicast, Multicast, RTP-over-TCP"
|
|
||||||
msgstr ""
|
|
||||||
"Określa tryb transmisji.\n"
|
|
||||||
"Unicast, Multicast, RTP-over-TCP."
|
|
||||||
|
|
||||||
msgid "Enable frontend reuse"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "Define whether reusing a frontend for multiple channels in a transponder should be enabled."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "Active SAT>IP servers:"
|
|
||||||
msgstr "Aktywne serwery SAT>IP:"
|
|
||||||
|
|
||||||
msgid "Help"
|
|
||||||
msgstr "Pomoc"
|
|
122
poller.c
122
poller.c
@ -1,122 +0,0 @@
|
|||||||
/*
|
|
||||||
* poller.c: SAT>IP plugin for the Video Disk Recorder
|
|
||||||
*
|
|
||||||
* See the README file for copyright information and how to reach the author.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define __STDC_FORMAT_MACROS // Required for format specifiers
|
|
||||||
#include <inttypes.h>
|
|
||||||
#include <sys/epoll.h>
|
|
||||||
|
|
||||||
#include "config.h"
|
|
||||||
#include "common.h"
|
|
||||||
#include "log.h"
|
|
||||||
#include "poller.h"
|
|
||||||
|
|
||||||
cSatipPoller *cSatipPoller::instanceS = NULL;
|
|
||||||
|
|
||||||
cSatipPoller *cSatipPoller::GetInstance(void)
|
|
||||||
{
|
|
||||||
if (!instanceS)
|
|
||||||
instanceS = new cSatipPoller();
|
|
||||||
return instanceS;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool cSatipPoller::Initialize(void)
|
|
||||||
{
|
|
||||||
debug1("%s", __PRETTY_FUNCTION__);
|
|
||||||
if (instanceS)
|
|
||||||
instanceS->Activate();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void cSatipPoller::Destroy(void)
|
|
||||||
{
|
|
||||||
debug1("%s", __PRETTY_FUNCTION__);
|
|
||||||
if (instanceS)
|
|
||||||
instanceS->Deactivate();
|
|
||||||
}
|
|
||||||
|
|
||||||
cSatipPoller::cSatipPoller()
|
|
||||||
: cThread("SATIP poller"),
|
|
||||||
mutexM(),
|
|
||||||
fdM(epoll_create(eMaxFileDescriptors))
|
|
||||||
{
|
|
||||||
debug1("%s", __PRETTY_FUNCTION__);
|
|
||||||
}
|
|
||||||
|
|
||||||
cSatipPoller::~cSatipPoller()
|
|
||||||
{
|
|
||||||
debug1("%s", __PRETTY_FUNCTION__);
|
|
||||||
Deactivate();
|
|
||||||
cMutexLock MutexLock(&mutexM);
|
|
||||||
close(fdM);
|
|
||||||
// Free allocated memory
|
|
||||||
}
|
|
||||||
|
|
||||||
void cSatipPoller::Activate(void)
|
|
||||||
{
|
|
||||||
// Start the thread
|
|
||||||
Start();
|
|
||||||
}
|
|
||||||
|
|
||||||
void cSatipPoller::Deactivate(void)
|
|
||||||
{
|
|
||||||
debug1("%s", __PRETTY_FUNCTION__);
|
|
||||||
cMutexLock MutexLock(&mutexM);
|
|
||||||
if (Running())
|
|
||||||
Cancel(3);
|
|
||||||
}
|
|
||||||
|
|
||||||
void cSatipPoller::Action(void)
|
|
||||||
{
|
|
||||||
debug1("%s Entering", __PRETTY_FUNCTION__);
|
|
||||||
struct epoll_event events[eMaxFileDescriptors];
|
|
||||||
uint64_t maxElapsed = 0;
|
|
||||||
// Increase priority
|
|
||||||
SetPriority(-1);
|
|
||||||
// Do the thread loop
|
|
||||||
while (Running()) {
|
|
||||||
int nfds = epoll_wait(fdM, events, eMaxFileDescriptors, -1);
|
|
||||||
ERROR_IF_FUNC((nfds == -1 && errno != EINTR), "epoll_wait() failed", break, ;);
|
|
||||||
for (int i = 0; i < nfds; ++i) {
|
|
||||||
cSatipPollerIf* poll = reinterpret_cast<cSatipPollerIf *>(events[i].data.ptr);
|
|
||||||
if (poll) {
|
|
||||||
uint64_t elapsed;
|
|
||||||
cTimeMs processing(0);
|
|
||||||
poll->Process();
|
|
||||||
elapsed = processing.Elapsed();
|
|
||||||
if (elapsed > maxElapsed) {
|
|
||||||
maxElapsed = elapsed;
|
|
||||||
debug1("%s Processing %s took %" PRIu64 " ms", __PRETTY_FUNCTION__, *(poll->ToString()), maxElapsed);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
debug1("%s Exiting", __PRETTY_FUNCTION__);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool cSatipPoller::Register(cSatipPollerIf &pollerP)
|
|
||||||
{
|
|
||||||
debug1("%s fd=%d", __PRETTY_FUNCTION__, pollerP.GetFd());
|
|
||||||
cMutexLock MutexLock(&mutexM);
|
|
||||||
|
|
||||||
struct epoll_event ev;
|
|
||||||
ev.events = EPOLLIN | EPOLLET;
|
|
||||||
ev.data.ptr = &pollerP;
|
|
||||||
ERROR_IF_RET(epoll_ctl(fdM, EPOLL_CTL_ADD, pollerP.GetFd(), &ev) == -1, "epoll_ctl(EPOLL_CTL_ADD) failed", return false);
|
|
||||||
debug1("%s Added interface fd=%d", __PRETTY_FUNCTION__, pollerP.GetFd());
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool cSatipPoller::Unregister(cSatipPollerIf &pollerP)
|
|
||||||
{
|
|
||||||
debug1("%s fd=%d", __PRETTY_FUNCTION__, pollerP.GetFd());
|
|
||||||
cMutexLock MutexLock(&mutexM);
|
|
||||||
ERROR_IF_RET((epoll_ctl(fdM, EPOLL_CTL_DEL, pollerP.GetFd(), NULL) == -1), "epoll_ctl(EPOLL_CTL_DEL) failed", return false);
|
|
||||||
debug1("%s Removed interface fd=%d", __PRETTY_FUNCTION__, pollerP.GetFd());
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
44
poller.h
44
poller.h
@ -1,44 +0,0 @@
|
|||||||
/*
|
|
||||||
* poller.h: SAT>IP plugin for the Video Disk Recorder
|
|
||||||
*
|
|
||||||
* See the README file for copyright information and how to reach the author.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef __SATIP_POLLER_H
|
|
||||||
#define __SATIP_POLLER_H
|
|
||||||
|
|
||||||
#include <vdr/thread.h>
|
|
||||||
#include <vdr/tools.h>
|
|
||||||
|
|
||||||
#include "pollerif.h"
|
|
||||||
|
|
||||||
class cSatipPoller : public cThread {
|
|
||||||
private:
|
|
||||||
enum {
|
|
||||||
eMaxFileDescriptors = SATIP_MAX_DEVICES * 2, // Data + Application
|
|
||||||
};
|
|
||||||
static cSatipPoller *instanceS;
|
|
||||||
cMutex mutexM;
|
|
||||||
int fdM;
|
|
||||||
void Activate(void);
|
|
||||||
void Deactivate(void);
|
|
||||||
// constructor
|
|
||||||
cSatipPoller();
|
|
||||||
// to prevent copy constructor and assignment
|
|
||||||
cSatipPoller(const cSatipPoller&);
|
|
||||||
cSatipPoller& operator=(const cSatipPoller&);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
virtual void Action(void);
|
|
||||||
|
|
||||||
public:
|
|
||||||
static cSatipPoller *GetInstance(void);
|
|
||||||
static bool Initialize(void);
|
|
||||||
static void Destroy(void);
|
|
||||||
virtual ~cSatipPoller();
|
|
||||||
bool Register(cSatipPollerIf &pollerP);
|
|
||||||
bool Unregister(cSatipPollerIf &pollerP);
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // __SATIP_POLLER_H
|
|
25
pollerif.h
25
pollerif.h
@ -1,25 +0,0 @@
|
|||||||
/*
|
|
||||||
* pollerif.h: SAT>IP plugin for the Video Disk Recorder
|
|
||||||
*
|
|
||||||
* See the README file for copyright information and how to reach the author.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef __SATIP_POLLERIF_H
|
|
||||||
#define __SATIP_POLLERIF_H
|
|
||||||
|
|
||||||
class cSatipPollerIf {
|
|
||||||
public:
|
|
||||||
cSatipPollerIf() {}
|
|
||||||
virtual ~cSatipPollerIf() {}
|
|
||||||
virtual int GetFd(void) = 0;
|
|
||||||
virtual void Process(void) = 0;
|
|
||||||
virtual void Process(unsigned char *dataP, int lengthP) = 0;
|
|
||||||
virtual cString ToString(void) const = 0;
|
|
||||||
|
|
||||||
private:
|
|
||||||
explicit cSatipPollerIf(const cSatipPollerIf&);
|
|
||||||
cSatipPollerIf& operator=(const cSatipPollerIf&);
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // __SATIP_POLLERIF_H
|
|
108
rtcp.c
108
rtcp.c
@ -1,108 +0,0 @@
|
|||||||
/*
|
|
||||||
* rtcp.c: SAT>IP plugin for the Video Disk Recorder
|
|
||||||
*
|
|
||||||
* See the README file for copyright information and how to reach the author.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "config.h"
|
|
||||||
#include "common.h"
|
|
||||||
#include "log.h"
|
|
||||||
#include "rtcp.h"
|
|
||||||
|
|
||||||
cSatipRtcp::cSatipRtcp(cSatipTunerIf &tunerP)
|
|
||||||
: tunerM(tunerP),
|
|
||||||
bufferLenM(eApplicationMaxSizeB),
|
|
||||||
bufferM(MALLOC(unsigned char, bufferLenM))
|
|
||||||
{
|
|
||||||
debug1("%s [device %d]", __PRETTY_FUNCTION__, tunerM.GetId());
|
|
||||||
if (bufferM)
|
|
||||||
memset(bufferM, 0, bufferLenM);
|
|
||||||
else
|
|
||||||
error("Cannot create RTCP buffer! [device %d]", tunerM.GetId());
|
|
||||||
}
|
|
||||||
|
|
||||||
cSatipRtcp::~cSatipRtcp()
|
|
||||||
{
|
|
||||||
debug1("%s [device %d]", __PRETTY_FUNCTION__, tunerM.GetId());
|
|
||||||
FREE_POINTER(bufferM);
|
|
||||||
}
|
|
||||||
|
|
||||||
int cSatipRtcp::GetFd(void)
|
|
||||||
{
|
|
||||||
debug16("%s [device %d]", __PRETTY_FUNCTION__, tunerM.GetId());
|
|
||||||
return Fd();
|
|
||||||
}
|
|
||||||
|
|
||||||
int cSatipRtcp::GetApplicationOffset(unsigned char *bufferP, int *lengthP)
|
|
||||||
{
|
|
||||||
debug16("%s (%d) [device %d]", __PRETTY_FUNCTION__, lengthP ? *lengthP : -1, tunerM.GetId());
|
|
||||||
if (!lengthP)
|
|
||||||
return -1;
|
|
||||||
int offset = 0;
|
|
||||||
int total = *lengthP;
|
|
||||||
while (total > 0) {
|
|
||||||
// Version
|
|
||||||
unsigned int v = (bufferP[offset] >> 6) & 0x03;
|
|
||||||
// Padding
|
|
||||||
//unsigned int p = (bufferP[offset] >> 5) & 0x01;
|
|
||||||
// Subtype
|
|
||||||
//unsigned int st = bufferP[offset] & 0x1F;
|
|
||||||
// Payload type
|
|
||||||
unsigned int pt = bufferP[offset + 1] & 0xFF;
|
|
||||||
// Length
|
|
||||||
unsigned int length = ((bufferP[offset + 2] & 0xFF) << 8) | (bufferP[offset + 3] & 0xFF);
|
|
||||||
// Convert it to bytes
|
|
||||||
length = (length + 1) * 4;
|
|
||||||
// V=2, APP = 204
|
|
||||||
if ((v == 2) && (pt == 204)) {
|
|
||||||
// SSCR/CSCR
|
|
||||||
//unsigned int ssrc = ((bufferP[offset + 4] & 0xFF) << 24) | ((bufferP[offset + 5] & 0xFF) << 16) |
|
|
||||||
// ((bufferP[offset + 6] & 0xFF) << 8) | (bufferP[offset + 7] & 0xFF);
|
|
||||||
// Name
|
|
||||||
if ((bufferP[offset + 8] == 'S') && (bufferP[offset + 9] == 'E') &&
|
|
||||||
(bufferP[offset + 10] == 'S') && (bufferP[offset + 11] == '1')) {
|
|
||||||
// Identifier
|
|
||||||
//unsigned int id = ((bufferP[offset + 12] & 0xFF) << 8) | (bufferP[offset + 13] & 0xFF);
|
|
||||||
// String length
|
|
||||||
int string_length = ((bufferP[offset + 14] & 0xFF) << 8) | (bufferP[offset + 15] & 0xFF);
|
|
||||||
if (string_length > 0) {
|
|
||||||
*lengthP = string_length;
|
|
||||||
return (offset + 16);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
offset += length;
|
|
||||||
total -= length;
|
|
||||||
}
|
|
||||||
*lengthP = 0;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void cSatipRtcp::Process(void)
|
|
||||||
{
|
|
||||||
debug16("%s [device %d]", __PRETTY_FUNCTION__, tunerM.GetId());
|
|
||||||
if (bufferM) {
|
|
||||||
int length;
|
|
||||||
while ((length = Read(bufferM, bufferLenM)) > 0) {
|
|
||||||
int offset = GetApplicationOffset(bufferM, &length);
|
|
||||||
if (offset >= 0)
|
|
||||||
tunerM.ProcessApplicationData(bufferM + offset, length);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void cSatipRtcp::Process(unsigned char *dataP, int lengthP)
|
|
||||||
{
|
|
||||||
debug16("%s [device %d]", __PRETTY_FUNCTION__, tunerM.GetId());
|
|
||||||
if (dataP && lengthP > 0) {
|
|
||||||
int offset = GetApplicationOffset(dataP, &lengthP);
|
|
||||||
if (offset >= 0)
|
|
||||||
tunerM.ProcessApplicationData(dataP + offset, lengthP);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
cString cSatipRtcp::ToString(void) const
|
|
||||||
{
|
|
||||||
return cString::sprintf("RTCP [device %d]", tunerM.GetId());
|
|
||||||
}
|
|
37
rtcp.h
37
rtcp.h
@ -1,37 +0,0 @@
|
|||||||
/*
|
|
||||||
* rtcp.h: SAT>IP plugin for the Video Disk Recorder
|
|
||||||
*
|
|
||||||
* See the README file for copyright information and how to reach the author.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef __SATIP_RTCP_H_
|
|
||||||
#define __SATIP_RTCP_H_
|
|
||||||
|
|
||||||
#include "socket.h"
|
|
||||||
#include "tunerif.h"
|
|
||||||
#include "pollerif.h"
|
|
||||||
|
|
||||||
class cSatipRtcp : public cSatipSocket, public cSatipPollerIf {
|
|
||||||
private:
|
|
||||||
enum {
|
|
||||||
eApplicationMaxSizeB = 1500,
|
|
||||||
};
|
|
||||||
cSatipTunerIf &tunerM;
|
|
||||||
unsigned int bufferLenM;
|
|
||||||
unsigned char *bufferM;
|
|
||||||
int GetApplicationOffset(unsigned char *bufferP, int *lengthP);
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit cSatipRtcp(cSatipTunerIf &tunerP);
|
|
||||||
virtual ~cSatipRtcp();
|
|
||||||
|
|
||||||
// for internal poller interface
|
|
||||||
public:
|
|
||||||
virtual int GetFd(void);
|
|
||||||
virtual void Process(void);
|
|
||||||
virtual void Process(unsigned char *dataP, int lengthP);
|
|
||||||
virtual cString ToString(void) const;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif /* __SATIP_RTCP_H_ */
|
|
165
rtp.c
165
rtp.c
@ -1,165 +0,0 @@
|
|||||||
/*
|
|
||||||
* rtp.c: SAT>IP plugin for the Video Disk Recorder
|
|
||||||
*
|
|
||||||
* See the README file for copyright information and how to reach the author.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define __STDC_FORMAT_MACROS // Required for format specifiers
|
|
||||||
#include <inttypes.h>
|
|
||||||
|
|
||||||
#include "config.h"
|
|
||||||
#include "common.h"
|
|
||||||
#include "log.h"
|
|
||||||
#include "rtp.h"
|
|
||||||
|
|
||||||
cSatipRtp::cSatipRtp(cSatipTunerIf &tunerP)
|
|
||||||
: cSatipSocket(SatipConfig.GetRtpRcvBufSize()),
|
|
||||||
tunerM(tunerP),
|
|
||||||
bufferLenM(eRtpPacketReadCount * eMaxUdpPacketSizeB),
|
|
||||||
bufferM(MALLOC(unsigned char, bufferLenM)),
|
|
||||||
lastErrorReportM(0),
|
|
||||||
packetErrorsM(0),
|
|
||||||
sequenceNumberM(-1)
|
|
||||||
{
|
|
||||||
debug1("%s () [device %d]", __PRETTY_FUNCTION__, tunerM.GetId());
|
|
||||||
if (!bufferM)
|
|
||||||
error("Cannot create RTP buffer! [device %d]", tunerM.GetId());
|
|
||||||
}
|
|
||||||
|
|
||||||
cSatipRtp::~cSatipRtp()
|
|
||||||
{
|
|
||||||
debug1("%s [device %d]", __PRETTY_FUNCTION__, tunerM.GetId());
|
|
||||||
FREE_POINTER(bufferM);
|
|
||||||
}
|
|
||||||
|
|
||||||
int cSatipRtp::GetFd(void)
|
|
||||||
{
|
|
||||||
return Fd();
|
|
||||||
}
|
|
||||||
|
|
||||||
void cSatipRtp::Close(void)
|
|
||||||
{
|
|
||||||
debug1("%s [device %d]", __PRETTY_FUNCTION__, tunerM.GetId());
|
|
||||||
|
|
||||||
cSatipSocket::Close();
|
|
||||||
|
|
||||||
sequenceNumberM = -1;
|
|
||||||
if (packetErrorsM) {
|
|
||||||
info("Detected %d RTP packet error%s [device %d]", packetErrorsM, packetErrorsM == 1 ? "": "s", tunerM.GetId());
|
|
||||||
packetErrorsM = 0;
|
|
||||||
lastErrorReportM = time(NULL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int cSatipRtp::GetHeaderLength(unsigned char *bufferP, unsigned int lengthP)
|
|
||||||
{
|
|
||||||
debug16("%s (, %d) [device %d]", __PRETTY_FUNCTION__, lengthP, tunerM.GetId());
|
|
||||||
unsigned int headerlen = 0;
|
|
||||||
|
|
||||||
if (lengthP > 0) {
|
|
||||||
if (bufferP[0] == TS_SYNC_BYTE)
|
|
||||||
return headerlen;
|
|
||||||
else if (lengthP > 3) {
|
|
||||||
// http://tools.ietf.org/html/rfc3550
|
|
||||||
// http://tools.ietf.org/html/rfc2250
|
|
||||||
// Version
|
|
||||||
unsigned int v = (bufferP[0] >> 6) & 0x03;
|
|
||||||
// Extension bit
|
|
||||||
unsigned int x = (bufferP[0] >> 4) & 0x01;
|
|
||||||
// CSCR count
|
|
||||||
unsigned int cc = bufferP[0] & 0x0F;
|
|
||||||
// Payload type: MPEG2 TS = 33
|
|
||||||
unsigned int pt = bufferP[1] & 0x7F;
|
|
||||||
if (pt != 33)
|
|
||||||
debug7("%s (%d) Received invalid RTP payload type %d - v=%d [device %d]",
|
|
||||||
__PRETTY_FUNCTION__, lengthP, pt, v, tunerM.GetId());
|
|
||||||
// Sequence number
|
|
||||||
int seq = ((bufferP[2] & 0xFF) << 8) | (bufferP[3] & 0xFF);
|
|
||||||
if ((((sequenceNumberM + 1) % 0xFFFF) == 0) && (seq == 0xFFFF))
|
|
||||||
sequenceNumberM = -1;
|
|
||||||
else if ((sequenceNumberM >= 0) && (((sequenceNumberM + 1) % 0xFFFF) != seq)) {
|
|
||||||
packetErrorsM++;
|
|
||||||
if (time(NULL) - lastErrorReportM > eReportIntervalS) {
|
|
||||||
info("Detected %d RTP packet error%s [device %d]", packetErrorsM, packetErrorsM == 1 ? "": "s", tunerM.GetId());
|
|
||||||
packetErrorsM = 0;
|
|
||||||
lastErrorReportM = time(NULL);
|
|
||||||
}
|
|
||||||
sequenceNumberM = seq;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
sequenceNumberM = seq;
|
|
||||||
// Header length
|
|
||||||
headerlen = (3 + cc) * (unsigned int)sizeof(uint32_t);
|
|
||||||
// Check if extension
|
|
||||||
if (x) {
|
|
||||||
// Extension header length
|
|
||||||
unsigned int ehl = (((bufferP[headerlen + 2] & 0xFF) << 8) | (bufferP[headerlen + 3] & 0xFF));
|
|
||||||
// Update header length
|
|
||||||
headerlen += (ehl + 1) * (unsigned int)sizeof(uint32_t);
|
|
||||||
}
|
|
||||||
// Check for empty payload
|
|
||||||
if (lengthP == headerlen) {
|
|
||||||
debug7("%s (%d) Received empty RTP packet #%d [device %d]", __PRETTY_FUNCTION__, lengthP, seq, tunerM.GetId());
|
|
||||||
headerlen = -1;
|
|
||||||
}
|
|
||||||
// Check that rtp is version 2 and payload contains multiple of TS packet data
|
|
||||||
else if ((v != 2) || (((lengthP - headerlen) % TS_SIZE) != 0) || (bufferP[headerlen] != TS_SYNC_BYTE)) {
|
|
||||||
debug7("%s (%d) Received incorrect RTP packet #%d v=%d len=%d sync=0x%02X [device %d]", __PRETTY_FUNCTION__,
|
|
||||||
lengthP, seq, v, headerlen, bufferP[headerlen], tunerM.GetId());
|
|
||||||
headerlen = -1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
debug7("%s (%d) Received RTP packet #%d v=%d len=%d sync=0x%02X [device %d]", __PRETTY_FUNCTION__,
|
|
||||||
lengthP, seq, v, headerlen, bufferP[headerlen], tunerM.GetId());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return headerlen;
|
|
||||||
}
|
|
||||||
|
|
||||||
void cSatipRtp::Process(void)
|
|
||||||
{
|
|
||||||
debug16("%s [device %d]", __PRETTY_FUNCTION__, tunerM.GetId());
|
|
||||||
if (bufferM) {
|
|
||||||
unsigned int lenMsg[eRtpPacketReadCount];
|
|
||||||
uint64_t elapsed;
|
|
||||||
int count = 0;
|
|
||||||
cTimeMs processing(0);
|
|
||||||
|
|
||||||
do {
|
|
||||||
count = ReadMulti(bufferM, lenMsg, eRtpPacketReadCount, eMaxUdpPacketSizeB);
|
|
||||||
for (int i = 0; i < count; ++i) {
|
|
||||||
unsigned char *p = &bufferM[i * eMaxUdpPacketSizeB];
|
|
||||||
int headerlen = GetHeaderLength(p, lenMsg[i]);
|
|
||||||
if ((headerlen >= 0) && (headerlen < (int)lenMsg[i]))
|
|
||||||
tunerM.ProcessVideoData(p + headerlen, lenMsg[i] - headerlen);
|
|
||||||
}
|
|
||||||
} while (count >= eRtpPacketReadCount);
|
|
||||||
|
|
||||||
elapsed = processing.Elapsed();
|
|
||||||
if (elapsed > 1)
|
|
||||||
debug6("%s %d read(s) took %" PRIu64 " ms [device %d]", __PRETTY_FUNCTION__, count, elapsed, tunerM.GetId());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void cSatipRtp::Process(unsigned char *dataP, int lengthP)
|
|
||||||
{
|
|
||||||
debug16("%s [device %d]", __PRETTY_FUNCTION__, tunerM.GetId());
|
|
||||||
if (dataP && lengthP > 0) {
|
|
||||||
uint64_t elapsed;
|
|
||||||
cTimeMs processing(0);
|
|
||||||
int headerlen = GetHeaderLength(dataP, lengthP);
|
|
||||||
if ((headerlen >= 0) && (headerlen < lengthP))
|
|
||||||
tunerM.ProcessVideoData(dataP + headerlen, lengthP - headerlen);
|
|
||||||
|
|
||||||
elapsed = processing.Elapsed();
|
|
||||||
if (elapsed > 1)
|
|
||||||
debug6("%s %d read(s) took %" PRIu64 " ms [device %d]", __PRETTY_FUNCTION__, lengthP, elapsed, tunerM.GetId());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
cString cSatipRtp::ToString(void) const
|
|
||||||
{
|
|
||||||
return cString::sprintf("RTP [device %d]", tunerM.GetId());
|
|
||||||
}
|
|
43
rtp.h
43
rtp.h
@ -1,43 +0,0 @@
|
|||||||
/*
|
|
||||||
* rtp.h: SAT>IP plugin for the Video Disk Recorder
|
|
||||||
*
|
|
||||||
* See the README file for copyright information and how to reach the author.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef __SATIP_RTP_H_
|
|
||||||
#define __SATIP_RTP_H_
|
|
||||||
|
|
||||||
#include "socket.h"
|
|
||||||
#include "tunerif.h"
|
|
||||||
#include "pollerif.h"
|
|
||||||
|
|
||||||
class cSatipRtp : public cSatipSocket, public cSatipPollerIf {
|
|
||||||
private:
|
|
||||||
enum {
|
|
||||||
eRtpPacketReadCount = 50,
|
|
||||||
eMaxUdpPacketSizeB = TS_SIZE * 7 + 12,
|
|
||||||
eReportIntervalS = 300 // in seconds
|
|
||||||
};
|
|
||||||
cSatipTunerIf &tunerM;
|
|
||||||
unsigned int bufferLenM;
|
|
||||||
unsigned char *bufferM;
|
|
||||||
time_t lastErrorReportM;
|
|
||||||
int packetErrorsM;
|
|
||||||
int sequenceNumberM;
|
|
||||||
int GetHeaderLength(unsigned char *bufferP, unsigned int lengthP);
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit cSatipRtp(cSatipTunerIf &tunerP);
|
|
||||||
virtual ~cSatipRtp();
|
|
||||||
virtual void Close(void);
|
|
||||||
|
|
||||||
// for internal poller interface
|
|
||||||
public:
|
|
||||||
virtual int GetFd(void);
|
|
||||||
virtual void Process(void);
|
|
||||||
virtual void Process(unsigned char *dataP, int lengthP);
|
|
||||||
virtual cString ToString(void) const;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif /* __SATIP_RTP_H_ */
|
|
568
rtsp.c
568
rtsp.c
@ -1,568 +0,0 @@
|
|||||||
/*
|
|
||||||
* rtsp.c: SAT>IP plugin for the Video Disk Recorder
|
|
||||||
*
|
|
||||||
* See the README file for copyright information and how to reach the author.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define __STDC_FORMAT_MACROS // Required for format specifiers
|
|
||||||
#include <inttypes.h>
|
|
||||||
|
|
||||||
#include "config.h"
|
|
||||||
#include "common.h"
|
|
||||||
#include "log.h"
|
|
||||||
#include "rtsp.h"
|
|
||||||
|
|
||||||
cSatipRtsp::cSatipRtsp(cSatipTunerIf &tunerP)
|
|
||||||
: tunerM(tunerP),
|
|
||||||
headerBufferM(),
|
|
||||||
dataBufferM(),
|
|
||||||
handleM(NULL),
|
|
||||||
headerListM(NULL),
|
|
||||||
errorNoMoreM(""),
|
|
||||||
errorOutOfRangeM(""),
|
|
||||||
errorCheckSyntaxM(""),
|
|
||||||
modeM(cSatipConfig::eTransportModeUnicast),
|
|
||||||
interleavedRtpIdM(0),
|
|
||||||
interleavedRtcpIdM(1)
|
|
||||||
{
|
|
||||||
debug1("%s [device %d]", __PRETTY_FUNCTION__, tunerM.GetId());
|
|
||||||
Create();
|
|
||||||
}
|
|
||||||
|
|
||||||
cSatipRtsp::~cSatipRtsp()
|
|
||||||
{
|
|
||||||
debug1("%s [device %d]", __PRETTY_FUNCTION__, tunerM.GetId());
|
|
||||||
Destroy();
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t cSatipRtsp::HeaderCallback(char *ptrP, size_t sizeP, size_t nmembP, void *dataP)
|
|
||||||
{
|
|
||||||
cSatipRtsp *obj = reinterpret_cast<cSatipRtsp *>(dataP);
|
|
||||||
size_t len = sizeP * nmembP;
|
|
||||||
debug16("%s len=%zu", __PRETTY_FUNCTION__, len);
|
|
||||||
|
|
||||||
if (obj && (len > 0))
|
|
||||||
obj->headerBufferM.Add(ptrP, len);
|
|
||||||
|
|
||||||
return len;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t cSatipRtsp::DataCallback(char *ptrP, size_t sizeP, size_t nmembP, void *dataP)
|
|
||||||
{
|
|
||||||
cSatipRtsp *obj = reinterpret_cast<cSatipRtsp *>(dataP);
|
|
||||||
size_t len = sizeP * nmembP;
|
|
||||||
debug16("%s len=%zu", __PRETTY_FUNCTION__, len);
|
|
||||||
|
|
||||||
if (obj)
|
|
||||||
obj->dataBufferM.Add(ptrP, len);
|
|
||||||
|
|
||||||
return len;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t cSatipRtsp::InterleaveCallback(char *ptrP, size_t sizeP, size_t nmembP, void *dataP)
|
|
||||||
{
|
|
||||||
cSatipRtsp *obj = reinterpret_cast<cSatipRtsp *>(dataP);
|
|
||||||
size_t len = sizeP * nmembP;
|
|
||||||
debug16("%s len=%zu", __PRETTY_FUNCTION__, len);
|
|
||||||
|
|
||||||
if (obj && ptrP && len > 0) {
|
|
||||||
char tag = ptrP[0] & 0xFF;
|
|
||||||
if (tag == '$') {
|
|
||||||
int count = ((ptrP[2] & 0xFF) << 8) | (ptrP[3] & 0xFF);
|
|
||||||
if (count > 0) {
|
|
||||||
unsigned int channel = ptrP[1] & 0xFF;
|
|
||||||
u_char *data = (u_char *)&ptrP[4];
|
|
||||||
if (channel == obj->interleavedRtpIdM)
|
|
||||||
obj->tunerM.ProcessRtpData(data, count);
|
|
||||||
else if (channel == obj->interleavedRtcpIdM)
|
|
||||||
obj->tunerM.ProcessRtcpData(data, count);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return len;
|
|
||||||
}
|
|
||||||
|
|
||||||
int cSatipRtsp::DebugCallback(CURL *handleP, curl_infotype typeP, char *dataP, size_t sizeP, void *userPtrP)
|
|
||||||
{
|
|
||||||
cSatipRtsp *obj = reinterpret_cast<cSatipRtsp *>(userPtrP);
|
|
||||||
|
|
||||||
if (obj) {
|
|
||||||
switch (typeP) {
|
|
||||||
case CURLINFO_TEXT:
|
|
||||||
debug2("%s [device %d] RTSP INFO %.*s", __PRETTY_FUNCTION__, obj->tunerM.GetId(), (int)sizeP, dataP);
|
|
||||||
break;
|
|
||||||
case CURLINFO_HEADER_IN:
|
|
||||||
debug2("%s [device %d] RTSP HEAD <<< %.*s", __PRETTY_FUNCTION__, obj->tunerM.GetId(), (int)sizeP, dataP);
|
|
||||||
break;
|
|
||||||
case CURLINFO_HEADER_OUT:
|
|
||||||
debug2("%s [device %d] RTSP HEAD >>>\n%.*s", __PRETTY_FUNCTION__, obj->tunerM.GetId(), (int)sizeP, dataP);
|
|
||||||
break;
|
|
||||||
case CURLINFO_DATA_IN:
|
|
||||||
debug2("%s [device %d] RTSP DATA <<< %.*s", __PRETTY_FUNCTION__, obj->tunerM.GetId(), (int)sizeP, dataP);
|
|
||||||
break;
|
|
||||||
case CURLINFO_DATA_OUT:
|
|
||||||
debug2("%s [device %d] RTSP DATA >>>\n%.*s", __PRETTY_FUNCTION__, obj->tunerM.GetId(), (int)sizeP, dataP);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
cString cSatipRtsp::GetActiveMode(void)
|
|
||||||
{
|
|
||||||
switch (modeM) {
|
|
||||||
case cSatipConfig::eTransportModeUnicast:
|
|
||||||
return "Unicast";
|
|
||||||
case cSatipConfig::eTransportModeMulticast:
|
|
||||||
return "Multicast";
|
|
||||||
case cSatipConfig::eTransportModeRtpOverTcp:
|
|
||||||
return "RTP-over-TCP";
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
cString cSatipRtsp::RtspUnescapeString(const char *strP)
|
|
||||||
{
|
|
||||||
debug1("%s (%s) [device %d]", __PRETTY_FUNCTION__, strP, tunerM.GetId());
|
|
||||||
if (handleM) {
|
|
||||||
char *p = curl_easy_unescape(handleM, strP, 0, NULL);
|
|
||||||
cString s = p;
|
|
||||||
curl_free(p);
|
|
||||||
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
return cString(strP);
|
|
||||||
}
|
|
||||||
|
|
||||||
void cSatipRtsp::Create(void)
|
|
||||||
{
|
|
||||||
debug1("%s [device %d]", __PRETTY_FUNCTION__, tunerM.GetId());
|
|
||||||
if (!handleM)
|
|
||||||
handleM = curl_easy_init();
|
|
||||||
|
|
||||||
if (handleM) {
|
|
||||||
CURLcode res = CURLE_OK;
|
|
||||||
|
|
||||||
// Verbose output
|
|
||||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_VERBOSE, 1L);
|
|
||||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_DEBUGFUNCTION, cSatipRtsp::DebugCallback);
|
|
||||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_DEBUGDATA, this);
|
|
||||||
|
|
||||||
// No progress meter and no signaling
|
|
||||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_NOPROGRESS, 1L);
|
|
||||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_NOSIGNAL, 1L);
|
|
||||||
|
|
||||||
// Set timeouts
|
|
||||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_TIMEOUT_MS, (long)eConnectTimeoutMs);
|
|
||||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_CONNECTTIMEOUT_MS, (long)eConnectTimeoutMs);
|
|
||||||
|
|
||||||
// Set user-agent
|
|
||||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_USERAGENT, *cString::sprintf("vdr-%s/%s (device %d)", PLUGIN_NAME_I18N, VERSION, tunerM.GetId()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void cSatipRtsp::Destroy(void)
|
|
||||||
{
|
|
||||||
debug1("%s [device %d]", __PRETTY_FUNCTION__, tunerM.GetId());
|
|
||||||
if (handleM) {
|
|
||||||
// Cleanup curl stuff
|
|
||||||
if (headerListM) {
|
|
||||||
curl_slist_free_all(headerListM);
|
|
||||||
headerListM = NULL;
|
|
||||||
}
|
|
||||||
curl_easy_cleanup(handleM);
|
|
||||||
handleM = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void cSatipRtsp::Reset(void)
|
|
||||||
{
|
|
||||||
debug1("%s [device %d]", __PRETTY_FUNCTION__, tunerM.GetId());
|
|
||||||
Destroy();
|
|
||||||
Create();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool cSatipRtsp::SetInterface(const char *bindAddrP)
|
|
||||||
{
|
|
||||||
debug1("%s (%s) [device %d]", __PRETTY_FUNCTION__, bindAddrP, tunerM.GetId());
|
|
||||||
bool result = true;
|
|
||||||
CURLcode res = CURLE_OK;
|
|
||||||
|
|
||||||
if (handleM && !isempty(bindAddrP)) {
|
|
||||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_INTERFACE, *cString::sprintf("host!%s", bindAddrP));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_INTERFACE, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool cSatipRtsp::Receive(const char *uriP)
|
|
||||||
{
|
|
||||||
debug1("%s (%s) [device %d]", __PRETTY_FUNCTION__, uriP, tunerM.GetId());
|
|
||||||
bool result = false;
|
|
||||||
|
|
||||||
if (handleM && !isempty(uriP) && modeM == cSatipConfig::eTransportModeRtpOverTcp) {
|
|
||||||
long rc = 0;
|
|
||||||
cTimeMs processing(0);
|
|
||||||
CURLcode res = CURLE_OK;
|
|
||||||
|
|
||||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_URL, uriP);
|
|
||||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_RTSP_STREAM_URI, uriP);
|
|
||||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_RTSP_REQUEST, (long)CURL_RTSPREQ_OPTIONS); // FIXME: this really should be CURL_RTSPREQ_RECEIVE, but getting timeout errors
|
|
||||||
SATIP_CURL_EASY_PERFORM(handleM);
|
|
||||||
|
|
||||||
result = ValidateLatestResponse(&rc);
|
|
||||||
debug5("%s (%s) Response %ld in %" PRIu64 " ms [device %d]", __PRETTY_FUNCTION__, uriP, rc, processing.Elapsed(), tunerM.GetId());
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool cSatipRtsp::Options(const char *uriP)
|
|
||||||
{
|
|
||||||
debug1("%s (%s) [device %d]", __PRETTY_FUNCTION__, uriP, tunerM.GetId());
|
|
||||||
bool result = false;
|
|
||||||
|
|
||||||
if (handleM && !isempty(uriP)) {
|
|
||||||
long rc = 0;
|
|
||||||
cTimeMs processing(0);
|
|
||||||
CURLcode res = CURLE_OK;
|
|
||||||
|
|
||||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_URL, uriP);
|
|
||||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_RTSP_STREAM_URI, uriP);
|
|
||||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_RTSP_REQUEST, (long)CURL_RTSPREQ_OPTIONS);
|
|
||||||
SATIP_CURL_EASY_PERFORM(handleM);
|
|
||||||
|
|
||||||
result = ValidateLatestResponse(&rc);
|
|
||||||
debug5("%s (%s) Response %ld in %" PRIu64 " ms [device %d]", __PRETTY_FUNCTION__, uriP, rc, processing.Elapsed(), tunerM.GetId());
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool cSatipRtsp::Setup(const char *uriP, int rtpPortP, int rtcpPortP, bool useTcpP)
|
|
||||||
{
|
|
||||||
debug1("%s (%s, %d, %d, %d) [device %d]", __PRETTY_FUNCTION__, uriP, rtpPortP, rtcpPortP, useTcpP, tunerM.GetId());
|
|
||||||
bool result = false;
|
|
||||||
|
|
||||||
if (handleM && !isempty(uriP)) {
|
|
||||||
cString transport;
|
|
||||||
long rc = 0;
|
|
||||||
cTimeMs processing(0);
|
|
||||||
CURLcode res = CURLE_OK;
|
|
||||||
|
|
||||||
switch (SatipConfig.GetTransportMode()) {
|
|
||||||
case cSatipConfig::eTransportModeMulticast:
|
|
||||||
// RTP/AVP;multicast;destination=<multicast group address>;port=<RTP port>-<RTCP port>;ttl=<ttl>[;source=<multicast source address>]
|
|
||||||
transport = cString::sprintf("RTP/AVP;multicast");
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
// RTP/AVP;unicast;client_port=<client RTP port>-<client RTCP port>
|
|
||||||
// RTP/AVP/TCP;unicast;client_port=<client RTP port>-<client RTCP port>
|
|
||||||
if (useTcpP)
|
|
||||||
transport = cString::sprintf("RTP/AVP/TCP;unicast;interleaved=%u-%u", interleavedRtpIdM, interleavedRtcpIdM);
|
|
||||||
else
|
|
||||||
transport = cString::sprintf("RTP/AVP;unicast;client_port=%d-%d", rtpPortP, rtcpPortP);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Setup media stream
|
|
||||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_RTSP_STREAM_URI, uriP);
|
|
||||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_RTSP_TRANSPORT, *transport);
|
|
||||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_RTSP_REQUEST, (long)CURL_RTSPREQ_SETUP);
|
|
||||||
// Set header callback for catching the session and timeout
|
|
||||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_HEADERFUNCTION, cSatipRtsp::HeaderCallback);
|
|
||||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEHEADER, this);
|
|
||||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEFUNCTION, cSatipRtsp::DataCallback);
|
|
||||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEDATA, this);
|
|
||||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_INTERLEAVEFUNCTION, NULL);
|
|
||||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_INTERLEAVEDATA, NULL);
|
|
||||||
|
|
||||||
SATIP_CURL_EASY_PERFORM(handleM);
|
|
||||||
// Session id is now known - disable header parsing
|
|
||||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_HEADERFUNCTION, NULL);
|
|
||||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEHEADER, NULL);
|
|
||||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEFUNCTION, NULL);
|
|
||||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEDATA, NULL);
|
|
||||||
if (headerBufferM.Size() > 0) {
|
|
||||||
ParseHeader();
|
|
||||||
headerBufferM.Reset();
|
|
||||||
}
|
|
||||||
if (dataBufferM.Size() > 0) {
|
|
||||||
ParseData();
|
|
||||||
dataBufferM.Reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
result = ValidateLatestResponse(&rc);
|
|
||||||
debug5("%s (%s, %d, %d) Response %ld in %" PRIu64 " ms [device %d]", __PRETTY_FUNCTION__, uriP, rtpPortP, rtcpPortP, rc, processing.Elapsed(), tunerM.GetId());
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool cSatipRtsp::SetSession(const char *sessionP)
|
|
||||||
{
|
|
||||||
debug1("%s (%s) [device %d]", __PRETTY_FUNCTION__, sessionP, tunerM.GetId());
|
|
||||||
if (handleM) {
|
|
||||||
CURLcode res = CURLE_OK;
|
|
||||||
|
|
||||||
debug1("%s: session id quirk enabled [device %d]", __PRETTY_FUNCTION__, tunerM.GetId());
|
|
||||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_RTSP_SESSION_ID, sessionP);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool cSatipRtsp::Describe(const char *uriP)
|
|
||||||
{
|
|
||||||
debug1("%s (%s) [device %d]", __PRETTY_FUNCTION__, uriP, tunerM.GetId());
|
|
||||||
bool result = false;
|
|
||||||
|
|
||||||
if (handleM && !isempty(uriP)) {
|
|
||||||
long rc = 0;
|
|
||||||
cTimeMs processing(0);
|
|
||||||
CURLcode res = CURLE_OK;
|
|
||||||
|
|
||||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_RTSP_STREAM_URI, uriP);
|
|
||||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_RTSP_REQUEST, (long)CURL_RTSPREQ_DESCRIBE);
|
|
||||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEFUNCTION, cSatipRtsp::DataCallback);
|
|
||||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEDATA, this);
|
|
||||||
SATIP_CURL_EASY_PERFORM(handleM);
|
|
||||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEFUNCTION, NULL);
|
|
||||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEDATA, NULL);
|
|
||||||
if (dataBufferM.Size() > 0) {
|
|
||||||
tunerM.ProcessApplicationData((u_char *)dataBufferM.Data(), dataBufferM.Size());
|
|
||||||
dataBufferM.Reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
result = ValidateLatestResponse(&rc);
|
|
||||||
debug5("%s (%s) Response %ld in %" PRIu64 " ms [device %d]", __PRETTY_FUNCTION__, uriP, rc, processing.Elapsed(), tunerM.GetId());
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool cSatipRtsp::Play(const char *uriP)
|
|
||||||
{
|
|
||||||
debug1("%s (%s) [device %d]", __PRETTY_FUNCTION__, uriP, tunerM.GetId());
|
|
||||||
bool result = false;
|
|
||||||
|
|
||||||
if (handleM && !isempty(uriP)) {
|
|
||||||
long rc = 0;
|
|
||||||
cTimeMs processing(0);
|
|
||||||
CURLcode res = CURLE_OK;
|
|
||||||
|
|
||||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_RTSP_STREAM_URI, uriP);
|
|
||||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_RTSP_REQUEST, (long)CURL_RTSPREQ_PLAY);
|
|
||||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEFUNCTION, cSatipRtsp::DataCallback);
|
|
||||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEDATA, this);
|
|
||||||
SATIP_CURL_EASY_PERFORM(handleM);
|
|
||||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEFUNCTION, NULL);
|
|
||||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEDATA, NULL);
|
|
||||||
if (dataBufferM.Size() > 0) {
|
|
||||||
ParseData();
|
|
||||||
dataBufferM.Reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
result = ValidateLatestResponse(&rc);
|
|
||||||
debug5("%s (%s) Response %ld in %" PRIu64 " ms [device %d]", __PRETTY_FUNCTION__, uriP, rc, processing.Elapsed(), tunerM.GetId());
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool cSatipRtsp::Teardown(const char *uriP)
|
|
||||||
{
|
|
||||||
debug1("%s (%s) [device %d]", __PRETTY_FUNCTION__, uriP, tunerM.GetId());
|
|
||||||
bool result = false;
|
|
||||||
|
|
||||||
if (handleM && !isempty(uriP)) {
|
|
||||||
long rc = 0;
|
|
||||||
cTimeMs processing(0);
|
|
||||||
CURLcode res = CURLE_OK;
|
|
||||||
|
|
||||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_RTSP_STREAM_URI, uriP);
|
|
||||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_RTSP_REQUEST, (long)CURL_RTSPREQ_TEARDOWN);
|
|
||||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEFUNCTION, cSatipRtsp::DataCallback);
|
|
||||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEDATA, this);
|
|
||||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_INTERLEAVEFUNCTION, NULL);
|
|
||||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_INTERLEAVEDATA, NULL);
|
|
||||||
SATIP_CURL_EASY_PERFORM(handleM);
|
|
||||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEFUNCTION, NULL);
|
|
||||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEDATA, NULL);
|
|
||||||
if (dataBufferM.Size() > 0) {
|
|
||||||
ParseData();
|
|
||||||
dataBufferM.Reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_RTSP_CLIENT_CSEQ, 1L);
|
|
||||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_RTSP_SESSION_ID, NULL);
|
|
||||||
|
|
||||||
result = ValidateLatestResponse(&rc);
|
|
||||||
debug5("%s (%s) Response %ld in %" PRIu64 " ms [device %d]", __PRETTY_FUNCTION__, uriP, rc, processing.Elapsed(), tunerM.GetId());
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
void cSatipRtsp::ParseHeader(void)
|
|
||||||
{
|
|
||||||
debug1("%s [device %d]", __PRETTY_FUNCTION__, tunerM.GetId());
|
|
||||||
char *s, *p = headerBufferM.Data();
|
|
||||||
char *r = strtok_r(p, "\r\n", &s);
|
|
||||||
|
|
||||||
while (r) {
|
|
||||||
debug16("%s (%zu): %s", __PRETTY_FUNCTION__, headerBufferM.Size(), r);
|
|
||||||
r = skipspace(r);
|
|
||||||
if (strstr(r, "com.ses.streamID")) {
|
|
||||||
int streamid = -1;
|
|
||||||
if (sscanf(r, "com.ses.streamID:%11d", &streamid) == 1)
|
|
||||||
tunerM.SetStreamId(streamid);
|
|
||||||
}
|
|
||||||
else if (strstr(r, "Session:")) {
|
|
||||||
int timeout = -1;
|
|
||||||
char *session = NULL;
|
|
||||||
if (sscanf(r, "Session:%m[^;];timeout=%11d", &session, &timeout) == 2)
|
|
||||||
tunerM.SetSessionTimeout(skipspace(session), timeout * 1000);
|
|
||||||
else if (sscanf(r, "Session:%m[^;]", &session) == 1)
|
|
||||||
tunerM.SetSessionTimeout(skipspace(session), -1);
|
|
||||||
FREE_POINTER(session);
|
|
||||||
}
|
|
||||||
else if (strstr(r, "Transport:")) {
|
|
||||||
CURLcode res = CURLE_OK;
|
|
||||||
int rtp = -1, rtcp = -1, ttl = -1;
|
|
||||||
char *tmp = NULL, *destination = NULL, *source = NULL;
|
|
||||||
interleavedRtpIdM = 0;
|
|
||||||
interleavedRtcpIdM = 1;
|
|
||||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_INTERLEAVEFUNCTION, NULL);
|
|
||||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_INTERLEAVEDATA, NULL);
|
|
||||||
if (sscanf(r, "Transport:%m[^;];unicast;client_port=%11d-%11d", &tmp, &rtp, &rtcp) == 3) {
|
|
||||||
modeM = cSatipConfig::eTransportModeUnicast;
|
|
||||||
tunerM.SetupTransport(rtp, rtcp, NULL, NULL);
|
|
||||||
}
|
|
||||||
else if (sscanf(r, "Transport:%m[^;];multicast;destination=%m[^;];port=%11d-%11d;ttl=%11d;source=%m[^;]", &tmp, &destination, &rtp, &rtcp, &ttl, &source) == 6 ||
|
|
||||||
sscanf(r, "Transport:%m[^;];multicast;destination=%m[^;];port=%11d-%11d;ttl=%11d", &tmp, &destination, &rtp, &rtcp, &ttl) == 5) {
|
|
||||||
modeM = cSatipConfig::eTransportModeMulticast;
|
|
||||||
tunerM.SetupTransport(rtp, rtcp, destination, source);
|
|
||||||
}
|
|
||||||
else if (sscanf(r, "Transport:%m[^;];interleaved=%11d-%11d", &tmp, &rtp, &rtcp) == 3) {
|
|
||||||
interleavedRtpIdM = rtp;
|
|
||||||
interleavedRtcpIdM = rtcp;
|
|
||||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_INTERLEAVEFUNCTION, cSatipRtsp::InterleaveCallback);
|
|
||||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_INTERLEAVEDATA, this);
|
|
||||||
modeM = cSatipConfig::eTransportModeRtpOverTcp;
|
|
||||||
tunerM.SetupTransport(-1, -1, NULL, NULL);
|
|
||||||
}
|
|
||||||
FREE_POINTER(tmp);
|
|
||||||
FREE_POINTER(destination);
|
|
||||||
FREE_POINTER(source);
|
|
||||||
}
|
|
||||||
r = strtok_r(NULL, "\r\n", &s);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void cSatipRtsp::ParseData(void)
|
|
||||||
{
|
|
||||||
debug1("%s [device %d]", __PRETTY_FUNCTION__, tunerM.GetId());
|
|
||||||
char *s, *p = dataBufferM.Data();
|
|
||||||
char *r = strtok_r(p, "\r\n", &s);
|
|
||||||
|
|
||||||
while (r) {
|
|
||||||
debug16("%s (%zu): %s", __PRETTY_FUNCTION__, dataBufferM.Size(), r);
|
|
||||||
r = skipspace(r);
|
|
||||||
if (strstr(r, "No-More:")) {
|
|
||||||
char *tmp = NULL;
|
|
||||||
if (sscanf(r, "No-More:%m[^;]", &tmp) == 1) {
|
|
||||||
errorNoMoreM = skipspace(tmp);
|
|
||||||
debug3("%s No-More: %s [device %d]", __PRETTY_FUNCTION__, *errorNoMoreM, tunerM.GetId());
|
|
||||||
}
|
|
||||||
FREE_POINTER(tmp);
|
|
||||||
}
|
|
||||||
else if (strstr(r, "Out-of-Range:")) {
|
|
||||||
char *tmp = NULL;
|
|
||||||
if (sscanf(r, "Out-of-Range:%m[^;]", &tmp) == 1) {
|
|
||||||
errorOutOfRangeM = skipspace(tmp);
|
|
||||||
debug3("%s Out-of-Range: %s [device %d]", __PRETTY_FUNCTION__, *errorOutOfRangeM, tunerM.GetId());
|
|
||||||
}
|
|
||||||
FREE_POINTER(tmp);
|
|
||||||
}
|
|
||||||
else if (strstr(r, "Check-Syntax:")) {
|
|
||||||
char *tmp = NULL;
|
|
||||||
if (sscanf(r, "Check-Syntax:%m[^;]", &tmp) == 1) {
|
|
||||||
errorCheckSyntaxM = skipspace(tmp);
|
|
||||||
debug3("%s Check-Syntax: %s [device %d]", __PRETTY_FUNCTION__, *errorCheckSyntaxM, tunerM.GetId());
|
|
||||||
}
|
|
||||||
FREE_POINTER(tmp);
|
|
||||||
}
|
|
||||||
r = strtok_r(NULL, "\r\n", &s);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool cSatipRtsp::ValidateLatestResponse(long *rcP)
|
|
||||||
{
|
|
||||||
bool result = false;
|
|
||||||
|
|
||||||
if (handleM) {
|
|
||||||
char *url = NULL;
|
|
||||||
long rc = 0;
|
|
||||||
CURLcode res = CURLE_OK;
|
|
||||||
SATIP_CURL_EASY_GETINFO(handleM, CURLINFO_RESPONSE_CODE, &rc);
|
|
||||||
switch (rc) {
|
|
||||||
case 200:
|
|
||||||
result = true;
|
|
||||||
break;
|
|
||||||
case 400:
|
|
||||||
// SETUP PLAY TEARDOWN
|
|
||||||
// The message body of the response may contain the "Check-Syntax:" parameter followed
|
|
||||||
// by the malformed syntax
|
|
||||||
if (!isempty(*errorCheckSyntaxM)) {
|
|
||||||
SATIP_CURL_EASY_GETINFO(handleM, CURLINFO_EFFECTIVE_URL, &url);
|
|
||||||
error("Check syntax: %s (error code %ld: %s) [device %d]", *errorCheckSyntaxM, rc, url, tunerM.GetId());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 403:
|
|
||||||
// SETUP PLAY TEARDOWN
|
|
||||||
// The message body of the response may contain the "Out-of-Range:" parameter followed
|
|
||||||
// by a space-separated list of the attribute names that are not understood:
|
|
||||||
// "src" "fe" "freq" "pol" "msys" "mtype" "plts" "ro" "sr" "fec" "pids" "addpids" "delpids" "mcast"
|
|
||||||
if (!isempty(*errorOutOfRangeM)) {
|
|
||||||
SATIP_CURL_EASY_GETINFO(handleM, CURLINFO_EFFECTIVE_URL, &url);
|
|
||||||
error("Out of range: %s (error code %ld: %s) [device %d]", *errorOutOfRangeM, rc, url, tunerM.GetId());
|
|
||||||
// Reseting the connection wouldn't help anything due to invalid channel configuration, so let it be successful
|
|
||||||
result = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 503:
|
|
||||||
// SETUP PLAY
|
|
||||||
// The message body of the response may contain the "No-More:" parameter followed
|
|
||||||
// by a space-separated list of the missing ressources: “sessions” "frontends" "pids
|
|
||||||
if (!isempty(*errorNoMoreM)) {
|
|
||||||
SATIP_CURL_EASY_GETINFO(handleM, CURLINFO_EFFECTIVE_URL, &url);
|
|
||||||
error("No more: %s (error code %ld: %s) [device %d]", *errorNoMoreM, rc, url, tunerM.GetId());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
SATIP_CURL_EASY_GETINFO(handleM, CURLINFO_EFFECTIVE_URL, &url);
|
|
||||||
error("Detected invalid status code %ld: %s [device %d]", rc, url, tunerM.GetId());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (rcP)
|
|
||||||
*rcP = rc;
|
|
||||||
}
|
|
||||||
errorNoMoreM = "";
|
|
||||||
errorOutOfRangeM = "";
|
|
||||||
errorCheckSyntaxM = "";
|
|
||||||
debug1("%s result=%s [device %d]", __PRETTY_FUNCTION__, result ? "ok" : "failed", tunerM.GetId());
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
71
rtsp.h
71
rtsp.h
@ -1,71 +0,0 @@
|
|||||||
/*
|
|
||||||
* rtsp.h: SAT>IP plugin for the Video Disk Recorder
|
|
||||||
*
|
|
||||||
* See the README file for copyright information and how to reach the author.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef __SATIP_RTSP_H
|
|
||||||
#define __SATIP_RTSP_H
|
|
||||||
|
|
||||||
#include <curl/curl.h>
|
|
||||||
#include <curl/easy.h>
|
|
||||||
|
|
||||||
#ifndef CURLOPT_RTSPHEADER
|
|
||||||
#error "libcurl is missing required RTSP support"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "common.h"
|
|
||||||
#include "tunerif.h"
|
|
||||||
|
|
||||||
class cSatipRtsp {
|
|
||||||
private:
|
|
||||||
static size_t HeaderCallback(char *ptrP, size_t sizeP, size_t nmembP, void *dataP);
|
|
||||||
static size_t DataCallback(char *ptrP, size_t sizeP, size_t nmembP, void *dataP);
|
|
||||||
static size_t InterleaveCallback(char *ptrP, size_t sizeP, size_t nmembP, void *dataP);
|
|
||||||
static int DebugCallback(CURL *handleP, curl_infotype typeP, char *dataP, size_t sizeP, void *userPtrP);
|
|
||||||
|
|
||||||
enum {
|
|
||||||
eConnectTimeoutMs = 1500, // in milliseconds
|
|
||||||
};
|
|
||||||
|
|
||||||
cSatipTunerIf &tunerM;
|
|
||||||
cSatipMemoryBuffer headerBufferM;
|
|
||||||
cSatipMemoryBuffer dataBufferM;
|
|
||||||
CURL *handleM;
|
|
||||||
struct curl_slist *headerListM;
|
|
||||||
cString errorNoMoreM;
|
|
||||||
cString errorOutOfRangeM;
|
|
||||||
cString errorCheckSyntaxM;
|
|
||||||
int modeM;
|
|
||||||
unsigned int interleavedRtpIdM;
|
|
||||||
unsigned int interleavedRtcpIdM;
|
|
||||||
|
|
||||||
void Create(void);
|
|
||||||
void Destroy(void);
|
|
||||||
void ParseHeader(void);
|
|
||||||
void ParseData(void);
|
|
||||||
bool ValidateLatestResponse(long *rcP);
|
|
||||||
|
|
||||||
// to prevent copy constructor and assignment
|
|
||||||
cSatipRtsp(const cSatipRtsp&);
|
|
||||||
cSatipRtsp& operator=(const cSatipRtsp&);
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit cSatipRtsp(cSatipTunerIf &tunerP);
|
|
||||||
virtual ~cSatipRtsp();
|
|
||||||
|
|
||||||
cString GetActiveMode(void);
|
|
||||||
cString RtspUnescapeString(const char *strP);
|
|
||||||
void Reset(void);
|
|
||||||
bool SetInterface(const char *bindAddrP);
|
|
||||||
bool Receive(const char *uriP);
|
|
||||||
bool Options(const char *uriP);
|
|
||||||
bool Setup(const char *uriP, int rtpPortP, int rtcpPortP, bool useTcpP);
|
|
||||||
bool SetSession(const char *sessionP);
|
|
||||||
bool Describe(const char *uriP);
|
|
||||||
bool Play(const char *uriP);
|
|
||||||
bool Teardown(const char *uriP);
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // __SATIP_RTSP_H
|
|
364
satip.c
364
satip.c
@ -5,40 +5,33 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <ctype.h>
|
|
||||||
#include <getopt.h>
|
#include <getopt.h>
|
||||||
#include <vdr/plugin.h>
|
#include <vdr/plugin.h>
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "device.h"
|
#include "device.h"
|
||||||
#include "discover.h"
|
#include "discover.h"
|
||||||
#include "log.h"
|
|
||||||
#include "poller.h"
|
|
||||||
#include "setup.h"
|
#include "setup.h"
|
||||||
|
|
||||||
#if defined(LIBCURL_VERSION_NUM) && LIBCURL_VERSION_NUM < 0x072400
|
#if defined(LIBCURL_VERSION_NUM) && LIBCURL_VERSION_NUM < 0x072400
|
||||||
#warning "CURL version >= 7.36.0 is recommended"
|
#warning "CURL version >= 0.7.36 is recommended"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(APIVERSNUM) && APIVERSNUM < 20400
|
#if defined(APIVERSNUM) && APIVERSNUM < 20000
|
||||||
#error "VDR-2.4.0 API version or greater is required!"
|
#error "VDR-2.0.0 API version or greater is required!"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef GITVERSION
|
#ifndef GITVERSION
|
||||||
#define GITVERSION ""
|
#define GITVERSION ""
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
const char VERSION[] = "2.4.1" GITVERSION;
|
const char VERSION[] = "0.3.2" GITVERSION;
|
||||||
static const char DESCRIPTION[] = trNOOP("SAT>IP Devices");
|
static const char DESCRIPTION[] = trNOOP("SAT>IP Devices");
|
||||||
|
|
||||||
class cPluginSatip : public cPlugin {
|
class cPluginSatip : public cPlugin {
|
||||||
private:
|
private:
|
||||||
unsigned int deviceCountM;
|
unsigned int deviceCountM;
|
||||||
cSatipDiscoverServers *serversM;
|
cSatipDiscover *discoverM;
|
||||||
void ParseServer(const char *paramP);
|
|
||||||
void ParsePortRange(const char *paramP);
|
|
||||||
int ParseCicams(const char *valueP, int *cicamsP);
|
|
||||||
int ParseSources(const char *valueP, int *sourcesP);
|
|
||||||
int ParseFilters(const char *valueP, int *filtersP);
|
int ParseFilters(const char *valueP, int *filtersP);
|
||||||
public:
|
public:
|
||||||
cPluginSatip(void);
|
cPluginSatip(void);
|
||||||
@ -64,10 +57,10 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
cPluginSatip::cPluginSatip(void)
|
cPluginSatip::cPluginSatip(void)
|
||||||
: deviceCountM(2),
|
: deviceCountM(1),
|
||||||
serversM(NULL)
|
discoverM(NULL)
|
||||||
{
|
{
|
||||||
debug16("%s", __PRETTY_FUNCTION__);
|
//debug("cPluginSatip::%s()", __FUNCTION__);
|
||||||
// Initialize any member variables here.
|
// Initialize any member variables here.
|
||||||
// DON'T DO ANYTHING ELSE THAT MAY HAVE SIDE EFFECTS, REQUIRE GLOBAL
|
// DON'T DO ANYTHING ELSE THAT MAY HAVE SIDE EFFECTS, REQUIRE GLOBAL
|
||||||
// VDR OBJECTS TO EXIST OR PRODUCE ANY OUTPUT!
|
// VDR OBJECTS TO EXIST OR PRODUCE ANY OUTPUT!
|
||||||
@ -75,120 +68,53 @@ cPluginSatip::cPluginSatip(void)
|
|||||||
|
|
||||||
cPluginSatip::~cPluginSatip()
|
cPluginSatip::~cPluginSatip()
|
||||||
{
|
{
|
||||||
debug16("%s", __PRETTY_FUNCTION__);
|
//debug("cPluginSatip::%s()", __FUNCTION__);
|
||||||
// Clean up after yourself!
|
// Clean up after yourself!
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *cPluginSatip::CommandLineHelp(void)
|
const char *cPluginSatip::CommandLineHelp(void)
|
||||||
{
|
{
|
||||||
debug1("%s", __PRETTY_FUNCTION__);
|
debug("cPluginSatip::%s()", __FUNCTION__);
|
||||||
// Return a string that describes all known command line options.
|
// Return a string that describes all known command line options.
|
||||||
return " -d <num>, --devices=<number> set number of devices to be created\n"
|
return " -d <num>, --devices=<number> number of devices to be created\n";
|
||||||
" -t <mode>, --trace=<mode> set the tracing mode\n"
|
|
||||||
" -s <ipaddr>|<model>|<desc>, --server=[<srcaddress>@]<ipaddress>[:<port>]|<model>[:<filter>]|<description>[:<quirk>];...\n"
|
|
||||||
" define hard-coded SAT>IP server(s)\n\n"
|
|
||||||
" srcaddress (Optional) Source address can be used to define used\n"
|
|
||||||
" networking interface on a host, e.g. 127.0.0.1.\n"
|
|
||||||
" ipaddress IP address of SAT>IP server, e.g. 127.0.0.1.\n"
|
|
||||||
" port (Optional) IP port number of SAT>IP server, e.g 443.\n"
|
|
||||||
" model Model defines DVB modulation system (DVBS2,\n"
|
|
||||||
" DVBT2, DVBT, DVBC) and number of available\n"
|
|
||||||
" frontends separated by a hyphen, e.g. DVBT2-4.\n"
|
|
||||||
" filter (Optional) Filter can be used to limit satellite frontends\n"
|
|
||||||
" to certain satellite position, e.g. S19.2E.\n"
|
|
||||||
" description Friendly name of SAT>IP server. This is used\n"
|
|
||||||
" for autodetection of quirks.\n"
|
|
||||||
" quirk (Optional) Quirks are non-standard compliant features and\n"
|
|
||||||
" bug fixes of SAT>IP server defined by a\n"
|
|
||||||
" hexadecimal number. Multiple quirks can be\n"
|
|
||||||
" defined by combining values by addition:\n\n"
|
|
||||||
" 0x01: Fix session id bug\n"
|
|
||||||
" 0x02: Fix play parameter (addpids/delpids) bug\n"
|
|
||||||
" 0x04: Fix frontend locking bug\n"
|
|
||||||
" 0x08: Support for RTP over TCP\n"
|
|
||||||
" 0x10: Support the X_PMT protocol extension\n"
|
|
||||||
" 0x20: Support the CI TNR protocol extension\n"
|
|
||||||
" 0x40: Fix auto-detection of pilot tones bug\n"
|
|
||||||
" 0x80: Fix re-tuning bug by teardowning a session\n"
|
|
||||||
" -D, --detach set the detached mode on\n"
|
|
||||||
" -S, --single set the single model server mode on\n"
|
|
||||||
" -n, --noquirks disable autodetection of the server quirks\n"
|
|
||||||
" -p, --portrange=<start>-<end> set a range of ports used for the RT[C]P server\n"
|
|
||||||
" a minimum of 2 ports per device is required.\n"
|
|
||||||
" -r, --rcvbuf override the size of the RTP receive buffer in bytes\n";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool cPluginSatip::ProcessArgs(int argc, char *argv[])
|
bool cPluginSatip::ProcessArgs(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
debug1("%s", __PRETTY_FUNCTION__);
|
debug("cPluginSatip::%s()", __FUNCTION__);
|
||||||
// Implement command line argument processing here if applicable.
|
// Implement command line argument processing here if applicable.
|
||||||
static const struct option long_options[] = {
|
static const struct option long_options[] = {
|
||||||
{ "devices", required_argument, NULL, 'd' },
|
{ "devices", required_argument, NULL, 'd' },
|
||||||
{ "trace", required_argument, NULL, 't' },
|
{ NULL, no_argument, NULL, 0 }
|
||||||
{ "server", required_argument, NULL, 's' },
|
|
||||||
{ "portrange",required_argument, NULL, 'p' },
|
|
||||||
{ "rcvbuf", required_argument, NULL, 'r' },
|
|
||||||
{ "detach", no_argument, NULL, 'D' },
|
|
||||||
{ "single", no_argument, NULL, 'S' },
|
|
||||||
{ "noquirks", no_argument, NULL, 'n' },
|
|
||||||
{ NULL, no_argument, NULL, 0 }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
cString server;
|
|
||||||
cString portrange;
|
|
||||||
int c;
|
int c;
|
||||||
while ((c = getopt_long(argc, argv, "d:t:s:p:r:DSn", long_options, NULL)) != -1) {
|
while ((c = getopt_long(argc, argv, "d:", long_options, NULL)) != -1) {
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case 'd':
|
case 'd':
|
||||||
deviceCountM = strtol(optarg, NULL, 0);
|
deviceCountM = atoi(optarg);
|
||||||
break;
|
|
||||||
case 't':
|
|
||||||
SatipConfig.SetTraceMode(strtol(optarg, NULL, 0));
|
|
||||||
break;
|
|
||||||
case 's':
|
|
||||||
server = optarg;
|
|
||||||
break;
|
|
||||||
case 'D':
|
|
||||||
SatipConfig.SetDetachedMode(true);
|
|
||||||
break;
|
|
||||||
case 'S':
|
|
||||||
SatipConfig.SetUseSingleModelServers(true);
|
|
||||||
break;
|
|
||||||
case 'n':
|
|
||||||
SatipConfig.SetDisableServerQuirks(true);
|
|
||||||
break;
|
|
||||||
case 'p':
|
|
||||||
portrange = optarg;
|
|
||||||
break;
|
|
||||||
case 'r':
|
|
||||||
SatipConfig.SetRtpRcvBufSize(strtol(optarg, NULL, 0));
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!isempty(*portrange))
|
|
||||||
ParsePortRange(portrange);
|
|
||||||
// this must be done after all parameters are parsed
|
|
||||||
if (!isempty(*server))
|
|
||||||
ParseServer(*server);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool cPluginSatip::Initialize(void)
|
bool cPluginSatip::Initialize(void)
|
||||||
{
|
{
|
||||||
debug1("%s", __PRETTY_FUNCTION__);
|
debug("cPluginSatip::%s()", __FUNCTION__);
|
||||||
// Initialize any background activities the plugin shall perform.
|
// Initialize any background activities the plugin shall perform.
|
||||||
if (curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK)
|
if (curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK)
|
||||||
error("Unable to initialize CURL");
|
error("Unable to initialize CURL");
|
||||||
cSatipPoller::GetInstance()->Initialize();
|
SatipConfig.SetConfigDirectory(cPlugin::ResourceDirectory(PLUGIN_NAME_I18N));
|
||||||
cSatipDiscover::GetInstance()->Initialize(serversM);
|
cSatipDiscover::GetInstance()->Initialize();
|
||||||
return cSatipDevice::Initialize(deviceCountM);
|
return cSatipDevice::Initialize(deviceCountM);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool cPluginSatip::Start(void)
|
bool cPluginSatip::Start(void)
|
||||||
{
|
{
|
||||||
debug1("%s", __PRETTY_FUNCTION__);
|
debug("cPluginSatip::%s()", __FUNCTION__);
|
||||||
// Start any background activities the plugin shall perform.
|
// Start any background activities the plugin shall perform.
|
||||||
curl_version_info_data *data = curl_version_info(CURLVERSION_NOW);
|
curl_version_info_data *data = curl_version_info(CURLVERSION_NOW);
|
||||||
cString info = cString::sprintf("Using CURL %s", data->version);
|
cString info = cString::sprintf("Using CURL %s", data->version);
|
||||||
@ -203,202 +129,63 @@ bool cPluginSatip::Start(void)
|
|||||||
|
|
||||||
void cPluginSatip::Stop(void)
|
void cPluginSatip::Stop(void)
|
||||||
{
|
{
|
||||||
debug1("%s", __PRETTY_FUNCTION__);
|
debug("cPluginSatip::%s()", __FUNCTION__);
|
||||||
// Stop any background activities the plugin is performing.
|
// Stop any background activities the plugin is performing.
|
||||||
cSatipDevice::Shutdown();
|
cSatipDevice::Shutdown();
|
||||||
cSatipDiscover::GetInstance()->Destroy();
|
cSatipDiscover::GetInstance()->Destroy();
|
||||||
cSatipPoller::GetInstance()->Destroy();
|
|
||||||
curl_global_cleanup();
|
curl_global_cleanup();
|
||||||
}
|
}
|
||||||
|
|
||||||
void cPluginSatip::Housekeeping(void)
|
void cPluginSatip::Housekeeping(void)
|
||||||
{
|
{
|
||||||
debug16("%s", __PRETTY_FUNCTION__);
|
//debug("cPluginSatip::%s()", __FUNCTION__);
|
||||||
// Perform any cleanup or other regular tasks.
|
// Perform any cleanup or other regular tasks.
|
||||||
}
|
}
|
||||||
|
|
||||||
void cPluginSatip::MainThreadHook(void)
|
void cPluginSatip::MainThreadHook(void)
|
||||||
{
|
{
|
||||||
debug16("%s", __PRETTY_FUNCTION__);
|
//debug("cPluginSatip::%s()", __FUNCTION__);
|
||||||
// Perform actions in the context of the main program thread.
|
// Perform actions in the context of the main program thread.
|
||||||
// WARNING: Use with great care - see PLUGINS.html!
|
// WARNING: Use with great care - see PLUGINS.html!
|
||||||
}
|
}
|
||||||
|
|
||||||
cString cPluginSatip::Active(void)
|
cString cPluginSatip::Active(void)
|
||||||
{
|
{
|
||||||
debug16("%s", __PRETTY_FUNCTION__);
|
//debug("cPluginSatip::%s()", __FUNCTION__);
|
||||||
// Return a message string if shutdown should be postponed
|
// Return a message string if shutdown should be postponed
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
time_t cPluginSatip::WakeupTime(void)
|
time_t cPluginSatip::WakeupTime(void)
|
||||||
{
|
{
|
||||||
debug16("%s", __PRETTY_FUNCTION__);
|
//debug("cPluginSatip::%s()", __FUNCTION__);
|
||||||
// Return custom wakeup time for shutdown script
|
// Return custom wakeup time for shutdown script
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
cOsdObject *cPluginSatip::MainMenuAction(void)
|
cOsdObject *cPluginSatip::MainMenuAction(void)
|
||||||
{
|
{
|
||||||
debug16("%s", __PRETTY_FUNCTION__);
|
//debug("cPluginSatip::%s()", __FUNCTION__);
|
||||||
// Perform the action when selected from the main VDR menu.
|
// Perform the action when selected from the main VDR menu.
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
cMenuSetupPage *cPluginSatip::SetupMenu(void)
|
cMenuSetupPage *cPluginSatip::SetupMenu(void)
|
||||||
{
|
{
|
||||||
debug1("%s", __PRETTY_FUNCTION__);
|
debug("cPluginSatip::%s()", __FUNCTION__);
|
||||||
// Return a setup menu in case the plugin supports one.
|
// Return a setup menu in case the plugin supports one.
|
||||||
return new cSatipPluginSetup();
|
return new cSatipPluginSetup();
|
||||||
}
|
}
|
||||||
|
|
||||||
void cPluginSatip::ParseServer(const char *paramP)
|
|
||||||
{
|
|
||||||
debug1("%s (%s)", __PRETTY_FUNCTION__, paramP);
|
|
||||||
int n = 0;
|
|
||||||
char *s, *p = strdup(paramP);
|
|
||||||
char *r = strtok_r(p, ";", &s);
|
|
||||||
while (r) {
|
|
||||||
r = skipspace(r);
|
|
||||||
debug3("%s server[%d]=%s", __PRETTY_FUNCTION__, n, r);
|
|
||||||
cString sourceAddr, serverAddr, serverModel, serverFilters, serverDescription;
|
|
||||||
int serverQuirk = cSatipServer::eSatipQuirkNone;
|
|
||||||
int serverPort = SATIP_DEFAULT_RTSP_PORT;
|
|
||||||
int n2 = 0;
|
|
||||||
char *s2, *p2 = r;
|
|
||||||
char *r2 = strtok_r(p2, "|", &s2);
|
|
||||||
while (r2) {
|
|
||||||
debug3("%s param[%d]=%s", __PRETTY_FUNCTION__, n2, r2);
|
|
||||||
switch (n2++) {
|
|
||||||
case 0:
|
|
||||||
{
|
|
||||||
char *r3 = strchr(r2, '@');
|
|
||||||
if (r3) {
|
|
||||||
*r3 = 0;
|
|
||||||
sourceAddr = r2;
|
|
||||||
r2 = r3 + 1;
|
|
||||||
}
|
|
||||||
serverAddr = r2;
|
|
||||||
r3 = strchr(r2, ':');
|
|
||||||
if (r3) {
|
|
||||||
serverPort = strtol(r3 + 1, NULL, 0);
|
|
||||||
serverAddr = serverAddr.Truncate(r3 - r2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
{
|
|
||||||
serverModel = r2;
|
|
||||||
char *r3 = strchr(r2, ':');
|
|
||||||
if (r3) {
|
|
||||||
serverFilters = r3 + 1;
|
|
||||||
serverModel = serverModel.Truncate(r3 - r2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
{
|
|
||||||
serverDescription = r2;
|
|
||||||
char *r3 = strchr(r2, ':');
|
|
||||||
if (r3) {
|
|
||||||
serverQuirk = strtol(r3 + 1, NULL, 0);
|
|
||||||
serverDescription = serverDescription.Truncate(r3 - r2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
r2 = strtok_r(NULL, "|", &s2);
|
|
||||||
}
|
|
||||||
if (*serverAddr && *serverModel && *serverDescription) {
|
|
||||||
debug1("%s srcaddr=%s ipaddr=%s port=%d model=%s (%s) desc=%s (%d)", __PRETTY_FUNCTION__, *sourceAddr, *serverAddr, serverPort, *serverModel, *serverFilters, *serverDescription, serverQuirk);
|
|
||||||
if (!serversM)
|
|
||||||
serversM = new cSatipDiscoverServers();
|
|
||||||
serversM->Add(new cSatipDiscoverServer(*sourceAddr, *serverAddr, serverPort, *serverModel, *serverFilters, *serverDescription, serverQuirk));
|
|
||||||
}
|
|
||||||
++n;
|
|
||||||
r = strtok_r(NULL, ";", &s);
|
|
||||||
}
|
|
||||||
FREE_POINTER(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
void cPluginSatip::ParsePortRange(const char *paramP)
|
|
||||||
{
|
|
||||||
char *s, *p = skipspace(paramP);
|
|
||||||
char *r = strtok_r(p, "-", &s);
|
|
||||||
unsigned int rangeStart = 0;
|
|
||||||
unsigned int rangeStop = 0;
|
|
||||||
if (r) {
|
|
||||||
rangeStart = strtol(r, NULL, 0);
|
|
||||||
r = strtok_r(NULL, "-", &s);
|
|
||||||
}
|
|
||||||
if (r)
|
|
||||||
rangeStop = strtol(r, NULL, 0);
|
|
||||||
else {
|
|
||||||
error("Port range argument not valid '%s'", paramP);
|
|
||||||
rangeStart = 0;
|
|
||||||
rangeStop = 0;
|
|
||||||
}
|
|
||||||
if (rangeStart % 2) {
|
|
||||||
error("The given range start port must be even!");
|
|
||||||
rangeStart = 0;
|
|
||||||
rangeStop = 0;
|
|
||||||
}
|
|
||||||
else if (rangeStop - rangeStart + 1 < deviceCountM * 2) {
|
|
||||||
error("The given port range is to small: %d < %d!", rangeStop - rangeStart + 1, deviceCountM * 2);
|
|
||||||
rangeStart = 0;
|
|
||||||
rangeStop = 0;
|
|
||||||
}
|
|
||||||
SatipConfig.SetPortRangeStart(rangeStart);
|
|
||||||
SatipConfig.SetPortRangeStop(rangeStop);
|
|
||||||
}
|
|
||||||
|
|
||||||
int cPluginSatip::ParseCicams(const char *valueP, int *cicamsP)
|
|
||||||
{
|
|
||||||
debug1("%s (%s,)", __PRETTY_FUNCTION__, valueP);
|
|
||||||
int n = 0;
|
|
||||||
char *s, *p = strdup(valueP);
|
|
||||||
char *r = strtok_r(p, " ", &s);
|
|
||||||
while (r) {
|
|
||||||
r = skipspace(r);
|
|
||||||
debug3("%s cicams[%d]=%s", __PRETTY_FUNCTION__, n, r);
|
|
||||||
if (n < MAX_CICAM_COUNT) {
|
|
||||||
cicamsP[n++] = atoi(r);
|
|
||||||
}
|
|
||||||
r = strtok_r(NULL, " ", &s);
|
|
||||||
}
|
|
||||||
FREE_POINTER(p);
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
|
|
||||||
int cPluginSatip::ParseSources(const char *valueP, int *sourcesP)
|
|
||||||
{
|
|
||||||
debug1("%s (%s,)", __PRETTY_FUNCTION__, valueP);
|
|
||||||
int n = 0;
|
|
||||||
char *s, *p = strdup(valueP);
|
|
||||||
char *r = strtok_r(p, " ", &s);
|
|
||||||
while (r) {
|
|
||||||
r = skipspace(r);
|
|
||||||
debug3("%s sources[%d]=%s", __PRETTY_FUNCTION__, n, r);
|
|
||||||
if (n < MAX_DISABLED_SOURCES_COUNT) {
|
|
||||||
sourcesP[n++] = cSource::FromString(r);
|
|
||||||
}
|
|
||||||
r = strtok_r(NULL, " ", &s);
|
|
||||||
}
|
|
||||||
FREE_POINTER(p);
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
|
|
||||||
int cPluginSatip::ParseFilters(const char *valueP, int *filtersP)
|
int cPluginSatip::ParseFilters(const char *valueP, int *filtersP)
|
||||||
{
|
{
|
||||||
debug1("%s (%s,)", __PRETTY_FUNCTION__, valueP);
|
debug("cPluginSatip::%s(%s)", __FUNCTION__, valueP);
|
||||||
char buffer[256];
|
char buffer[256];
|
||||||
int n = 0;
|
int n = 0;
|
||||||
while (valueP && *valueP && (n < SECTION_FILTER_TABLE_SIZE)) {
|
while (valueP && *valueP && (n < SECTION_FILTER_TABLE_SIZE)) {
|
||||||
strn0cpy(buffer, valueP, sizeof(buffer));
|
strn0cpy(buffer, valueP, sizeof(buffer));
|
||||||
int i = atoi(buffer);
|
int i = atoi(buffer);
|
||||||
debug3("%s filters[%d]=%d", __PRETTY_FUNCTION__, n, i);
|
//debug("cPluginSatip::%s(): filters[%d]=%d", __FUNCTION__, n, i);
|
||||||
if (i >= 0)
|
if (i >= 0)
|
||||||
filtersP[n++] = i;
|
filtersP[n++] = i;
|
||||||
if ((valueP = strchr(valueP, ' ')) != NULL)
|
if ((valueP = strchr(valueP, ' ')) != NULL)
|
||||||
@ -409,42 +196,20 @@ int cPluginSatip::ParseFilters(const char *valueP, int *filtersP)
|
|||||||
|
|
||||||
bool cPluginSatip::SetupParse(const char *nameP, const char *valueP)
|
bool cPluginSatip::SetupParse(const char *nameP, const char *valueP)
|
||||||
{
|
{
|
||||||
debug1("%s", __PRETTY_FUNCTION__);
|
debug("cPluginSatip::%s()", __FUNCTION__);
|
||||||
// Parse your own setup parameters and store their values.
|
// Parse your own setup parameters and store their values.
|
||||||
if (!strcasecmp(nameP, "OperatingMode"))
|
if (!strcasecmp(nameP, "OperatingMode"))
|
||||||
SatipConfig.SetOperatingMode(atoi(valueP));
|
SatipConfig.SetOperatingMode(atoi(valueP));
|
||||||
else if (!strcasecmp(nameP, "EnableCIExtension"))
|
|
||||||
SatipConfig.SetCIExtension(atoi(valueP));
|
|
||||||
else if (!strcasecmp(nameP, "EnableFrontendReuse"))
|
|
||||||
SatipConfig.SetFrontendReuse(atoi(valueP));
|
|
||||||
else if (!strcasecmp(nameP, "CICAM")) {
|
|
||||||
int Cicams[MAX_CICAM_COUNT];
|
|
||||||
for (unsigned int i = 0; i < ELEMENTS(Cicams); ++i)
|
|
||||||
Cicams[i] = 0;
|
|
||||||
unsigned int CicamsCount = ParseCicams(valueP, Cicams);
|
|
||||||
for (unsigned int i = 0; i < CicamsCount; ++i)
|
|
||||||
SatipConfig.SetCICAM(i, Cicams[i]);
|
|
||||||
}
|
|
||||||
else if (!strcasecmp(nameP, "EnableEITScan"))
|
else if (!strcasecmp(nameP, "EnableEITScan"))
|
||||||
SatipConfig.SetEITScan(atoi(valueP));
|
SatipConfig.SetEITScan(atoi(valueP));
|
||||||
else if (!strcasecmp(nameP, "DisabledSources")) {
|
|
||||||
int DisabledSources[MAX_DISABLED_SOURCES_COUNT];
|
|
||||||
for (unsigned int i = 0; i < ELEMENTS(DisabledSources); ++i)
|
|
||||||
DisabledSources[i] = cSource::stNone;
|
|
||||||
unsigned int DisabledSourcesCount = ParseSources(valueP, DisabledSources);
|
|
||||||
for (unsigned int i = 0; i < DisabledSourcesCount; ++i)
|
|
||||||
SatipConfig.SetDisabledSources(i, DisabledSources[i]);
|
|
||||||
}
|
|
||||||
else if (!strcasecmp(nameP, "DisabledFilters")) {
|
else if (!strcasecmp(nameP, "DisabledFilters")) {
|
||||||
int DisabledFilters[SECTION_FILTER_TABLE_SIZE];
|
int DisabledFilters[SECTION_FILTER_TABLE_SIZE];
|
||||||
for (unsigned int i = 0; i < ELEMENTS(DisabledFilters); ++i)
|
for (unsigned int i = 0; i < ARRAY_SIZE(DisabledFilters); ++i)
|
||||||
DisabledFilters[i] = -1;
|
DisabledFilters[i] = -1;
|
||||||
unsigned int DisabledFiltersCount = ParseFilters(valueP, DisabledFilters);
|
unsigned int DisabledFiltersCount = ParseFilters(valueP, DisabledFilters);
|
||||||
for (unsigned int i = 0; i < DisabledFiltersCount; ++i)
|
for (unsigned int i = 0; i < DisabledFiltersCount; ++i)
|
||||||
SatipConfig.SetDisabledFilters(i, DisabledFilters[i]);
|
SatipConfig.SetDisabledFilters(i, DisabledFilters[i]);
|
||||||
}
|
}
|
||||||
else if (!strcasecmp(nameP, "TransportMode"))
|
|
||||||
SatipConfig.SetTransportMode(atoi(valueP));
|
|
||||||
else
|
else
|
||||||
return false;
|
return false;
|
||||||
return true;
|
return true;
|
||||||
@ -452,13 +217,13 @@ bool cPluginSatip::SetupParse(const char *nameP, const char *valueP)
|
|||||||
|
|
||||||
bool cPluginSatip::Service(const char *idP, void *dataP)
|
bool cPluginSatip::Service(const char *idP, void *dataP)
|
||||||
{
|
{
|
||||||
debug1("%s", __PRETTY_FUNCTION__);
|
debug("cPluginSatip::%s()", __FUNCTION__);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char **cPluginSatip::SVDRPHelpPages(void)
|
const char **cPluginSatip::SVDRPHelpPages(void)
|
||||||
{
|
{
|
||||||
debug1("%s", __PRETTY_FUNCTION__);
|
debug("cPluginSatip::%s()", __FUNCTION__);
|
||||||
static const char *HelpPages[] = {
|
static const char *HelpPages[] = {
|
||||||
"INFO [ <page> ] [ <card index> ]\n"
|
"INFO [ <page> ] [ <card index> ]\n"
|
||||||
" Prints SAT>IP device information and statistics.\n"
|
" Prints SAT>IP device information and statistics.\n"
|
||||||
@ -468,20 +233,10 @@ const char **cPluginSatip::SVDRPHelpPages(void)
|
|||||||
" Toggles between bit or byte information mode.\n",
|
" Toggles between bit or byte information mode.\n",
|
||||||
"LIST\n"
|
"LIST\n"
|
||||||
" Lists active SAT>IP servers.\n",
|
" Lists active SAT>IP servers.\n",
|
||||||
"SCAN\n"
|
|
||||||
" Scans active SAT>IP servers.\n",
|
|
||||||
"STAT\n"
|
|
||||||
" Lists status information of SAT>IP devices.\n",
|
|
||||||
"CONT\n"
|
"CONT\n"
|
||||||
" Shows SAT>IP device count.\n",
|
" Shows SAT>IP device count.\n",
|
||||||
"OPER [ off | low | normal | high ]\n"
|
"OPER\n"
|
||||||
" Gets and(or sets operating mode of SAT>IP devices.\n",
|
" Toggles operating mode of SAT>IP devices.\n",
|
||||||
"ATTA\n"
|
|
||||||
" Attach active SAT>IP servers.\n",
|
|
||||||
"DETA\n"
|
|
||||||
" Detachs active SAT>IP servers.\n",
|
|
||||||
"TRAC [ <mode> ]\n"
|
|
||||||
" Gets and/or sets used tracing mode.\n",
|
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
return HelpPages;
|
return HelpPages;
|
||||||
@ -489,7 +244,7 @@ const char **cPluginSatip::SVDRPHelpPages(void)
|
|||||||
|
|
||||||
cString cPluginSatip::SVDRPCommand(const char *commandP, const char *optionP, int &replyCodeP)
|
cString cPluginSatip::SVDRPCommand(const char *commandP, const char *optionP, int &replyCodeP)
|
||||||
{
|
{
|
||||||
debug1("%s (%s, %s,)", __PRETTY_FUNCTION__, commandP, optionP);
|
debug("cPluginSatip::%s(%s, %s)", __FUNCTION__, commandP, optionP);
|
||||||
if (strcasecmp(commandP, "INFO") == 0) {
|
if (strcasecmp(commandP, "INFO") == 0) {
|
||||||
int index = cDevice::ActualDevice()->CardIndex();
|
int index = cDevice::ActualDevice()->CardIndex();
|
||||||
int page = SATIP_DEVICE_INFO_ALL;
|
int page = SATIP_DEVICE_INFO_ALL;
|
||||||
@ -516,13 +271,13 @@ cString cPluginSatip::SVDRPCommand(const char *commandP, const char *optionP, in
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
replyCodeP = 550; // Requested action not taken
|
replyCodeP = 550; // Requested action not taken
|
||||||
return cString("SATIP information not available!");
|
return cString("SAT>IP information not available!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (strcasecmp(commandP, "MODE") == 0) {
|
else if (strcasecmp(commandP, "MODE") == 0) {
|
||||||
unsigned int mode = !SatipConfig.GetUseBytes();
|
unsigned int mode = !SatipConfig.GetUseBytes();
|
||||||
SatipConfig.SetUseBytes(mode);
|
SatipConfig.SetUseBytes(mode);
|
||||||
return cString::sprintf("SATIP information mode: %s\n", mode ? "bytes" : "bits");
|
return cString::sprintf("SAT>IP information mode: %s\n", mode ? "bytes" : "bits");
|
||||||
}
|
}
|
||||||
else if (strcasecmp(commandP, "LIST") == 0) {
|
else if (strcasecmp(commandP, "LIST") == 0) {
|
||||||
cString list = cSatipDiscover::GetInstance()->GetServerList();
|
cString list = cSatipDiscover::GetInstance()->GetServerList();
|
||||||
@ -531,34 +286,16 @@ cString cPluginSatip::SVDRPCommand(const char *commandP, const char *optionP, in
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
replyCodeP = 550; // Requested action not taken
|
replyCodeP = 550; // Requested action not taken
|
||||||
return cString("No SATIP servers detected!");
|
return cString("No SAT>IP devices detected!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (strcasecmp(commandP, "SCAN") == 0) {
|
|
||||||
cSatipDiscover::GetInstance()->TriggerScan();
|
|
||||||
return cString("SATIP server scan requested");
|
|
||||||
}
|
|
||||||
else if (strcasecmp(commandP, "STAT") == 0) {
|
|
||||||
return cSatipDevice::GetSatipStatus();
|
|
||||||
}
|
|
||||||
else if (strcasecmp(commandP, "CONT") == 0) {
|
else if (strcasecmp(commandP, "CONT") == 0) {
|
||||||
return cString::sprintf("SATIP device count: %u", cSatipDevice::Count());
|
return cString::sprintf("SAT>IP device count: %u", cSatipDevice::Count());
|
||||||
}
|
}
|
||||||
else if (strcasecmp(commandP, "OPER") == 0) {
|
else if (strcasecmp(commandP, "OPER") == 0) {
|
||||||
cString mode;
|
cString mode;
|
||||||
unsigned int oper = SatipConfig.GetOperatingMode();
|
SatipConfig.ToggleOperatingMode();
|
||||||
if (optionP && *optionP) {
|
switch (SatipConfig.GetOperatingMode()) {
|
||||||
if (strcasecmp(optionP, "off") == 0)
|
|
||||||
oper = cSatipConfig::eOperatingModeOff;
|
|
||||||
else if (strcasecmp(optionP, "low") == 0)
|
|
||||||
oper = cSatipConfig::eOperatingModeLow;
|
|
||||||
else if (strcasecmp(optionP, "normal") == 0)
|
|
||||||
oper = cSatipConfig::eOperatingModeNormal;
|
|
||||||
else if (strcasecmp(optionP, "high") == 0)
|
|
||||||
oper = cSatipConfig::eOperatingModeHigh;
|
|
||||||
SatipConfig.SetOperatingMode(oper);
|
|
||||||
}
|
|
||||||
switch (oper) {
|
|
||||||
case cSatipConfig::eOperatingModeOff:
|
case cSatipConfig::eOperatingModeOff:
|
||||||
mode = "off";
|
mode = "off";
|
||||||
break;
|
break;
|
||||||
@ -575,22 +312,7 @@ cString cPluginSatip::SVDRPCommand(const char *commandP, const char *optionP, in
|
|||||||
mode = "unknown";
|
mode = "unknown";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return cString::sprintf("SATIP operating mode: %s\n", *mode);
|
return cString::sprintf("SAT>IP operating mode: %s\n", *mode);
|
||||||
}
|
|
||||||
else if (strcasecmp(commandP, "ATTA") == 0) {
|
|
||||||
SatipConfig.SetDetachedMode(false);
|
|
||||||
info("SATIP servers attached");
|
|
||||||
return cString("SATIP servers attached");
|
|
||||||
}
|
|
||||||
else if (strcasecmp(commandP, "DETA") == 0) {
|
|
||||||
SatipConfig.SetDetachedMode(true);
|
|
||||||
info("SATIP servers detached");
|
|
||||||
return cString("SATIP servers detached");
|
|
||||||
}
|
|
||||||
else if (strcasecmp(commandP, "TRAC") == 0) {
|
|
||||||
if (optionP && *optionP)
|
|
||||||
SatipConfig.SetTraceMode(strtol(optionP, NULL, 0));
|
|
||||||
return cString::sprintf("SATIP tracing mode: 0x%04X\n", SatipConfig.GetTraceMode());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
230
sectionfilter.c
230
sectionfilter.c
@ -6,7 +6,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "log.h"
|
|
||||||
#include "sectionfilter.h"
|
#include "sectionfilter.h"
|
||||||
|
|
||||||
cSatipSectionFilter::cSatipSectionFilter(int deviceIndexP, uint16_t pidP, uint8_t tidP, uint8_t maskP)
|
cSatipSectionFilter::cSatipSectionFilter(int deviceIndexP, uint16_t pidP, uint8_t tidP, uint8_t maskP)
|
||||||
@ -18,14 +17,35 @@ cSatipSectionFilter::cSatipSectionFilter(int deviceIndexP, uint16_t pidP, uint8_
|
|||||||
secLenM(0),
|
secLenM(0),
|
||||||
tsFeedpM(0),
|
tsFeedpM(0),
|
||||||
pidM(pidP),
|
pidM(pidP),
|
||||||
tidM(tidP),
|
|
||||||
maskM(maskP),
|
|
||||||
ringBufferM(new cRingBufferFrame(eDmxMaxSectionCount * eDmxMaxSectionSize)),
|
ringBufferM(new cRingBufferFrame(eDmxMaxSectionCount * eDmxMaxSectionSize)),
|
||||||
deviceIndexM(deviceIndexP)
|
deviceIndexM(deviceIndexP)
|
||||||
{
|
{
|
||||||
debug16("%s (%d, %d, %d, %d) [device %d]", __PRETTY_FUNCTION__, deviceIndexM, pidM, tidP, maskP, deviceIndexM);
|
//debug("cSatipSectionFilter::%s(%d, %d)", __FUNCTION__, deviceIndexM, pidM);
|
||||||
|
int i;
|
||||||
|
|
||||||
memset(secBufBaseM, 0, sizeof(secBufBaseM));
|
memset(secBufBaseM, 0, sizeof(secBufBaseM));
|
||||||
|
memset(filterValueM, 0, sizeof(filterValueM));
|
||||||
|
memset(filterMaskM, 0, sizeof(filterMaskM));
|
||||||
|
memset(filterModeM, 0, sizeof(filterModeM));
|
||||||
|
memset(maskAndModeM, 0, sizeof(maskAndModeM));
|
||||||
|
memset(maskAndNotModeM, 0, sizeof(maskAndNotModeM));
|
||||||
|
|
||||||
|
filterValueM[0] = tidP;
|
||||||
|
filterMaskM[0] = maskP;
|
||||||
|
|
||||||
|
// Invert the filter
|
||||||
|
for (i = 0; i < eDmxMaxFilterSize; ++i)
|
||||||
|
filterValueM[i] ^= 0xFF;
|
||||||
|
|
||||||
|
uint8_t mask, mode, doneq = 0;
|
||||||
|
for (i = 0; i < eDmxMaxFilterSize; ++i) {
|
||||||
|
mode = filterModeM[i];
|
||||||
|
mask = filterMaskM[i];
|
||||||
|
maskAndModeM[i] = (uint8_t)(mask & mode);
|
||||||
|
maskAndNotModeM[i] = (uint8_t)(mask & ~mode);
|
||||||
|
doneq |= maskAndNotModeM[i];
|
||||||
|
}
|
||||||
|
doneqM = doneq ? 1 : 0;
|
||||||
|
|
||||||
// Create sockets
|
// Create sockets
|
||||||
socketM[0] = socketM[1] = -1;
|
socketM[0] = socketM[1] = -1;
|
||||||
@ -41,7 +61,7 @@ cSatipSectionFilter::cSatipSectionFilter(int deviceIndexP, uint16_t pidP, uint8_
|
|||||||
|
|
||||||
cSatipSectionFilter::~cSatipSectionFilter()
|
cSatipSectionFilter::~cSatipSectionFilter()
|
||||||
{
|
{
|
||||||
debug16("%s pid=%d [device %d]", __PRETTY_FUNCTION__, pidM, deviceIndexM);
|
//debug("cSatipSectionFilter::%s(%d, %d)", __FUNCTION__, deviceIndexM, pidM);
|
||||||
int tmp = socketM[1];
|
int tmp = socketM[1];
|
||||||
socketM[1] = -1;
|
socketM[1] = -1;
|
||||||
if (tmp >= 0)
|
if (tmp >= 0)
|
||||||
@ -68,13 +88,21 @@ void cSatipSectionFilter::New(void)
|
|||||||
int cSatipSectionFilter::Filter(void)
|
int cSatipSectionFilter::Filter(void)
|
||||||
{
|
{
|
||||||
if (secBufM) {
|
if (secBufM) {
|
||||||
if ((tidM & maskM) == (secBufM[0] & maskM)) {
|
int i;
|
||||||
if (ringBufferM && (secLenM > 0)) {
|
uint8_t neq = 0;
|
||||||
cFrame* section = new cFrame(secBufM, secLenM);
|
|
||||||
if (!ringBufferM->Put(section))
|
for (i = 0; i < eDmxMaxFilterSize; ++i) {
|
||||||
DELETE_POINTER(section);
|
uint8_t calcxor = (uint8_t)(filterValueM[i] ^ secBufM[i]);
|
||||||
}
|
if (maskAndModeM[i] & calcxor)
|
||||||
}
|
return 0;
|
||||||
|
neq |= (maskAndNotModeM[i] & calcxor);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (doneqM && !neq)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (ringBufferM && (secLenM > 0))
|
||||||
|
ringBufferM->Put(new cFrame(secBufM, secLenM));
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -89,7 +117,7 @@ inline int cSatipSectionFilter::Feed(void)
|
|||||||
|
|
||||||
int cSatipSectionFilter::CopyDump(const uint8_t *bufP, uint8_t lenP)
|
int cSatipSectionFilter::CopyDump(const uint8_t *bufP, uint8_t lenP)
|
||||||
{
|
{
|
||||||
uint16_t limit, n;
|
uint16_t limit, seclen, n;
|
||||||
|
|
||||||
if (tsFeedpM >= eDmxMaxSectionFeedSize)
|
if (tsFeedpM >= eDmxMaxSectionFeedSize)
|
||||||
return 0;
|
return 0;
|
||||||
@ -97,7 +125,7 @@ int cSatipSectionFilter::CopyDump(const uint8_t *bufP, uint8_t lenP)
|
|||||||
if (tsFeedpM + lenP > eDmxMaxSectionFeedSize)
|
if (tsFeedpM + lenP > eDmxMaxSectionFeedSize)
|
||||||
lenP = (uint8_t)(eDmxMaxSectionFeedSize - tsFeedpM);
|
lenP = (uint8_t)(eDmxMaxSectionFeedSize - tsFeedpM);
|
||||||
|
|
||||||
if (lenP == 0)
|
if (lenP <= 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
memcpy(secBufBaseM + tsFeedpM, bufP, lenP);
|
memcpy(secBufBaseM + tsFeedpM, bufP, lenP);
|
||||||
@ -111,8 +139,8 @@ int cSatipSectionFilter::CopyDump(const uint8_t *bufP, uint8_t lenP)
|
|||||||
secBufM = secBufBaseM + secBufpM;
|
secBufM = secBufBaseM + secBufpM;
|
||||||
|
|
||||||
for (n = 0; secBufpM + 2 < limit; ++n) {
|
for (n = 0; secBufpM + 2 < limit; ++n) {
|
||||||
uint16_t seclen = GetLength(secBufM);
|
seclen = GetLength(secBufM);
|
||||||
if ((seclen > eDmxMaxSectionSize) || ((seclen + secBufpM) > limit))
|
if ((seclen <= 0) || (seclen > eDmxMaxSectionSize) || ((seclen + secBufpM) > limit))
|
||||||
return 0;
|
return 0;
|
||||||
secLenM = seclen;
|
secLenM = seclen;
|
||||||
if (pusiSeenM)
|
if (pusiSeenM)
|
||||||
@ -180,36 +208,35 @@ void cSatipSectionFilter::Process(const uint8_t* dataP)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void cSatipSectionFilter::Send(void)
|
bool cSatipSectionFilter::Send(void)
|
||||||
{
|
{
|
||||||
|
bool result = false;
|
||||||
cFrame *section = ringBufferM->Get();
|
cFrame *section = ringBufferM->Get();
|
||||||
if (section) {
|
if (section) {
|
||||||
uchar *data = section->Data();
|
uchar *data = section->Data();
|
||||||
int count = section->Count();
|
int count = section->Count();
|
||||||
if (data && (count > 0) && (socketM[1] >= 0) && (socketM[0] >= 0)) {
|
if (data && (count > 0) && (socketM[1] >= 0) && (socketM[0] >= 0)) {
|
||||||
if (send(socketM[1], data, count, MSG_EOR) > 0) {
|
ssize_t len = send(socketM[1], data, count, MSG_EOR);
|
||||||
|
ERROR_IF(len < 0 && errno != EAGAIN, "send()");
|
||||||
|
if (len > 0) {
|
||||||
|
ringBufferM->Drop(section);
|
||||||
|
result = !!ringBufferM->Available();
|
||||||
// Update statistics
|
// Update statistics
|
||||||
AddSectionStatistic(count, 1);
|
AddSectionStatistic(len, 1);
|
||||||
}
|
}
|
||||||
else if (errno != EAGAIN)
|
|
||||||
error("failed to send section data (%i bytes) [device=%d]", count, deviceIndexM);
|
|
||||||
}
|
}
|
||||||
ringBufferM->Drop(section);
|
|
||||||
}
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
int cSatipSectionFilter::Available(void) const
|
|
||||||
{
|
|
||||||
return ringBufferM->Available();
|
|
||||||
}
|
|
||||||
|
|
||||||
cSatipSectionFilterHandler::cSatipSectionFilterHandler(int deviceIndexP, unsigned int bufferLenP)
|
cSatipSectionFilterHandler::cSatipSectionFilterHandler(int deviceIndexP, unsigned int bufferLenP)
|
||||||
: cThread(cString::sprintf("SATIP#%d section handler", deviceIndexP)),
|
: cThread("SAT>IP section handler"),
|
||||||
ringBufferM(new cRingBufferLinear(bufferLenP, TS_SIZE, false, *cString::sprintf("SATIP %d section handler", deviceIndexP))),
|
ringBufferM(new cRingBufferLinear(bufferLenP, TS_SIZE, false, *cString::sprintf("SAT>IP SECTION HANDLER %d", deviceIndexP))),
|
||||||
mutexM(),
|
mutexM(),
|
||||||
deviceIndexM(deviceIndexP)
|
deviceIndexM(deviceIndexP)
|
||||||
{
|
{
|
||||||
debug1("%s (%d, %d) [device %d]", __PRETTY_FUNCTION__, deviceIndexM, bufferLenP, deviceIndexM);
|
debug("cSatipSectionFilterHandler::%s(%d)", __FUNCTION__, deviceIndexM);
|
||||||
|
|
||||||
// Initialize filter pointers
|
// Initialize filter pointers
|
||||||
memset(filtersM, 0, sizeof(filtersM));
|
memset(filtersM, 0, sizeof(filtersM));
|
||||||
@ -220,14 +247,14 @@ cSatipSectionFilterHandler::cSatipSectionFilterHandler(int deviceIndexP, unsigne
|
|||||||
ringBufferM->SetIoThrottle();
|
ringBufferM->SetIoThrottle();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
error("Failed to allocate buffer for section filter handler [device=%d]", deviceIndexM);
|
error("Failed to allocate buffer for section filter handler (device=%d): ", deviceIndexM);
|
||||||
|
|
||||||
Start();
|
Start();
|
||||||
}
|
}
|
||||||
|
|
||||||
cSatipSectionFilterHandler::~cSatipSectionFilterHandler()
|
cSatipSectionFilterHandler::~cSatipSectionFilterHandler()
|
||||||
{
|
{
|
||||||
debug1("%s [device %d]", __PRETTY_FUNCTION__, deviceIndexM);
|
debug("cSatipSectionFilterHandler::%s(%d)", __FUNCTION__, deviceIndexM);
|
||||||
// Stop thread
|
// Stop thread
|
||||||
if (Running())
|
if (Running())
|
||||||
Cancel(3);
|
Cancel(3);
|
||||||
@ -239,80 +266,61 @@ cSatipSectionFilterHandler::~cSatipSectionFilterHandler()
|
|||||||
Delete(i);
|
Delete(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
void cSatipSectionFilterHandler::SendAll(void)
|
|
||||||
{
|
|
||||||
cMutexLock MutexLock(&mutexM);
|
|
||||||
bool pendingData;
|
|
||||||
do {
|
|
||||||
pendingData = false;
|
|
||||||
|
|
||||||
// zero polling structures
|
|
||||||
memset(pollFdsM, 0, sizeof(pollFdsM));
|
|
||||||
|
|
||||||
// assemble all handlers to poll (use -1 to ignore handlers)
|
|
||||||
for (unsigned int i = 0; i < eMaxSecFilterCount; ++i) {
|
|
||||||
if (filtersM[i] && filtersM[i]->Available() != 0) {
|
|
||||||
pollFdsM[i].fd = filtersM[i]->GetFd();
|
|
||||||
pollFdsM[i].events = POLLOUT;
|
|
||||||
pendingData = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
pollFdsM[i].fd = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// exit if there isn't any pending data or we time out
|
|
||||||
if (!pendingData || poll(pollFdsM, eMaxSecFilterCount, eSecFilterSendTimeoutMs) <= 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// send data (if available)
|
|
||||||
for (unsigned int i = 0; i < eMaxSecFilterCount && pendingData; ++i) {
|
|
||||||
if (pollFdsM[i].revents & POLLOUT)
|
|
||||||
filtersM[i]->Send();
|
|
||||||
}
|
|
||||||
} while (pendingData);
|
|
||||||
}
|
|
||||||
|
|
||||||
void cSatipSectionFilterHandler::Action(void)
|
void cSatipSectionFilterHandler::Action(void)
|
||||||
{
|
{
|
||||||
debug1("%s Entering [device %d]", __PRETTY_FUNCTION__, deviceIndexM);
|
debug("cSatipSectionFilterHandler::%s(%d): entering", __FUNCTION__, deviceIndexM);
|
||||||
|
bool processed = false;
|
||||||
// Do the thread loop
|
// Do the thread loop
|
||||||
while (Running()) {
|
while (Running()) {
|
||||||
uchar *p = NULL;
|
|
||||||
int len = 0;
|
|
||||||
// Process all pending TS packets
|
|
||||||
while ((p = ringBufferM->Get(len)) != NULL) {
|
|
||||||
if (p && (len >= TS_SIZE)) {
|
|
||||||
if (*p != TS_SYNC_BYTE) {
|
|
||||||
for (int i = 1; i < len; ++i) {
|
|
||||||
if (p[i] == TS_SYNC_BYTE) {
|
|
||||||
len = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ringBufferM->Del(len);
|
|
||||||
debug1("%s Skipped %d bytes to sync on TS packet [device %d]", __PRETTY_FUNCTION__, len, deviceIndexM);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
// Process TS packet through all filters
|
|
||||||
mutexM.Lock();
|
|
||||||
for (unsigned int i = 0; i < eMaxSecFilterCount; ++i) {
|
|
||||||
if (filtersM[i])
|
|
||||||
filtersM[i]->Process(p);
|
|
||||||
}
|
|
||||||
mutexM.Unlock();
|
|
||||||
ringBufferM->Del(TS_SIZE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Send demuxed section packets through all filters
|
// Send demuxed section packets through all filters
|
||||||
SendAll();
|
bool retry = false;
|
||||||
|
mutexM.Lock();
|
||||||
|
for (unsigned int i = 0; i < eMaxSecFilterCount; ++i) {
|
||||||
|
if (filtersM[i] && filtersM[i]->Send())
|
||||||
|
retry = true;
|
||||||
|
}
|
||||||
|
mutexM.Unlock();
|
||||||
|
if (retry)
|
||||||
|
continue;
|
||||||
|
// Read one TS packet
|
||||||
|
if (ringBufferM) {
|
||||||
|
int len = 0;
|
||||||
|
if (processed) {
|
||||||
|
ringBufferM->Del(TS_SIZE);
|
||||||
|
processed = false;
|
||||||
|
}
|
||||||
|
uchar *p = ringBufferM->Get(len);
|
||||||
|
if (p && (len >= TS_SIZE)) {
|
||||||
|
if (*p != TS_SYNC_BYTE) {
|
||||||
|
for (int i = 1; i < len; ++i) {
|
||||||
|
if (p[i] == TS_SYNC_BYTE) {
|
||||||
|
len = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ringBufferM->Del(len);
|
||||||
|
debug("cSatipSectionFilterHandler::%s(%d): Skipped %d bytes to sync on TS packet", __FUNCTION__, deviceIndexM, len);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// Process TS packet through all filters
|
||||||
|
mutexM.Lock();
|
||||||
|
for (unsigned int i = 0; i < eMaxSecFilterCount; ++i) {
|
||||||
|
if (filtersM[i])
|
||||||
|
filtersM[i]->Process(p);
|
||||||
|
}
|
||||||
|
mutexM.Unlock();
|
||||||
|
processed = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cCondWait::SleepMs(10); // to avoid busy loop and reduce cpu load
|
||||||
}
|
}
|
||||||
debug1("%s Exiting [device %d]", __PRETTY_FUNCTION__, deviceIndexM);
|
debug("cSatipSectionFilterHandler::%s(%d): exiting", __FUNCTION__, deviceIndexM);
|
||||||
}
|
}
|
||||||
|
|
||||||
cString cSatipSectionFilterHandler::GetInformation(void)
|
cString cSatipSectionFilterHandler::GetInformation(void)
|
||||||
{
|
{
|
||||||
debug16("%s [device %d]", __PRETTY_FUNCTION__, deviceIndexM);
|
//debug("cSatipSectionFilterHandler::%s(%d)", __FUNCTION__, deviceIndexM);
|
||||||
// loop through active section filters
|
// loop through active section filters
|
||||||
cMutexLock MutexLock(&mutexM);
|
cMutexLock MutexLock(&mutexM);
|
||||||
cString s = "";
|
cString s = "";
|
||||||
@ -329,24 +337,11 @@ cString cSatipSectionFilterHandler::GetInformation(void)
|
|||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool cSatipSectionFilterHandler::Exists(u_short pidP)
|
|
||||||
{
|
|
||||||
debug16("%s (%d) [device %d]", __PRETTY_FUNCTION__, pidP, deviceIndexM);
|
|
||||||
cMutexLock MutexLock(&mutexM);
|
|
||||||
for (unsigned int i = 0; i < eMaxSecFilterCount; ++i) {
|
|
||||||
if (filtersM[i] && (pidP == filtersM[i]->GetPid())) {
|
|
||||||
debug12("%s (%d) Found [device %d]", __PRETTY_FUNCTION__, pidP, deviceIndexM);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool cSatipSectionFilterHandler::Delete(unsigned int indexP)
|
bool cSatipSectionFilterHandler::Delete(unsigned int indexP)
|
||||||
{
|
{
|
||||||
debug16("%s (%d) [device %d]", __PRETTY_FUNCTION__, indexP, deviceIndexM);
|
//debug("cSatipSectionFilterHandler::%s(%d): index=%d", __FUNCTION__, deviceIndexM, indexP);
|
||||||
if ((indexP < eMaxSecFilterCount) && filtersM[indexP]) {
|
if ((indexP < eMaxSecFilterCount) && filtersM[indexP]) {
|
||||||
debug8("%s (%d) Found [device %d]", __PRETTY_FUNCTION__, indexP, deviceIndexM);
|
//debug("cSatipSectionFilterHandler::%s(%d): found %d", __FUNCTION__, deviceIndexM, indexP);
|
||||||
cSatipSectionFilter *tmp = filtersM[indexP];
|
cSatipSectionFilter *tmp = filtersM[indexP];
|
||||||
filtersM[indexP] = NULL;
|
filtersM[indexP] = NULL;
|
||||||
delete tmp;
|
delete tmp;
|
||||||
@ -357,7 +352,7 @@ bool cSatipSectionFilterHandler::Delete(unsigned int indexP)
|
|||||||
|
|
||||||
bool cSatipSectionFilterHandler::IsBlackListed(u_short pidP, u_char tidP, u_char maskP) const
|
bool cSatipSectionFilterHandler::IsBlackListed(u_short pidP, u_char tidP, u_char maskP) const
|
||||||
{
|
{
|
||||||
debug16("%s (%d, %02X, %02X) [device %d]", __PRETTY_FUNCTION__, pidP, tidP, maskP, deviceIndexM);
|
//debug("cSatipSectionFilterHandler::%s(%d): pid=%d tid=%02X mask=%02X", __FUNCTION__, deviceIndexM, pidP, tidP, maskP);
|
||||||
// loop through section filter table
|
// loop through section filter table
|
||||||
for (int i = 0; i < SECTION_FILTER_TABLE_SIZE; ++i) {
|
for (int i = 0; i < SECTION_FILTER_TABLE_SIZE; ++i) {
|
||||||
int index = SatipConfig.GetDisabledFilters(i);
|
int index = SatipConfig.GetDisabledFilters(i);
|
||||||
@ -365,7 +360,7 @@ bool cSatipSectionFilterHandler::IsBlackListed(u_short pidP, u_char tidP, u_char
|
|||||||
if ((index >= 0) && (index < SECTION_FILTER_TABLE_SIZE) &&
|
if ((index >= 0) && (index < SECTION_FILTER_TABLE_SIZE) &&
|
||||||
(section_filter_table[index].pid == pidP) && (section_filter_table[index].tid == tidP) &&
|
(section_filter_table[index].pid == pidP) && (section_filter_table[index].tid == tidP) &&
|
||||||
(section_filter_table[index].mask == maskP)) {
|
(section_filter_table[index].mask == maskP)) {
|
||||||
debug8("%s Found %s [device %d]", __PRETTY_FUNCTION__, section_filter_table[index].description, deviceIndexM);
|
//debug("cSatipSectionFilterHandler::%s(%d): found %s", __FUNCTION__, deviceIndexM, section_filter_table[index].description);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -374,6 +369,7 @@ bool cSatipSectionFilterHandler::IsBlackListed(u_short pidP, u_char tidP, u_char
|
|||||||
|
|
||||||
int cSatipSectionFilterHandler::Open(u_short pidP, u_char tidP, u_char maskP)
|
int cSatipSectionFilterHandler::Open(u_short pidP, u_char tidP, u_char maskP)
|
||||||
{
|
{
|
||||||
|
// Lock
|
||||||
cMutexLock MutexLock(&mutexM);
|
cMutexLock MutexLock(&mutexM);
|
||||||
// Blacklist check, refuse certain filters
|
// Blacklist check, refuse certain filters
|
||||||
if (IsBlackListed(pidP, tidP, maskP))
|
if (IsBlackListed(pidP, tidP, maskP))
|
||||||
@ -382,7 +378,7 @@ int cSatipSectionFilterHandler::Open(u_short pidP, u_char tidP, u_char maskP)
|
|||||||
for (unsigned int i = 0; i < eMaxSecFilterCount; ++i) {
|
for (unsigned int i = 0; i < eMaxSecFilterCount; ++i) {
|
||||||
if (!filtersM[i]) {
|
if (!filtersM[i]) {
|
||||||
filtersM[i] = new cSatipSectionFilter(deviceIndexM, pidP, tidP, maskP);
|
filtersM[i] = new cSatipSectionFilter(deviceIndexM, pidP, tidP, maskP);
|
||||||
debug16("%s (%d, %02X, %02X) handle=%d index=%u [device %d]", __PRETTY_FUNCTION__, pidP, tidP, maskP, filtersM[i]->GetFd(), i, deviceIndexM);
|
//debug("cSatipSectionFilterHandler::%s(%d): pid=%d tid=%02X mask=%02X handle=%d index=%u", __FUNCTION__, deviceIndexM, pidP, tidP, maskP, filtersM[i]->GetFd(), i);
|
||||||
return filtersM[i]->GetFd();
|
return filtersM[i]->GetFd();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -392,11 +388,12 @@ int cSatipSectionFilterHandler::Open(u_short pidP, u_char tidP, u_char maskP)
|
|||||||
|
|
||||||
void cSatipSectionFilterHandler::Close(int handleP)
|
void cSatipSectionFilterHandler::Close(int handleP)
|
||||||
{
|
{
|
||||||
|
// Lock
|
||||||
cMutexLock MutexLock(&mutexM);
|
cMutexLock MutexLock(&mutexM);
|
||||||
// Search the filter for deletion
|
// Search the filter for deletion
|
||||||
for (unsigned int i = 0; i < eMaxSecFilterCount; ++i) {
|
for (unsigned int i = 0; i < eMaxSecFilterCount; ++i) {
|
||||||
if (filtersM[i] && (handleP == filtersM[i]->GetFd())) {
|
if (filtersM[i] && (handleP == filtersM[i]->GetFd())) {
|
||||||
debug8("%s (%d) pid=%d index=%u [device %d]", __PRETTY_FUNCTION__, handleP, filtersM[i]->GetPid(), i, deviceIndexM);
|
//debug("cSatipSectionFilterHandler::%s(%d): pid=%d handle=%d index=%u", __FUNCTION__, deviceIndexM, filtersM[i]->GetPid(), filtersM[i]->GetFd(), i);
|
||||||
Delete(i);
|
Delete(i);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -405,11 +402,12 @@ void cSatipSectionFilterHandler::Close(int handleP)
|
|||||||
|
|
||||||
int cSatipSectionFilterHandler::GetPid(int handleP)
|
int cSatipSectionFilterHandler::GetPid(int handleP)
|
||||||
{
|
{
|
||||||
|
// Lock
|
||||||
cMutexLock MutexLock(&mutexM);
|
cMutexLock MutexLock(&mutexM);
|
||||||
// Search the filter for data
|
// Search the filter for data
|
||||||
for (unsigned int i = 0; i < eMaxSecFilterCount; ++i) {
|
for (unsigned int i = 0; i < eMaxSecFilterCount; ++i) {
|
||||||
if (filtersM[i] && (handleP == filtersM[i]->GetFd())) {
|
if (filtersM[i] && (handleP == filtersM[i]->GetFd())) {
|
||||||
debug8("%s (%d) pid=%d index=%u [device %d]", __PRETTY_FUNCTION__, handleP, filtersM[i]->GetPid(), i, deviceIndexM);
|
//debug("cSatipSectionFilterHandler::%s(%d): pid=%d handle=%d index=%u", __FUNCTION__, deviceIndexM, filtersM[i]->GetPid(), filtersM[i]->GetFd(), i);
|
||||||
return filtersM[i]->GetPid();
|
return filtersM[i]->GetPid();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -418,7 +416,7 @@ int cSatipSectionFilterHandler::GetPid(int handleP)
|
|||||||
|
|
||||||
void cSatipSectionFilterHandler::Write(uchar *bufferP, int lengthP)
|
void cSatipSectionFilterHandler::Write(uchar *bufferP, int lengthP)
|
||||||
{
|
{
|
||||||
debug16("%s (, %d) [device %d]", __PRETTY_FUNCTION__, lengthP, deviceIndexM);
|
//debug("cSatipSectionFilterHandler::%s(%d): length=%d", __FUNCTION__, deviceIndexM, lengthP);
|
||||||
// Fill up the buffer
|
// Fill up the buffer
|
||||||
if (ringBufferM) {
|
if (ringBufferM) {
|
||||||
int len = ringBufferM->Put(bufferP, lengthP);
|
int len = ringBufferM->Put(bufferP, lengthP);
|
||||||
|
@ -8,7 +8,6 @@
|
|||||||
#ifndef __SATIP_SECTIONFILTER_H
|
#ifndef __SATIP_SECTIONFILTER_H
|
||||||
#define __SATIP_SECTIONFILTER_H
|
#define __SATIP_SECTIONFILTER_H
|
||||||
|
|
||||||
#include <poll.h>
|
|
||||||
#include <vdr/device.h>
|
#include <vdr/device.h>
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
@ -33,13 +32,18 @@ private:
|
|||||||
uint16_t secLenM;
|
uint16_t secLenM;
|
||||||
uint16_t tsFeedpM;
|
uint16_t tsFeedpM;
|
||||||
uint16_t pidM;
|
uint16_t pidM;
|
||||||
uint8_t tidM;
|
|
||||||
uint8_t maskM;
|
|
||||||
|
|
||||||
cRingBufferFrame *ringBufferM;
|
cRingBufferFrame *ringBufferM;
|
||||||
int deviceIndexM;
|
int deviceIndexM;
|
||||||
int socketM[2];
|
int socketM[2];
|
||||||
|
|
||||||
|
uint8_t filterValueM[eDmxMaxFilterSize];
|
||||||
|
uint8_t filterMaskM[eDmxMaxFilterSize];
|
||||||
|
uint8_t filterModeM[eDmxMaxFilterSize];
|
||||||
|
|
||||||
|
uint8_t maskAndModeM[eDmxMaxFilterSize];
|
||||||
|
uint8_t maskAndNotModeM[eDmxMaxFilterSize];
|
||||||
|
|
||||||
inline uint16_t GetLength(const uint8_t *dataP);
|
inline uint16_t GetLength(const uint8_t *dataP);
|
||||||
void New(void);
|
void New(void);
|
||||||
int Filter(void);
|
int Filter(void);
|
||||||
@ -51,27 +55,23 @@ public:
|
|||||||
cSatipSectionFilter(int deviceIndexP, uint16_t pidP, uint8_t tidP, uint8_t maskP);
|
cSatipSectionFilter(int deviceIndexP, uint16_t pidP, uint8_t tidP, uint8_t maskP);
|
||||||
virtual ~cSatipSectionFilter();
|
virtual ~cSatipSectionFilter();
|
||||||
void Process(const uint8_t* dataP);
|
void Process(const uint8_t* dataP);
|
||||||
void Send(void);
|
bool Send(void);
|
||||||
int GetFd(void) { return socketM[0]; }
|
int GetFd(void) { return socketM[0]; }
|
||||||
uint16_t GetPid(void) const { return pidM; }
|
uint16_t GetPid(void) const { return pidM; }
|
||||||
int Available(void) const;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class cSatipSectionFilterHandler : public cThread {
|
class cSatipSectionFilterHandler : public cThread {
|
||||||
private:
|
private:
|
||||||
enum {
|
enum {
|
||||||
eMaxSecFilterCount = 32,
|
eMaxSecFilterCount = 32
|
||||||
eSecFilterSendTimeoutMs = 10
|
|
||||||
};
|
};
|
||||||
cRingBufferLinear *ringBufferM;
|
cRingBufferLinear *ringBufferM;
|
||||||
cMutex mutexM;
|
cMutex mutexM;
|
||||||
int deviceIndexM;
|
int deviceIndexM;
|
||||||
cSatipSectionFilter *filtersM[eMaxSecFilterCount];
|
cSatipSectionFilter *filtersM[eMaxSecFilterCount];
|
||||||
struct pollfd pollFdsM[eMaxSecFilterCount];
|
|
||||||
|
|
||||||
bool Delete(unsigned int indexP);
|
bool Delete(unsigned int indexP);
|
||||||
bool IsBlackListed(u_short pidP, u_char tidP, u_char maskP) const;
|
bool IsBlackListed(u_short pidP, u_char tidP, u_char maskP) const;
|
||||||
void SendAll(void);
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void Action(void);
|
virtual void Action(void);
|
||||||
@ -80,7 +80,6 @@ public:
|
|||||||
cSatipSectionFilterHandler(int deviceIndexP, unsigned int bufferLenP);
|
cSatipSectionFilterHandler(int deviceIndexP, unsigned int bufferLenP);
|
||||||
virtual ~cSatipSectionFilterHandler();
|
virtual ~cSatipSectionFilterHandler();
|
||||||
cString GetInformation(void);
|
cString GetInformation(void);
|
||||||
bool Exists(u_short pidP);
|
|
||||||
int Open(u_short pidP, u_char tidP, u_char maskP);
|
int Open(u_short pidP, u_char tidP, u_char maskP);
|
||||||
void Close(int handleP);
|
void Close(int handleP);
|
||||||
int GetPid(int handleP);
|
int GetPid(int handleP);
|
||||||
|
528
server.c
528
server.c
@ -7,234 +7,60 @@
|
|||||||
|
|
||||||
#include <vdr/sources.h>
|
#include <vdr/sources.h>
|
||||||
|
|
||||||
#include "config.h"
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "log.h"
|
|
||||||
#include "server.h"
|
#include "server.h"
|
||||||
|
|
||||||
// --- cSatipFrontend ---------------------------------------------------------
|
|
||||||
|
|
||||||
cSatipFrontend::cSatipFrontend(const int indexP, const char *descriptionP)
|
|
||||||
: indexM(indexP),
|
|
||||||
transponderM(0),
|
|
||||||
deviceIdM(-1),
|
|
||||||
descriptionM(descriptionP)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
cSatipFrontend::~cSatipFrontend()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
// --- cSatipFrontends --------------------------------------------------------
|
|
||||||
|
|
||||||
bool cSatipFrontends::Matches(int deviceIdP, int transponderP)
|
|
||||||
{
|
|
||||||
for (cSatipFrontend *f = First(); f; f = Next(f)) {
|
|
||||||
if (f->Attached() && (f->DeviceId() == deviceIdP) && (f->Transponder() == transponderP))
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool cSatipFrontends::Assign(int deviceIdP, int transponderP)
|
|
||||||
{
|
|
||||||
cSatipFrontend *tmp = NULL;
|
|
||||||
// Prefer any used one
|
|
||||||
for (cSatipFrontend *f = First(); f; f = Next(f)) {
|
|
||||||
if (f->DeviceId() == deviceIdP) { // give deviceID priority, but take detached frontend if deviceID ist not yet attached
|
|
||||||
tmp = f;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (!f->Attached()) {
|
|
||||||
tmp = f;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (tmp) {
|
|
||||||
tmp->SetTransponder(transponderP);
|
|
||||||
debug9("%s assigned TP %d to %s/#%d", __PRETTY_FUNCTION__, transponderP, *tmp->Description(), tmp->Index());
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
error("no assignable frontend found [device %u]", deviceIdP);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool cSatipFrontends::Attach(int deviceIdP, int transponderP)
|
|
||||||
{
|
|
||||||
cSatipFrontend *tmp = NULL;
|
|
||||||
for (cSatipFrontend *f = First(); f; f = Next(f)) {
|
|
||||||
if (f->Transponder() == transponderP) {
|
|
||||||
tmp = f;
|
|
||||||
if (f->DeviceId() == deviceIdP) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tmp) {
|
|
||||||
tmp->Attach(deviceIdP);
|
|
||||||
debug9("%s attached deviceId %d (TP %d) to %s/#%d", __PRETTY_FUNCTION__, deviceIdP, transponderP, *tmp->Description(), tmp->Index());
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
error("%s no Frontend found for attaching deviceID %d (TP %d)", __PRETTY_FUNCTION__, deviceIdP, transponderP);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool cSatipFrontends::Detach(int deviceIdP, int transponderP)
|
|
||||||
{
|
|
||||||
for (cSatipFrontend *f = First(); f; f = Next(f)) {
|
|
||||||
if (f->Transponder() == transponderP) {
|
|
||||||
f->Detach(deviceIdP);
|
|
||||||
debug9("%s detached deviceID %d (TP %d) from %s/#%d", __PRETTY_FUNCTION__, deviceIdP, transponderP, *f->Description(), f->Index());
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// --- cSatipServer -----------------------------------------------------------
|
// --- cSatipServer -----------------------------------------------------------
|
||||||
|
|
||||||
cSatipServer::cSatipServer(const char *srcAddressP, const char *addressP, const int portP, const char *modelP, const char *filtersP, const char *descriptionP, const int quirkP)
|
cSatipServer::cSatipServer(const char *addressP, const char *descriptionP, const char *modelP)
|
||||||
: srcAddressM((srcAddressP && *srcAddressP) ? srcAddressP : ""),
|
: addressM(addressP),
|
||||||
addressM((addressP && *addressP) ? addressP : "0.0.0.0"),
|
descriptionM(descriptionP),
|
||||||
modelM((modelP && *modelP) ? modelP : "DVBS-1"),
|
modelM(modelP),
|
||||||
filtersM((filtersP && *filtersP) ? filtersP : ""),
|
modelTypeM(eSatipModelTypeNone),
|
||||||
descriptionM(!isempty(descriptionP) ? descriptionP : "MyBrokenHardware"),
|
quirkM(eSatipQuirkNone),
|
||||||
quirksM(""),
|
useCountM(0),
|
||||||
portM(portP),
|
|
||||||
quirkM(quirkP),
|
|
||||||
hasCiM(false),
|
|
||||||
activeM(true),
|
|
||||||
createdM(time(NULL)),
|
createdM(time(NULL)),
|
||||||
lastSeenM(0)
|
lastSeenM(0)
|
||||||
{
|
{
|
||||||
memset(sourceFiltersM, 0, sizeof(sourceFiltersM));
|
memset(modelCountM, 0, sizeof(modelCountM));
|
||||||
if (!isempty(*filtersM)) {
|
if (isempty(*modelM))
|
||||||
char *s, *p = strdup(*filtersM);
|
modelM = "DVBS-1";
|
||||||
char *r = strtok_r(p, ",", &s);
|
// Grundig Sat Systems GSS.box DSI 400 has a session id bug
|
||||||
unsigned int i = 0;
|
if (strstr(*descriptionM, "GSSBOX"))
|
||||||
while (r) {
|
quirkM |= eSatipQuirkSessionId;
|
||||||
int t = cSource::FromString(skipspace(r));
|
|
||||||
if (t && i < ELEMENTS(sourceFiltersM))
|
|
||||||
sourceFiltersM[i++] = t;
|
|
||||||
r = strtok_r(NULL, ",", &s);
|
|
||||||
}
|
|
||||||
if (i) {
|
|
||||||
filtersM = "";
|
|
||||||
for (unsigned int j = 0; j < i; ++j)
|
|
||||||
filtersM = cString::sprintf("%s%s%s", *filtersM, isempty(*filtersM) ? "" : ",", *cSource::ToString(sourceFiltersM[j]));
|
|
||||||
debug3("%s filters=%s", __PRETTY_FUNCTION__, *filtersM);
|
|
||||||
}
|
|
||||||
FREE_POINTER(p);
|
|
||||||
}
|
|
||||||
if (!SatipConfig.GetDisableServerQuirks()) {
|
|
||||||
// These devices contain a session id bug:
|
|
||||||
// Inverto Airscreen Server IDL 400 ?
|
|
||||||
// Elgato EyeTV Netstream 4Sat ?
|
|
||||||
if (strstr(*descriptionM, "GSSBOX") || // Grundig Sat Systems GSS.box DSI 400
|
|
||||||
strstr(*descriptionM, "DIGIBIT") || // Telestar Digibit R1
|
|
||||||
strstr(*descriptionM, "Multibox-") || // Inverto IDL-400s: Multibox-<MMAACC>:SAT>IP
|
|
||||||
strstr(*descriptionM, "Triax SatIP Converter") // Triax TSS 400
|
|
||||||
)
|
|
||||||
quirkM |= eSatipQuirkSessionId;
|
|
||||||
// These devices contain support for RTP over TCP:
|
|
||||||
if (strstr(*descriptionM, "minisatip") || // minisatip server
|
|
||||||
strstr(*descriptionM, "DVBViewer") // DVBViewer Media Server
|
|
||||||
)
|
|
||||||
quirkM |= eSatipQuirkRtpOverTcp;
|
|
||||||
// These devices contain a play (add/delpids) parameter bug:
|
|
||||||
if (strstr(*descriptionM, "FRITZ!WLAN Repeater DVB-C") || // FRITZ!WLAN Repeater DVB-C
|
|
||||||
strstr(*descriptionM, "fritzdvbc") // FRITZ!WLAN Repeater DVB-C (old firmware)
|
|
||||||
)
|
|
||||||
quirkM |= eSatipQuirkPlayPids;
|
|
||||||
// These devices contain a frontend locking bug:
|
|
||||||
if (strstr(*descriptionM, "FRITZ!WLAN Repeater DVB-C") || // FRITZ!WLAN Repeater DVB-C
|
|
||||||
strstr(*descriptionM, "fritzdvbc") || // FRITZ!WLAN Repeater DVB-C (old firmware)
|
|
||||||
strstr(*descriptionM, "Schwaiger Sat>IP Server") // Schwaiger MS41IP
|
|
||||||
)
|
|
||||||
quirkM |= eSatipQuirkForceLock;
|
|
||||||
// These devices support the X_PMT protocol extension:
|
|
||||||
if (strstr(*descriptionM, "OctopusNet") || // Digital Devices OctopusNet
|
|
||||||
strstr(*descriptionM, "minisatip") // minisatip server
|
|
||||||
)
|
|
||||||
quirkM |= eSatipQuirkCiXpmt;
|
|
||||||
// These devices support the TNR protocol extension:
|
|
||||||
if (strstr(*descriptionM, "DVBViewer") // DVBViewer Media Server
|
|
||||||
)
|
|
||||||
quirkM |= eSatipQuirkCiTnr;
|
|
||||||
// These devices don't support auto-detection of pilot tones:
|
|
||||||
if (strstr(*descriptionM, "GSSBOX") || // Grundig Sat Systems GSS.box DSI 400
|
|
||||||
strstr(*descriptionM, "DIGIBIT") || // Telestar Digibit R1
|
|
||||||
strstr(*descriptionM, "Multibox-") || // Inverto IDL-400s: Multibox-<MMAACC>:SAT>IP
|
|
||||||
strstr(*descriptionM, "Triax SatIP Converter") || // Triax TSS 400
|
|
||||||
strstr(*descriptionM, "KATHREIN SatIP Server") // Kathrein ExIP 414/E
|
|
||||||
)
|
|
||||||
quirkM |= eSatipQuirkForcePilot;
|
|
||||||
// These devices require TEARDOWN before new PLAY command:
|
|
||||||
if (strstr(*descriptionM, "FRITZ!WLAN Repeater DVB-C") || // FRITZ!WLAN Repeater DVB-C
|
|
||||||
strstr(*descriptionM, "fritzdvbc") // FRITZ!WLAN Repeater DVB-C (old firmware)
|
|
||||||
)
|
|
||||||
quirkM |= eSatipQuirkTearAndPlay;
|
|
||||||
}
|
|
||||||
if ((quirkM & eSatipQuirkMask) & eSatipQuirkSessionId)
|
|
||||||
quirksM = cString::sprintf("%s%sSessionId", *quirksM, isempty(*quirksM) ? "" : ",");
|
|
||||||
if ((quirkM & eSatipQuirkMask) & eSatipQuirkPlayPids)
|
|
||||||
quirksM = cString::sprintf("%s%sPlayPids", *quirksM, isempty(*quirksM) ? "" : ",");
|
|
||||||
if ((quirkM & eSatipQuirkMask) & eSatipQuirkForceLock)
|
|
||||||
quirksM = cString::sprintf("%s%sForceLock", *quirksM, isempty(*quirksM) ? "" : ",");
|
|
||||||
if ((quirkM & eSatipQuirkMask) & eSatipQuirkRtpOverTcp)
|
|
||||||
quirksM = cString::sprintf("%s%sRtpOverTcp", *quirksM, isempty(*quirksM) ? "" : ",");
|
|
||||||
if ((quirkM & eSatipQuirkMask) & eSatipQuirkCiXpmt)
|
|
||||||
quirksM = cString::sprintf("%s%sCiXpmt", *quirksM, isempty(*quirksM) ? "" : ",");
|
|
||||||
if ((quirkM & eSatipQuirkMask) & eSatipQuirkCiTnr)
|
|
||||||
quirksM = cString::sprintf("%s%sCiTnr", *quirksM, isempty(*quirksM) ? "" : ",");
|
|
||||||
if ((quirkM & eSatipQuirkMask) & eSatipQuirkForcePilot)
|
|
||||||
quirksM = cString::sprintf("%s%sForcePilot", *quirksM, isempty(*quirksM) ? "" : ",");
|
|
||||||
debug3("%s description=%s quirks=%s", __PRETTY_FUNCTION__, *descriptionM, *quirksM);
|
|
||||||
// These devices support external CI
|
|
||||||
if (strstr(*descriptionM, "OctopusNet") || // Digital Devices OctopusNet
|
|
||||||
strstr(*descriptionM, "minisatip") || // minisatip server
|
|
||||||
strstr(*descriptionM, "DVBViewer") // DVBViewer Media Server
|
|
||||||
) {
|
|
||||||
hasCiM = true;
|
|
||||||
}
|
|
||||||
char *s, *p = strdup(*modelM);
|
char *s, *p = strdup(*modelM);
|
||||||
char *r = strtok_r(p, ",", &s);
|
char *r = strtok_r(p, ",", &s);
|
||||||
while (r) {
|
while (r) {
|
||||||
char *c;
|
if (strstr(r, "DVBS2")) {
|
||||||
if (c = strstr(r, "DVBS2-")) {
|
modelTypeM |= cSatipServer::eSatipModelTypeDVBS2;
|
||||||
int count = atoi(c + 6);
|
if (char *c = strstr(r, "-"))
|
||||||
for (int i = 1; i <= count; ++i)
|
modelCountM[eSatipModuleDVBS2] = atoi(++c);
|
||||||
frontendsM[eSatipFrontendDVBS2].Add(new cSatipFrontend(i, "DVB-S2"));
|
else
|
||||||
|
modelCountM[eSatipModuleDVBS2] = 1;
|
||||||
}
|
}
|
||||||
else if (c = strstr(r, "DVBT-")) {
|
if (strstr(r, "DVBT2")) {
|
||||||
int count = atoi(c + 5);
|
modelTypeM |= cSatipServer::eSatipModelTypeDVBT | cSatipServer::eSatipModelTypeDVBT2;
|
||||||
for (int i = 1; i <= count; ++i)
|
if (char *c = strstr(r, "-"))
|
||||||
frontendsM[eSatipFrontendDVBT].Add(new cSatipFrontend(i, "DVB-T"));
|
modelCountM[eSatipModuleDVBT2] = atoi(++c);
|
||||||
|
else
|
||||||
|
modelCountM[eSatipModuleDVBT2] = 1;
|
||||||
|
// Add model quirks here
|
||||||
|
if (strstr(*descriptionM, "OctopusNet"))
|
||||||
|
modelTypeM |= cSatipServer::eSatipModelTypeDVBC;
|
||||||
}
|
}
|
||||||
else if (c = strstr(r, "DVBT2-")) {
|
if (strstr(r, "DVBT")) {
|
||||||
int count = atoi(c + 6);
|
modelTypeM |= cSatipServer::eSatipModelTypeDVBT;
|
||||||
for (int i = 1; i <= count; ++i)
|
if (char *c = strstr(r, "-"))
|
||||||
frontendsM[eSatipFrontendDVBT2].Add(new cSatipFrontend(i, "DVB-T2"));
|
modelCountM[eSatipModuleDVBT] = atoi(++c);
|
||||||
}
|
else
|
||||||
else if (c = strstr(r, "DVBC-")) {
|
modelCountM[eSatipModuleDVBT] = 1;
|
||||||
int count = atoi(c + 5);
|
// Add model quirks here
|
||||||
for (int i = 1; i <= count; ++i)
|
if (strstr(*descriptionM, "OctopusNet"))
|
||||||
frontendsM[eSatipFrontendDVBC].Add(new cSatipFrontend(i, "DVB-C"));
|
modelTypeM |= cSatipServer::eSatipModelTypeDVBC;
|
||||||
}
|
|
||||||
else if (c = strstr(r, "DVBC2-")) {
|
|
||||||
int count = atoi(c + 6);
|
|
||||||
for (int i = 1; i <= count; ++i)
|
|
||||||
frontendsM[eSatipFrontendDVBC2].Add(new cSatipFrontend(i, "DVB-C2"));
|
|
||||||
}
|
|
||||||
else if (c = strstr(r, "ATSC-")) {
|
|
||||||
int count = atoi(c + 5);
|
|
||||||
for (int i = 1; i <= count; ++i)
|
|
||||||
frontendsM[eSatipFrontendATSC].Add(new cSatipFrontend(i, "ATSC"));
|
|
||||||
}
|
}
|
||||||
r = strtok_r(NULL, ",", &s);
|
r = strtok_r(NULL, ",", &s);
|
||||||
}
|
}
|
||||||
FREE_POINTER(p);
|
free(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
cSatipServer::~cSatipServer()
|
cSatipServer::~cSatipServer()
|
||||||
@ -244,135 +70,15 @@ cSatipServer::~cSatipServer()
|
|||||||
int cSatipServer::Compare(const cListObject &listObjectP) const
|
int cSatipServer::Compare(const cListObject &listObjectP) const
|
||||||
{
|
{
|
||||||
const cSatipServer *s = (const cSatipServer *)&listObjectP;
|
const cSatipServer *s = (const cSatipServer *)&listObjectP;
|
||||||
int result = strcasecmp(*addressM, *s->addressM);
|
return strcasecmp(*addressM, *s->addressM);
|
||||||
if (!result) {
|
|
||||||
result = strcasecmp(*modelM, *s->modelM);
|
|
||||||
if (!result)
|
|
||||||
result = strcasecmp(*descriptionM, *s->descriptionM);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool cSatipServer::IsValidSource(int sourceP)
|
void cSatipServer::Use(bool onOffP)
|
||||||
{
|
{
|
||||||
if (sourceFiltersM[0]) {
|
if (onOffP)
|
||||||
for (unsigned int i = 0; i < ELEMENTS(sourceFiltersM); ++i) {
|
++useCountM;
|
||||||
if (sourceP == sourceFiltersM[i]) {
|
else
|
||||||
return true;
|
--useCountM;
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool cSatipServer::Assign(int deviceIdP, int sourceP, int systemP, int transponderP)
|
|
||||||
{
|
|
||||||
bool result = false;
|
|
||||||
if (IsValidSource(sourceP)) {
|
|
||||||
if (cSource::IsType(sourceP, 'S'))
|
|
||||||
result = frontendsM[eSatipFrontendDVBS2].Assign(deviceIdP, transponderP);
|
|
||||||
else if (cSource::IsType(sourceP, 'T')) {
|
|
||||||
if (systemP)
|
|
||||||
result = frontendsM[eSatipFrontendDVBT2].Assign(deviceIdP, transponderP);
|
|
||||||
else
|
|
||||||
result = frontendsM[eSatipFrontendDVBT].Assign(deviceIdP, transponderP) || frontendsM[eSatipFrontendDVBT2].Assign(deviceIdP, transponderP);
|
|
||||||
}
|
|
||||||
else if (cSource::IsType(sourceP, 'C')) {
|
|
||||||
if (systemP)
|
|
||||||
result = frontendsM[eSatipFrontendDVBC2].Assign(deviceIdP, transponderP);
|
|
||||||
else
|
|
||||||
result = frontendsM[eSatipFrontendDVBC].Assign(deviceIdP, transponderP) || frontendsM[eSatipFrontendDVBC2].Assign(deviceIdP, transponderP);
|
|
||||||
}
|
|
||||||
else if (cSource::IsType(sourceP, 'A'))
|
|
||||||
result = frontendsM[eSatipFrontendATSC].Assign(deviceIdP, transponderP);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool cSatipServer::Matches(int sourceP)
|
|
||||||
{
|
|
||||||
if (IsValidSource(sourceP)) {
|
|
||||||
if (cSource::IsType(sourceP, 'S'))
|
|
||||||
return GetModulesDVBS2();
|
|
||||||
else if (cSource::IsType(sourceP, 'T'))
|
|
||||||
return GetModulesDVBT() || GetModulesDVBT2();
|
|
||||||
else if (cSource::IsType(sourceP, 'C'))
|
|
||||||
return GetModulesDVBC() || GetModulesDVBC2();
|
|
||||||
else if (cSource::IsType(sourceP, 'A'))
|
|
||||||
return GetModulesATSC();
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool cSatipServer::Matches(int deviceIdP, int sourceP, int systemP, int transponderP)
|
|
||||||
{
|
|
||||||
bool result = false;
|
|
||||||
if (IsValidSource(sourceP)) {
|
|
||||||
if (cSource::IsType(sourceP, 'S'))
|
|
||||||
result = frontendsM[eSatipFrontendDVBS2].Matches(deviceIdP, transponderP);
|
|
||||||
else if (cSource::IsType(sourceP, 'T')) {
|
|
||||||
if (systemP)
|
|
||||||
result = frontendsM[eSatipFrontendDVBT2].Matches(deviceIdP, transponderP);
|
|
||||||
else
|
|
||||||
result = frontendsM[eSatipFrontendDVBT].Matches(deviceIdP, transponderP) || frontendsM[eSatipFrontendDVBT2].Matches(deviceIdP, transponderP);
|
|
||||||
}
|
|
||||||
else if (cSource::IsType(sourceP, 'C')) {
|
|
||||||
if (systemP)
|
|
||||||
result = frontendsM[eSatipFrontendDVBC2].Matches(deviceIdP, transponderP);
|
|
||||||
else
|
|
||||||
result = frontendsM[eSatipFrontendDVBC].Matches(deviceIdP, transponderP) || frontendsM[eSatipFrontendDVBC2].Matches(deviceIdP, transponderP);
|
|
||||||
}
|
|
||||||
else if (cSource::IsType(sourceP, 'A'))
|
|
||||||
result = frontendsM[eSatipFrontendATSC].Matches(deviceIdP, transponderP);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
void cSatipServer::Attach(int deviceIdP, int transponderP)
|
|
||||||
{
|
|
||||||
for (int i = 0; i < eSatipFrontendCount; ++i) {
|
|
||||||
if (frontendsM[i].Attach(deviceIdP, transponderP))
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void cSatipServer::Detach(int deviceIdP, int transponderP)
|
|
||||||
{
|
|
||||||
for (int i = 0; i < eSatipFrontendCount; ++i) {
|
|
||||||
if (frontendsM[i].Detach(deviceIdP, transponderP))
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int cSatipServer::GetModulesDVBS2(void)
|
|
||||||
{
|
|
||||||
return frontendsM[eSatipFrontendDVBS2].Count();
|
|
||||||
}
|
|
||||||
|
|
||||||
int cSatipServer::GetModulesDVBT(void)
|
|
||||||
{
|
|
||||||
return frontendsM[eSatipFrontendDVBT].Count();
|
|
||||||
}
|
|
||||||
|
|
||||||
int cSatipServer::GetModulesDVBT2(void)
|
|
||||||
{
|
|
||||||
return frontendsM[eSatipFrontendDVBT2].Count();
|
|
||||||
}
|
|
||||||
|
|
||||||
int cSatipServer::GetModulesDVBC(void)
|
|
||||||
{
|
|
||||||
return frontendsM[eSatipFrontendDVBC].Count();
|
|
||||||
}
|
|
||||||
|
|
||||||
int cSatipServer::GetModulesDVBC2(void)
|
|
||||||
{
|
|
||||||
return frontendsM[eSatipFrontendDVBC2].Count();
|
|
||||||
}
|
|
||||||
|
|
||||||
int cSatipServer::GetModulesATSC(void)
|
|
||||||
{
|
|
||||||
return frontendsM[eSatipFrontendATSC].Count();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- cSatipServers ----------------------------------------------------------
|
// --- cSatipServers ----------------------------------------------------------
|
||||||
@ -380,32 +86,35 @@ int cSatipServer::GetModulesATSC(void)
|
|||||||
cSatipServer *cSatipServers::Find(cSatipServer *serverP)
|
cSatipServer *cSatipServers::Find(cSatipServer *serverP)
|
||||||
{
|
{
|
||||||
for (cSatipServer *s = First(); s; s = Next(s)) {
|
for (cSatipServer *s = First(); s; s = Next(s)) {
|
||||||
if (s->Compare(*serverP) == 0)
|
if (s == serverP)
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
cSatipServer *cSatipServers::Find(int sourceP)
|
cSatipServer *cSatipServers::Find(int sourceP, int systemP)
|
||||||
{
|
{
|
||||||
|
cSatipServer *result = NULL;
|
||||||
|
int model = 0;
|
||||||
|
if (cSource::IsType(sourceP, 'S'))
|
||||||
|
model |= cSatipServer::eSatipModelTypeDVBS2;
|
||||||
|
else if (cSource::IsType(sourceP, 'T')) {
|
||||||
|
if (systemP < 0)
|
||||||
|
model |= cSatipServer::eSatipModelTypeDVBT2 | cSatipServer::eSatipModelTypeDVBT;
|
||||||
|
else
|
||||||
|
model |= systemP ? cSatipServer::eSatipModelTypeDVBT2 : cSatipServer::eSatipModelTypeDVBT;
|
||||||
|
}
|
||||||
|
else if (cSource::IsType(sourceP, 'C'))
|
||||||
|
model |= cSatipServer::eSatipModelTypeDVBC;
|
||||||
for (cSatipServer *s = First(); s; s = Next(s)) {
|
for (cSatipServer *s = First(); s; s = Next(s)) {
|
||||||
if (s->Matches(sourceP))
|
if (s->Match(model)) {
|
||||||
return s;
|
result = s;
|
||||||
|
if (!s->Used()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return NULL;
|
return result;
|
||||||
}
|
|
||||||
|
|
||||||
cSatipServer *cSatipServers::Assign(int deviceIdP, int sourceP, int transponderP, int systemP)
|
|
||||||
{
|
|
||||||
for (cSatipServer *s = First(); s; s = Next(s)) {
|
|
||||||
if (s->IsActive() && s->Matches(deviceIdP, sourceP, systemP, transponderP))
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
for (cSatipServer *s = First(); s; s = Next(s)) {
|
|
||||||
if (s->IsActive() && s->Assign(deviceIdP, sourceP, systemP, transponderP))
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cSatipServer *cSatipServers::Update(cSatipServer *serverP)
|
cSatipServer *cSatipServers::Update(cSatipServer *serverP)
|
||||||
@ -419,106 +128,26 @@ cSatipServer *cSatipServers::Update(cSatipServer *serverP)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void cSatipServers::Activate(cSatipServer *serverP, bool onOffP)
|
void cSatipServers::Use(cSatipServer *serverP, bool onOffP)
|
||||||
{
|
{
|
||||||
for (cSatipServer *s = First(); s; s = Next(s)) {
|
for (cSatipServer *s = First(); s; s = Next(s)) {
|
||||||
if (s == serverP) {
|
if (s == serverP) {
|
||||||
s->Activate(onOffP);
|
s->Use(onOffP);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void cSatipServers::Attach(cSatipServer *serverP, int deviceIdP, int transponderP)
|
|
||||||
{
|
|
||||||
for (cSatipServer *s = First(); s; s = Next(s)) {
|
|
||||||
if (s == serverP) {
|
|
||||||
s->Attach(deviceIdP, transponderP);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void cSatipServers::Detach(cSatipServer *serverP, int deviceIdP, int transponderP)
|
|
||||||
{
|
|
||||||
for (cSatipServer *s = First(); s; s = Next(s)) {
|
|
||||||
if (s == serverP) {
|
|
||||||
s->Detach(deviceIdP, transponderP);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool cSatipServers::IsQuirk(cSatipServer *serverP, int quirkP)
|
|
||||||
{
|
|
||||||
bool result = false;
|
|
||||||
for (cSatipServer *s = First(); s; s = Next(s)) {
|
|
||||||
if (s == serverP) {
|
|
||||||
result = s->Quirk(quirkP);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool cSatipServers::HasCI(cSatipServer *serverP)
|
|
||||||
{
|
|
||||||
bool result = false;
|
|
||||||
for (cSatipServer *s = First(); s; s = Next(s)) {
|
|
||||||
if (s == serverP) {
|
|
||||||
result = s->HasCI();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
void cSatipServers::Cleanup(uint64_t intervalMsP)
|
void cSatipServers::Cleanup(uint64_t intervalMsP)
|
||||||
{
|
{
|
||||||
for (cSatipServer *s = First(); s; s = Next(s)) {
|
for (cSatipServer *s = First(); s; s = Next(s)) {
|
||||||
if (!intervalMsP || (s->LastSeen() > intervalMsP)) {
|
if (!intervalMsP || (s->LastSeen() > intervalMsP)) {
|
||||||
info("Removing server %s (%s %s)", s->Description(), s->Address(), s->Model());
|
info("Removing device %s (%s %s)", s->Description(), s->Address(), s->Model());
|
||||||
Del(s);
|
Del(s);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cString cSatipServers::GetSrcAddress(cSatipServer *serverP)
|
|
||||||
{
|
|
||||||
cString address = "";
|
|
||||||
for (cSatipServer *s = First(); s; s = Next(s)) {
|
|
||||||
if (s == serverP) {
|
|
||||||
address = s->SrcAddress();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return address;
|
|
||||||
}
|
|
||||||
|
|
||||||
cString cSatipServers::GetAddress(cSatipServer *serverP)
|
|
||||||
{
|
|
||||||
cString address = "";
|
|
||||||
for (cSatipServer *s = First(); s; s = Next(s)) {
|
|
||||||
if (s == serverP) {
|
|
||||||
address = s->Address();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return address;
|
|
||||||
}
|
|
||||||
|
|
||||||
int cSatipServers::GetPort(cSatipServer *serverP)
|
|
||||||
{
|
|
||||||
int port = SATIP_DEFAULT_RTSP_PORT;
|
|
||||||
for (cSatipServer *s = First(); s; s = Next(s)) {
|
|
||||||
if (s == serverP) {
|
|
||||||
port = s->Port();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return port;
|
|
||||||
}
|
|
||||||
|
|
||||||
cString cSatipServers::GetString(cSatipServer *serverP)
|
cString cSatipServers::GetString(cSatipServer *serverP)
|
||||||
{
|
{
|
||||||
cString list = "";
|
cString list = "";
|
||||||
@ -535,10 +164,7 @@ cString cSatipServers::List(void)
|
|||||||
{
|
{
|
||||||
cString list = "";
|
cString list = "";
|
||||||
for (cSatipServer *s = First(); s; s = Next(s))
|
for (cSatipServer *s = First(); s; s = Next(s))
|
||||||
if (isempty(s->SrcAddress()))
|
list = cString::sprintf("%s%s|%s|%s\n", *list, s->Address(), s->Model(), s->Description());
|
||||||
list = cString::sprintf("%s%c %s|%s|%s\n", *list, s->IsActive() ? '+' : '-', s->Address(), s->Model(), s->Description());
|
|
||||||
else
|
|
||||||
list = cString::sprintf("%s%c %s@%s|%s|%s\n", *list, s->IsActive() ? '+' : '-', s->SrcAddress(), s->Address(), s->Model(), s->Description());
|
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -546,18 +172,10 @@ int cSatipServers::NumProvidedSystems(void)
|
|||||||
{
|
{
|
||||||
int count = 0;
|
int count = 0;
|
||||||
for (cSatipServer *s = First(); s; s = Next(s)) {
|
for (cSatipServer *s = First(); s; s = Next(s)) {
|
||||||
// DVB-S2: qpsk, 8psk, 16apsk, 32apsk
|
// DVB-S*: qpsk, 8psk
|
||||||
count += s->GetModulesDVBS2() * 4;
|
count += s->Satellite() * 4;
|
||||||
// DVB-T: qpsk, qam16, qam64
|
// DVB-T*: qpsk, qam16, qam64, qam256
|
||||||
count += s->GetModulesDVBT() * 3;
|
count += (s->Terrestrial2() ? s->Terrestrial2() : s->Terrestrial()) * 4;
|
||||||
// DVB-T2: qpsk, qam16, qam64, qam256
|
|
||||||
count += s->GetModulesDVBT2() * 4;
|
|
||||||
// DVB-C: qam64, qam128, qam256
|
|
||||||
count += s->GetModulesDVBC() * 3;
|
|
||||||
// DVB-C2: qam16, qam32, qam64, qam128, qam256
|
|
||||||
count += s->GetModulesDVBC2() * 5;
|
|
||||||
// ATSC: 8vbs, 16vbs, qam256
|
|
||||||
count += s->GetModulesATSC() * 3;
|
|
||||||
}
|
}
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
140
server.h
140
server.h
@ -8,114 +8,58 @@
|
|||||||
#ifndef __SATIP_SERVER_H
|
#ifndef __SATIP_SERVER_H
|
||||||
#define __SATIP_SERVER_H
|
#define __SATIP_SERVER_H
|
||||||
|
|
||||||
class cSatipServer;
|
|
||||||
|
|
||||||
// --- cSatipFrontend ---------------------------------------------------------
|
|
||||||
|
|
||||||
class cSatipFrontend : public cListObject {
|
|
||||||
private:
|
|
||||||
int indexM;
|
|
||||||
int transponderM;
|
|
||||||
int deviceIdM;
|
|
||||||
cString descriptionM;
|
|
||||||
|
|
||||||
public:
|
|
||||||
cSatipFrontend(const int indexP, const char *descriptionP);
|
|
||||||
virtual ~cSatipFrontend();
|
|
||||||
void Attach(int deviceIdP) { deviceIdM = deviceIdP; }
|
|
||||||
void Detach(int deviceIdP) { if (deviceIdP == deviceIdM) deviceIdM = -1; }
|
|
||||||
cString Description(void) { return descriptionM; }
|
|
||||||
bool Attached(void) { return (deviceIdM >= 0); }
|
|
||||||
int Index(void) { return indexM; }
|
|
||||||
int Transponder(void) { return transponderM; }
|
|
||||||
int DeviceId(void) { return deviceIdM; }
|
|
||||||
void SetTransponder(int transponderP) { transponderM = transponderP; }
|
|
||||||
};
|
|
||||||
|
|
||||||
// --- cSatipFrontends --------------------------------------------------------
|
|
||||||
|
|
||||||
class cSatipFrontends : public cList<cSatipFrontend> {
|
|
||||||
public:
|
|
||||||
bool Matches(int deviceIdP, int transponderP);
|
|
||||||
bool Assign(int deviceIdP, int transponderP);
|
|
||||||
bool Attach(int deviceIdP, int transponderP);
|
|
||||||
bool Detach(int deviceIdP, int transponderP);
|
|
||||||
};
|
|
||||||
|
|
||||||
// --- cSatipServer -----------------------------------------------------------
|
// --- cSatipServer -----------------------------------------------------------
|
||||||
|
|
||||||
class cSatipServer : public cListObject {
|
class cSatipServer : public cListObject {
|
||||||
private:
|
private:
|
||||||
enum eSatipFrontend {
|
enum eSatipModule {
|
||||||
eSatipFrontendDVBS2 = 0,
|
eSatipModuleDVBS2 = 0,
|
||||||
eSatipFrontendDVBT,
|
eSatipModuleDVBT,
|
||||||
eSatipFrontendDVBT2,
|
eSatipModuleDVBT2,
|
||||||
eSatipFrontendDVBC,
|
eSatipModuleCount
|
||||||
eSatipFrontendDVBC2,
|
|
||||||
eSatipFrontendATSC,
|
|
||||||
eSatipFrontendCount
|
|
||||||
};
|
};
|
||||||
enum {
|
|
||||||
eSatipMaxSourceFilters = 16
|
|
||||||
};
|
|
||||||
cString srcAddressM;
|
|
||||||
cString addressM;
|
cString addressM;
|
||||||
cString modelM;
|
|
||||||
cString filtersM;
|
|
||||||
cString descriptionM;
|
cString descriptionM;
|
||||||
cString quirksM;
|
cString modelM;
|
||||||
cSatipFrontends frontendsM[eSatipFrontendCount];
|
int modelCountM[eSatipModuleCount];
|
||||||
int sourceFiltersM[eSatipMaxSourceFilters];
|
int modelTypeM;
|
||||||
int portM;
|
|
||||||
int quirkM;
|
int quirkM;
|
||||||
bool hasCiM;
|
int useCountM;
|
||||||
bool activeM;
|
|
||||||
time_t createdM;
|
time_t createdM;
|
||||||
cTimeMs lastSeenM;
|
cTimeMs lastSeenM;
|
||||||
bool IsValidSource(int sourceP);
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
enum eSatipQuirk {
|
enum eSatipQuirk {
|
||||||
eSatipQuirkNone = 0x00,
|
eSatipQuirkNone = 0x00,
|
||||||
eSatipQuirkSessionId = 0x01,
|
eSatipQuirkSessionId = 0x01,
|
||||||
eSatipQuirkPlayPids = 0x02,
|
eSatipQuirkMask = 0x0F
|
||||||
eSatipQuirkForceLock = 0x04,
|
|
||||||
eSatipQuirkRtpOverTcp = 0x08,
|
|
||||||
eSatipQuirkCiXpmt = 0x10,
|
|
||||||
eSatipQuirkCiTnr = 0x20,
|
|
||||||
eSatipQuirkForcePilot = 0x40,
|
|
||||||
eSatipQuirkTearAndPlay = 0x80,
|
|
||||||
eSatipQuirkMask = 0xFF
|
|
||||||
};
|
};
|
||||||
cSatipServer(const char *srcAddressP, const char *addressP, const int portP, const char *modelP, const char *filtersP, const char *descriptionP, const int quirkP);
|
enum eSatipModelType {
|
||||||
|
eSatipModelTypeNone = 0x00,
|
||||||
|
eSatipModelTypeDVBS2 = 0x01,
|
||||||
|
eSatipModelTypeDVBT = 0x02,
|
||||||
|
eSatipModelTypeDVBT2 = 0x04,
|
||||||
|
eSatipModelTypeDVBC = 0x08,
|
||||||
|
eSatipModelTypeMask = 0x0F
|
||||||
|
};
|
||||||
|
cSatipServer(const char *addressP, const char *descriptionP, const char *modelP);
|
||||||
virtual ~cSatipServer();
|
virtual ~cSatipServer();
|
||||||
virtual int Compare(const cListObject &listObjectP) const;
|
virtual int Compare(const cListObject &listObjectP) const;
|
||||||
bool Assign(int deviceIdP, int sourceP, int systemP, int transponderP);
|
void Use(bool onOffP);
|
||||||
bool Matches(int sourceP);
|
bool Used(void) { return !!useCountM; }
|
||||||
bool Matches(int deviceIdP, int sourceP, int systemP, int transponderP);
|
const char *Description() { return *descriptionM; }
|
||||||
void Attach(int deviceIdP, int transponderP);
|
const char *Address() { return *addressM; }
|
||||||
void Detach(int deviceIdP, int transponderP);
|
const char *Model(void) { return modelM; }
|
||||||
int GetModulesDVBS2(void);
|
bool Quirk(int quirkP) { return ((quirkP & eSatipQuirkMask) & quirkM); }
|
||||||
int GetModulesDVBT(void);
|
int ModelType(void) { return modelTypeM; }
|
||||||
int GetModulesDVBT2(void);
|
bool Match(int modelP) { return ((modelP & eSatipModelTypeMask) & modelTypeM); }
|
||||||
int GetModulesDVBC(void);
|
int Cable() { return Match(eSatipModelTypeDVBC) ? (Match(eSatipModelTypeDVBT2) ? modelCountM[eSatipModuleDVBT2] : modelCountM[eSatipModuleDVBT]) : 0; } // an ugly hack
|
||||||
int GetModulesDVBC2(void);
|
int Satellite() { return Match(eSatipModelTypeDVBS2) ? modelCountM[eSatipModuleDVBS2] : 0; }
|
||||||
int GetModulesATSC(void);
|
int Terrestrial() { return Match(eSatipModelTypeDVBT) ? modelCountM[eSatipModuleDVBT] : 0; }
|
||||||
void Activate(bool onOffP) { activeM = onOffP; }
|
int Terrestrial2() { return Match(eSatipModelTypeDVBT2) ? modelCountM[eSatipModuleDVBT2] : 0; }
|
||||||
const char *SrcAddress(void) { return *srcAddressM; }
|
void Update(void) { lastSeenM.Set(); }
|
||||||
const char *Address(void) { return *addressM; }
|
uint64_t LastSeen(void) { return lastSeenM.Elapsed(); }
|
||||||
const char *Model(void) { return *modelM; }
|
time_t Created(void) { return createdM; }
|
||||||
const char *Filters(void) { return *filtersM; }
|
|
||||||
const char *Description(void) { return *descriptionM; }
|
|
||||||
const char *Quirks(void) { return *quirksM; }
|
|
||||||
int Port(void) { return portM; }
|
|
||||||
bool Quirk(int quirkP) { return ((quirkP & eSatipQuirkMask) & quirkM); }
|
|
||||||
bool HasQuirk(void) { return (quirkM != eSatipQuirkNone); }
|
|
||||||
bool HasCI(void) { return hasCiM; }
|
|
||||||
bool IsActive(void) { return activeM; }
|
|
||||||
void Update(void) { lastSeenM.Set(); }
|
|
||||||
uint64_t LastSeen(void) { return lastSeenM.Elapsed(); }
|
|
||||||
time_t Created(void) { return createdM; }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// --- cSatipServers ----------------------------------------------------------
|
// --- cSatipServers ----------------------------------------------------------
|
||||||
@ -123,19 +67,11 @@ public:
|
|||||||
class cSatipServers : public cList<cSatipServer> {
|
class cSatipServers : public cList<cSatipServer> {
|
||||||
public:
|
public:
|
||||||
cSatipServer *Find(cSatipServer *serverP);
|
cSatipServer *Find(cSatipServer *serverP);
|
||||||
cSatipServer *Find(int sourceP);
|
cSatipServer *Find(int sourceP, int systemP);
|
||||||
cSatipServer *Assign(int deviceIdP, int sourceP, int transponderP, int systemP);
|
|
||||||
cSatipServer *Update(cSatipServer *serverP);
|
cSatipServer *Update(cSatipServer *serverP);
|
||||||
void Activate(cSatipServer *serverP, bool onOffP);
|
void Use(cSatipServer *serverP, bool onOffP);
|
||||||
void Attach(cSatipServer *serverP, int deviceIdP, int transponderP);
|
|
||||||
void Detach(cSatipServer *serverP, int deviceIdP, int transponderP);
|
|
||||||
bool IsQuirk(cSatipServer *serverP, int quirkP);
|
|
||||||
bool HasCI(cSatipServer *serverP);
|
|
||||||
void Cleanup(uint64_t intervalMsP = 0);
|
void Cleanup(uint64_t intervalMsP = 0);
|
||||||
cString GetAddress(cSatipServer *serverP);
|
|
||||||
cString GetSrcAddress(cSatipServer *serverP);
|
|
||||||
cString GetString(cSatipServer *serverP);
|
cString GetString(cSatipServer *serverP);
|
||||||
int GetPort(cSatipServer *serverP);
|
|
||||||
cString List(void);
|
cString List(void);
|
||||||
int NumProvidedSystems(void);
|
int NumProvidedSystems(void);
|
||||||
};
|
};
|
||||||
|
321
setup.c
321
setup.c
@ -12,103 +12,30 @@
|
|||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "device.h"
|
#include "device.h"
|
||||||
#include "discover.h"
|
#include "discover.h"
|
||||||
#include "log.h"
|
|
||||||
#include "setup.h"
|
#include "setup.h"
|
||||||
|
|
||||||
// --- cSatipEditSrcItem ------------------------------------------------------
|
|
||||||
// This class is a 99% copy of cMenuEditSrcItem() taken from VDR's menu.c
|
|
||||||
|
|
||||||
class cSatipEditSrcItem : public cMenuEditIntItem {
|
|
||||||
private:
|
|
||||||
const cSource *source;
|
|
||||||
protected:
|
|
||||||
virtual void Set(void);
|
|
||||||
public:
|
|
||||||
cSatipEditSrcItem(const char *Name, int *Value);
|
|
||||||
eOSState ProcessKey(eKeys Key);
|
|
||||||
};
|
|
||||||
|
|
||||||
cSatipEditSrcItem::cSatipEditSrcItem(const char *Name, int *Value)
|
|
||||||
:cMenuEditIntItem(Name, Value, 0)
|
|
||||||
{
|
|
||||||
source = Sources.Get(*Value);
|
|
||||||
if (!source)
|
|
||||||
source = Sources.First();
|
|
||||||
Set();
|
|
||||||
}
|
|
||||||
|
|
||||||
void cSatipEditSrcItem::Set(void)
|
|
||||||
{
|
|
||||||
if (source)
|
|
||||||
SetValue(cString::sprintf("%s - %s", *cSource::ToString(source->Code()), source->Description()));
|
|
||||||
else
|
|
||||||
cMenuEditIntItem::Set();
|
|
||||||
}
|
|
||||||
|
|
||||||
eOSState cSatipEditSrcItem::ProcessKey(eKeys Key)
|
|
||||||
{
|
|
||||||
eOSState state = cMenuEditItem::ProcessKey(Key);
|
|
||||||
|
|
||||||
if (state == osUnknown) {
|
|
||||||
bool IsRepeat = Key & k_Repeat;
|
|
||||||
Key = NORMALKEY(Key);
|
|
||||||
if (Key == kLeft) { // TODO might want to increase the delta if repeated quickly?
|
|
||||||
if (source) {
|
|
||||||
if (source->Prev())
|
|
||||||
source = (cSource *)source->Prev();
|
|
||||||
else if (!IsRepeat)
|
|
||||||
source = Sources.Last();
|
|
||||||
*value = source->Code();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (Key == kRight) {
|
|
||||||
if (source) {
|
|
||||||
if (source->Next())
|
|
||||||
source = (cSource *)source->Next();
|
|
||||||
else if (!IsRepeat)
|
|
||||||
source = Sources.First();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
source = Sources.First();
|
|
||||||
if (source)
|
|
||||||
*value = source->Code();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return state; // we don't call cMenuEditIntItem::ProcessKey(Key) here since we don't accept numerical input
|
|
||||||
Set();
|
|
||||||
state = osContinue;
|
|
||||||
}
|
|
||||||
return state;
|
|
||||||
}
|
|
||||||
|
|
||||||
// --- cSatipServerInfo -------------------------------------------------------
|
// --- cSatipServerInfo -------------------------------------------------------
|
||||||
|
|
||||||
class cSatipServerInfo : public cOsdMenu
|
class cSatipServerInfo : public cOsdMenu
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
cSatipServer *serverM;
|
|
||||||
int activeM;
|
|
||||||
cString addressM;
|
cString addressM;
|
||||||
cString modelM;
|
cString modelM;
|
||||||
cString descriptionM;
|
cString descriptionM;
|
||||||
cString ciExtensionM;
|
|
||||||
uint64_t createdM;
|
uint64_t createdM;
|
||||||
void Setup(void);
|
void Setup(void);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit cSatipServerInfo(cSatipServer *serverP);
|
cSatipServerInfo(cSatipServer *serverP);
|
||||||
virtual ~cSatipServerInfo();
|
virtual ~cSatipServerInfo();
|
||||||
virtual eOSState ProcessKey(eKeys keyP);
|
virtual eOSState ProcessKey(eKeys keyP);
|
||||||
};
|
};
|
||||||
|
|
||||||
cSatipServerInfo::cSatipServerInfo(cSatipServer *serverP)
|
cSatipServerInfo::cSatipServerInfo(cSatipServer *serverP)
|
||||||
: cOsdMenu(tr("SAT>IP Server"), 20),
|
: cOsdMenu(tr("SAT>IP Device"), 20),
|
||||||
serverM(serverP),
|
addressM(serverP ? serverP->Address() : "---"),
|
||||||
activeM(serverP && serverP->IsActive()),
|
|
||||||
addressM(serverP ? (isempty(serverP->SrcAddress()) ? serverP->Address() : *cString::sprintf("%s@%s", serverP->SrcAddress(), serverP->Address())) : "---"),
|
|
||||||
modelM(serverP ? serverP->Model() : "---"),
|
modelM(serverP ? serverP->Model() : "---"),
|
||||||
descriptionM(serverP ? serverP->Description() : "---"),
|
descriptionM(serverP ? serverP->Description() : "---"),
|
||||||
ciExtensionM(serverP && serverP->HasCI() ? trVDR("yes") : trVDR("no")),
|
|
||||||
createdM(serverP ? serverP->Created() : 0)
|
createdM(serverP ? serverP->Created() : 0)
|
||||||
{
|
{
|
||||||
SetMenuCategory(mcSetupPlugins);
|
SetMenuCategory(mcSetupPlugins);
|
||||||
@ -122,17 +49,14 @@ cSatipServerInfo::~cSatipServerInfo()
|
|||||||
|
|
||||||
void cSatipServerInfo::Setup(void)
|
void cSatipServerInfo::Setup(void)
|
||||||
{
|
{
|
||||||
Add(new cMenuEditBoolItem(trVDR("Active"), &activeM));
|
|
||||||
Add(new cOsdItem(cString::sprintf("%s:\t%s", tr("Address"), *addressM), osUnknown, false));
|
Add(new cOsdItem(cString::sprintf("%s:\t%s", tr("Address"), *addressM), osUnknown, false));
|
||||||
Add(new cOsdItem(cString::sprintf("%s:\t%s", tr("Model"), *modelM), osUnknown, false));
|
Add(new cOsdItem(cString::sprintf("%s:\t%s", tr("Model"), *modelM), osUnknown, false));
|
||||||
Add(new cOsdItem(cString::sprintf("%s:\t%s", tr("Description"), *descriptionM), osUnknown, false));
|
Add(new cOsdItem(cString::sprintf("%s:\t%s", tr("Description"), *descriptionM), osUnknown, false));
|
||||||
Add(new cOsdItem(cString::sprintf("%s:\t%s", tr("CI extension"), *ciExtensionM), osUnknown, false));
|
|
||||||
Add(new cOsdItem(cString::sprintf("%s:\t%s", tr("Creation date"), *DayDateTime(createdM)), osUnknown, false));
|
Add(new cOsdItem(cString::sprintf("%s:\t%s", tr("Creation date"), *DayDateTime(createdM)), osUnknown, false));
|
||||||
}
|
}
|
||||||
|
|
||||||
eOSState cSatipServerInfo::ProcessKey(eKeys keyP)
|
eOSState cSatipServerInfo::ProcessKey(eKeys keyP)
|
||||||
{
|
{
|
||||||
int oldActive = activeM;
|
|
||||||
eOSState state = cOsdMenu::ProcessKey(keyP);
|
eOSState state = cOsdMenu::ProcessKey(keyP);
|
||||||
|
|
||||||
if (state == osUnknown) {
|
if (state == osUnknown) {
|
||||||
@ -141,12 +65,6 @@ eOSState cSatipServerInfo::ProcessKey(eKeys keyP)
|
|||||||
default: state = osContinue; break;
|
default: state = osContinue; break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (keyP != kNone && oldActive != activeM) {
|
|
||||||
cSatipDiscover::GetInstance()->ActivateServer(serverM, activeM);
|
|
||||||
Setup();
|
|
||||||
}
|
|
||||||
|
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -157,7 +75,7 @@ private:
|
|||||||
cSatipServer *serverM;
|
cSatipServer *serverM;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit cSatipServerItem(cSatipServer *serverP);
|
cSatipServerItem(cSatipServer *serverP);
|
||||||
cSatipServer *Server(void) { return serverM; }
|
cSatipServer *Server(void) { return serverM; }
|
||||||
virtual void SetMenuItem(cSkinDisplayMenu *displayMenuP, int indexP, bool currentP, bool selectableP);
|
virtual void SetMenuItem(cSkinDisplayMenu *displayMenuP, int indexP, bool currentP, bool selectableP);
|
||||||
};
|
};
|
||||||
@ -167,7 +85,7 @@ cSatipServerItem::cSatipServerItem(cSatipServer *serverP)
|
|||||||
{
|
{
|
||||||
SetSelectable(true);
|
SetSelectable(true);
|
||||||
// Must begin with a '#' character!
|
// Must begin with a '#' character!
|
||||||
SetText(*cString::sprintf("%s %s (%s)\t%s", serverM->IsActive() ? "+" : "-", isempty(serverM->SrcAddress()) ? serverM->Address() : *cString::sprintf("%s@%s", serverM->SrcAddress(), serverM->Address()), serverM->Model(), serverM->Description()));
|
SetText(*cString::sprintf("# %s (%s)\t%s", serverM->Address(), serverM->Model(), serverM->Description()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void cSatipServerItem::SetMenuItem(cSkinDisplayMenu *displayMenuP, int indexP, bool currentP, bool selectableP)
|
void cSatipServerItem::SetMenuItem(cSkinDisplayMenu *displayMenuP, int indexP, bool currentP, bool selectableP)
|
||||||
@ -176,71 +94,6 @@ void cSatipServerItem::SetMenuItem(cSkinDisplayMenu *displayMenuP, int indexP, b
|
|||||||
displayMenuP->SetItem(Text(), indexP, currentP, selectableP);
|
displayMenuP->SetItem(Text(), indexP, currentP, selectableP);
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- cSatipMenuDeviceStatus -------------------------------------------------
|
|
||||||
|
|
||||||
class cSatipMenuDeviceStatus : public cOsdMenu
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
enum {
|
|
||||||
eInfoTimeoutMs = 15000
|
|
||||||
};
|
|
||||||
cString textM;
|
|
||||||
cTimeMs timeoutM;
|
|
||||||
void UpdateInfo();
|
|
||||||
|
|
||||||
public:
|
|
||||||
cSatipMenuDeviceStatus();
|
|
||||||
virtual ~cSatipMenuDeviceStatus();
|
|
||||||
virtual void Display(void);
|
|
||||||
virtual eOSState ProcessKey(eKeys keyP);
|
|
||||||
};
|
|
||||||
|
|
||||||
cSatipMenuDeviceStatus::cSatipMenuDeviceStatus()
|
|
||||||
: cOsdMenu(tr("SAT>IP Device Status")),
|
|
||||||
textM(""),
|
|
||||||
timeoutM()
|
|
||||||
{
|
|
||||||
SetMenuCategory(mcText);
|
|
||||||
timeoutM.Set(eInfoTimeoutMs);
|
|
||||||
UpdateInfo();
|
|
||||||
SetHelp(NULL, NULL, NULL, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
cSatipMenuDeviceStatus::~cSatipMenuDeviceStatus()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void cSatipMenuDeviceStatus::UpdateInfo()
|
|
||||||
{
|
|
||||||
textM = cSatipDevice::GetSatipStatus();
|
|
||||||
Display();
|
|
||||||
timeoutM.Set(eInfoTimeoutMs);
|
|
||||||
}
|
|
||||||
|
|
||||||
void cSatipMenuDeviceStatus::Display(void)
|
|
||||||
{
|
|
||||||
cOsdMenu::Display();
|
|
||||||
DisplayMenu()->SetText(textM, true);
|
|
||||||
if (*textM)
|
|
||||||
cStatus::MsgOsdTextItem(textM);
|
|
||||||
}
|
|
||||||
|
|
||||||
eOSState cSatipMenuDeviceStatus::ProcessKey(eKeys keyP)
|
|
||||||
{
|
|
||||||
eOSState state = cOsdMenu::ProcessKey(keyP);
|
|
||||||
|
|
||||||
if (state == osUnknown) {
|
|
||||||
switch (keyP) {
|
|
||||||
case kOk: state = osBack; break;
|
|
||||||
default: if (timeoutM.TimedOut())
|
|
||||||
UpdateInfo();
|
|
||||||
state = osContinue;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return state;
|
|
||||||
}
|
|
||||||
|
|
||||||
// --- cSatipMenuInfo ---------------------------------------------------------
|
// --- cSatipMenuInfo ---------------------------------------------------------
|
||||||
|
|
||||||
class cSatipMenuInfo : public cOsdMenu
|
class cSatipMenuInfo : public cOsdMenu
|
||||||
@ -342,32 +195,16 @@ eOSState cSatipMenuInfo::ProcessKey(eKeys keyP)
|
|||||||
// --- cSatipPluginSetup ------------------------------------------------------
|
// --- cSatipPluginSetup ------------------------------------------------------
|
||||||
|
|
||||||
cSatipPluginSetup::cSatipPluginSetup()
|
cSatipPluginSetup::cSatipPluginSetup()
|
||||||
: detachedModeM(SatipConfig.GetDetachedMode()),
|
: deviceCountM(0),
|
||||||
deviceCountM(0),
|
|
||||||
operatingModeM(SatipConfig.GetOperatingMode()),
|
operatingModeM(SatipConfig.GetOperatingMode()),
|
||||||
transportModeM(SatipConfig.GetTransportMode()),
|
|
||||||
ciExtensionM(SatipConfig.GetCIExtension()),
|
|
||||||
frontendReuseM(SatipConfig.GetFrontendReuse()),
|
|
||||||
eitScanM(SatipConfig.GetEITScan()),
|
eitScanM(SatipConfig.GetEITScan()),
|
||||||
numDisabledSourcesM(SatipConfig.GetDisabledSourcesCount()),
|
|
||||||
numDisabledFiltersM(SatipConfig.GetDisabledFiltersCount())
|
numDisabledFiltersM(SatipConfig.GetDisabledFiltersCount())
|
||||||
{
|
{
|
||||||
debug1("%s", __PRETTY_FUNCTION__);
|
debug("cSatipPluginSetup::%s()", __FUNCTION__);
|
||||||
operatingModeTextsM[cSatipConfig::eOperatingModeOff] = tr("off");
|
operatingModeTextsM[cSatipConfig::eOperatingModeOff] = tr("off");
|
||||||
operatingModeTextsM[cSatipConfig::eOperatingModeLow] = tr("low");
|
operatingModeTextsM[cSatipConfig::eOperatingModeLow] = tr("low");
|
||||||
operatingModeTextsM[cSatipConfig::eOperatingModeNormal] = tr("normal");
|
operatingModeTextsM[cSatipConfig::eOperatingModeNormal] = tr("normal");
|
||||||
operatingModeTextsM[cSatipConfig::eOperatingModeHigh] = tr("high");
|
operatingModeTextsM[cSatipConfig::eOperatingModeHigh] = tr("high");
|
||||||
transportModeTextsM[cSatipConfig::eTransportModeUnicast] = tr("Unicast");
|
|
||||||
transportModeTextsM[cSatipConfig::eTransportModeMulticast] = tr("Multicast");
|
|
||||||
transportModeTextsM[cSatipConfig::eTransportModeRtpOverTcp] = tr("RTP-over-TCP");
|
|
||||||
for (unsigned int i = 0; i < ELEMENTS(cicamsM); ++i)
|
|
||||||
cicamsM[i] = SatipConfig.GetCICAM(i);
|
|
||||||
for (unsigned int i = 0; i < ELEMENTS(ca_systems_table); ++i)
|
|
||||||
cicamTextsM[i] = ca_systems_table[i].description;
|
|
||||||
if (numDisabledSourcesM > MAX_DISABLED_SOURCES_COUNT)
|
|
||||||
numDisabledSourcesM = MAX_DISABLED_SOURCES_COUNT;
|
|
||||||
for (int i = 0; i < MAX_DISABLED_SOURCES_COUNT; ++i)
|
|
||||||
disabledSourcesM[i] = SatipConfig.GetDisabledSources(i);
|
|
||||||
if (numDisabledFiltersM > SECTION_FILTER_TABLE_SIZE)
|
if (numDisabledFiltersM > SECTION_FILTER_TABLE_SIZE)
|
||||||
numDisabledFiltersM = SECTION_FILTER_TABLE_SIZE;
|
numDisabledFiltersM = SECTION_FILTER_TABLE_SIZE;
|
||||||
for (int i = 0; i < SECTION_FILTER_TABLE_SIZE; ++i) {
|
for (int i = 0; i < SECTION_FILTER_TABLE_SIZE; ++i) {
|
||||||
@ -376,7 +213,7 @@ cSatipPluginSetup::cSatipPluginSetup()
|
|||||||
}
|
}
|
||||||
SetMenuCategory(mcSetupPlugins);
|
SetMenuCategory(mcSetupPlugins);
|
||||||
Setup();
|
Setup();
|
||||||
SetHelp(trVDR("Button$Scan"), NULL, tr("Button$Devices"), trVDR("Button$Info"));
|
SetHelp(trVDR("Button$Scan"), NULL, NULL, trVDR("Button$Info"));
|
||||||
}
|
}
|
||||||
|
|
||||||
void cSatipPluginSetup::Setup(void)
|
void cSatipPluginSetup::Setup(void)
|
||||||
@ -390,51 +227,26 @@ void cSatipPluginSetup::Setup(void)
|
|||||||
helpM.Append(tr("Define the used operating mode for all SAT>IP devices:\n\noff - devices are disabled\nlow - devices are working at the lowest priority\nnormal - devices are working within normal parameters\nhigh - devices are working at the highest priority"));
|
helpM.Append(tr("Define the used operating mode for all SAT>IP devices:\n\noff - devices are disabled\nlow - devices are working at the lowest priority\nnormal - devices are working within normal parameters\nhigh - devices are working at the highest priority"));
|
||||||
|
|
||||||
if (operatingModeM) {
|
if (operatingModeM) {
|
||||||
Add(new cMenuEditBoolItem(tr("Enable CI extension"), &ciExtensionM));
|
|
||||||
helpM.Append(tr("Define whether a CI extension shall be used.\n\nThis setting enables integrated CI/CAM handling found in some SAT>IP hardware (e.g. Digital Devices OctopusNet)."));
|
|
||||||
|
|
||||||
for (unsigned int i = 0; ciExtensionM && i < ELEMENTS(cicamsM); ++i) {
|
|
||||||
Add(new cMenuEditStraItem(*cString::sprintf(" %s #%d", tr("CI/CAM"), i + 1), &cicamsM[i], ELEMENTS(cicamTextsM), cicamTextsM));
|
|
||||||
helpM.Append(tr("Define a desired CAM type for the CI slot.\n\nThe '---' option lets SAT>IP hardware do the auto-selection."));
|
|
||||||
}
|
|
||||||
|
|
||||||
Add(new cMenuEditBoolItem(tr("Enable EPG scanning"), &eitScanM));
|
Add(new cMenuEditBoolItem(tr("Enable EPG scanning"), &eitScanM));
|
||||||
helpM.Append(tr("Define whether the EPG background scanning shall be used.\n\nThis setting disables the automatic EIT scanning functionality for all SAT>IP devices."));
|
helpM.Append(tr("Define whether the EPG background scanning shall be used.\n\nThis setting disables the automatic EIT scanning functionality for all SAT>IP devices."));
|
||||||
|
|
||||||
Add(new cMenuEditIntItem(tr("Disabled sources"), &numDisabledSourcesM, 0, MAX_DISABLED_SOURCES_COUNT, tr("none")));
|
|
||||||
helpM.Append(tr("Define number of sources to be disabled.\n\nSAT>IP servers might not have all satellite positions available and such sources can be blacklisted here."));
|
|
||||||
|
|
||||||
for (int i = 0; i < numDisabledSourcesM; ++i) {
|
|
||||||
Add(new cSatipEditSrcItem(*cString::sprintf(" %s %d", trVDR("Source"), i + 1), &disabledSourcesM[i]));
|
|
||||||
helpM.Append(tr("Define a source to be blacklisted."));
|
|
||||||
}
|
|
||||||
|
|
||||||
Add(new cMenuEditIntItem(tr("Disabled filters"), &numDisabledFiltersM, 0, SECTION_FILTER_TABLE_SIZE, tr("none")));
|
Add(new cMenuEditIntItem(tr("Disabled filters"), &numDisabledFiltersM, 0, SECTION_FILTER_TABLE_SIZE, tr("none")));
|
||||||
helpM.Append(tr("Define number of section filters to be disabled.\n\nCertain section filters might cause some unwanted behaviour to VDR such as time being falsely synchronized. By blacklisting the filters here, useful section data can be left intact for VDR to process."));
|
helpM.Append(tr("Define number of section filters to be disabled.\n\nCertain section filters might cause some unwanted behaviour to VDR such as time being falsely synchronized. By black-listing the filters here useful section data can be left intact for VDR to process."));
|
||||||
|
|
||||||
for (int i = 0; i < numDisabledFiltersM; ++i) {
|
for (int i = 0; i < numDisabledFiltersM; ++i) {
|
||||||
Add(new cMenuEditStraItem(*cString::sprintf(" %s %d", tr("Filter"), i + 1), &disabledFilterIndexesM[i], SECTION_FILTER_TABLE_SIZE, disabledFilterNamesM));
|
Add(new cMenuEditStraItem(*cString::sprintf(" %s %d", tr("Filter"), i + 1), &disabledFilterIndexesM[i], SECTION_FILTER_TABLE_SIZE, disabledFilterNamesM));
|
||||||
helpM.Append(tr("Define an ill-behaving filter to be blacklisted."));
|
helpM.Append(tr("Define an ill-behaving filter to be blacklisted."));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Add(new cMenuEditStraItem(tr("Transport mode"), &transportModeM, ELEMENTS(transportModeTextsM), transportModeTextsM));
|
Add(new cOsdItem(tr("Active SAT>IP devices:"), osUnknown, false));
|
||||||
helpM.Append(tr("Define which transport mode shall be used.\n\nUnicast, Multicast, RTP-over-TCP"));
|
|
||||||
|
|
||||||
Add(new cMenuEditBoolItem(tr("Enable frontend reuse"), &frontendReuseM));
|
|
||||||
helpM.Append(tr("Define whether reusing a frontend for multiple channels in a transponder should be enabled."));
|
|
||||||
|
|
||||||
Add(new cOsdItem(tr("Active SAT>IP servers:"), osUnknown, false));
|
|
||||||
helpM.Append("");
|
helpM.Append("");
|
||||||
|
|
||||||
detachedModeM = SatipConfig.GetDetachedMode();
|
cSatipServers *servers = cSatipDiscover::GetInstance()->GetServers();
|
||||||
if (!detachedModeM) {
|
deviceCountM = servers->Count();
|
||||||
cSatipServers *servers = cSatipDiscover::GetInstance()->GetServers();
|
for (cSatipServer *s = servers->First(); s; s = servers->Next(s)) {
|
||||||
deviceCountM = servers->Count();
|
Add(new cSatipServerItem(s));
|
||||||
for (cSatipServer *s = servers->First(); s; s = servers->Next(s)) {
|
helpM.Append("");
|
||||||
Add(new cSatipServerItem(s));
|
}
|
||||||
helpM.Append("");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SetCurrent(Get(current));
|
SetCurrent(Get(current));
|
||||||
Display();
|
Display();
|
||||||
@ -442,7 +254,7 @@ void cSatipPluginSetup::Setup(void)
|
|||||||
|
|
||||||
eOSState cSatipPluginSetup::DeviceScan(void)
|
eOSState cSatipPluginSetup::DeviceScan(void)
|
||||||
{
|
{
|
||||||
debug1("%s", __PRETTY_FUNCTION__);
|
debug("cSatipPluginSetup::%s()", __FUNCTION__);
|
||||||
cSatipDiscover::GetInstance()->TriggerScan();
|
cSatipDiscover::GetInstance()->TriggerScan();
|
||||||
|
|
||||||
return osContinue;
|
return osContinue;
|
||||||
@ -450,7 +262,7 @@ eOSState cSatipPluginSetup::DeviceScan(void)
|
|||||||
|
|
||||||
eOSState cSatipPluginSetup::DeviceInfo(void)
|
eOSState cSatipPluginSetup::DeviceInfo(void)
|
||||||
{
|
{
|
||||||
debug1("%s", __PRETTY_FUNCTION__);
|
debug("cSatipPluginSetup::%s()", __FUNCTION__);
|
||||||
if (HasSubMenu() || Count() == 0)
|
if (HasSubMenu() || Count() == 0)
|
||||||
return osContinue;
|
return osContinue;
|
||||||
|
|
||||||
@ -461,18 +273,9 @@ eOSState cSatipPluginSetup::DeviceInfo(void)
|
|||||||
return osContinue;
|
return osContinue;
|
||||||
}
|
}
|
||||||
|
|
||||||
eOSState cSatipPluginSetup::ShowDeviceStatus(void)
|
|
||||||
{
|
|
||||||
debug1("%s", __PRETTY_FUNCTION__);
|
|
||||||
if (HasSubMenu() || Count() == 0)
|
|
||||||
return osContinue;
|
|
||||||
|
|
||||||
return AddSubMenu(new cSatipMenuDeviceStatus());
|
|
||||||
}
|
|
||||||
|
|
||||||
eOSState cSatipPluginSetup::ShowInfo(void)
|
eOSState cSatipPluginSetup::ShowInfo(void)
|
||||||
{
|
{
|
||||||
debug1("%s", __PRETTY_FUNCTION__);
|
debug("cSatipPluginSetup::%s()", __FUNCTION__);
|
||||||
if (HasSubMenu() || Count() == 0)
|
if (HasSubMenu() || Count() == 0)
|
||||||
return osContinue;
|
return osContinue;
|
||||||
|
|
||||||
@ -483,36 +286,28 @@ eOSState cSatipPluginSetup::ProcessKey(eKeys keyP)
|
|||||||
{
|
{
|
||||||
bool hadSubMenu = HasSubMenu();
|
bool hadSubMenu = HasSubMenu();
|
||||||
int oldOperatingMode = operatingModeM;
|
int oldOperatingMode = operatingModeM;
|
||||||
int oldCiExtension = ciExtensionM;
|
|
||||||
int oldFrontendReuse = frontendReuseM;
|
|
||||||
int oldNumDisabledSources = numDisabledSourcesM;
|
|
||||||
int oldNumDisabledFilters = numDisabledFiltersM;
|
int oldNumDisabledFilters = numDisabledFiltersM;
|
||||||
eOSState state = cMenuSetupPage::ProcessKey(keyP);
|
eOSState state = cMenuSetupPage::ProcessKey(keyP);
|
||||||
|
|
||||||
// Ugly hack with hardcoded '+/-' characters :(
|
// Ugly hack with hardcoded '#' character :(
|
||||||
const char *p = Get(Current())->Text();
|
const char *p = Get(Current())->Text();
|
||||||
if (!hadSubMenu && !HasSubMenu() && p && (*p == '+' || *p == '-') && (keyP == kOk))
|
if (!hadSubMenu && !HasSubMenu() && (*p == '#') && (keyP == kOk))
|
||||||
return DeviceInfo();
|
return DeviceInfo();
|
||||||
if (hadSubMenu && !HasSubMenu())
|
|
||||||
Setup();
|
|
||||||
|
|
||||||
if (state == osUnknown) {
|
if (state == osUnknown) {
|
||||||
switch (keyP) {
|
switch (keyP) {
|
||||||
case kRed: return DeviceScan();
|
case kRed: return DeviceScan();
|
||||||
case kYellow: return ShowDeviceStatus();
|
case kBlue: return ShowInfo();
|
||||||
case kBlue: return ShowInfo();
|
case kInfo: if (Current() < helpM.Size())
|
||||||
case kInfo: if (Current() < helpM.Size())
|
return AddSubMenu(new cMenuText(cString::sprintf("%s - %s '%s'", tr("Help"), trVDR("Plugin"), PLUGIN_NAME_I18N), helpM[Current()]));
|
||||||
return AddSubMenu(new cMenuText(cString::sprintf("%s - %s '%s'", tr("Help"), trVDR("Plugin"), PLUGIN_NAME_I18N), helpM[Current()]));
|
default: state = osContinue; break;
|
||||||
default: state = osContinue; break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((keyP == kNone) && (cSatipDiscover::GetInstance()->GetServers()->Count() != deviceCountM))
|
if ((keyP == kNone) && (cSatipDiscover::GetInstance()->GetServers()->Count() != deviceCountM))
|
||||||
Setup();
|
Setup();
|
||||||
|
|
||||||
if ((keyP != kNone) && ((numDisabledSourcesM != oldNumDisabledSources) || (numDisabledFiltersM != oldNumDisabledFilters) || (operatingModeM != oldOperatingMode) || (ciExtensionM != oldCiExtension) || ( oldFrontendReuse != frontendReuseM) || (detachedModeM != SatipConfig.GetDetachedMode()))) {
|
if ((keyP != kNone) && ((numDisabledFiltersM != oldNumDisabledFilters) || (operatingModeM != oldOperatingMode))) {
|
||||||
while ((numDisabledSourcesM < oldNumDisabledSources) && (oldNumDisabledSources > 0))
|
|
||||||
disabledSourcesM[--oldNumDisabledSources] = cSource::stNone;
|
|
||||||
while ((numDisabledFiltersM < oldNumDisabledFilters) && (oldNumDisabledFilters > 0))
|
while ((numDisabledFiltersM < oldNumDisabledFilters) && (oldNumDisabledFilters > 0))
|
||||||
disabledFilterIndexesM[--oldNumDisabledFilters] = -1;
|
disabledFilterIndexesM[--oldNumDisabledFilters] = -1;
|
||||||
Setup();
|
Setup();
|
||||||
@ -521,74 +316,34 @@ eOSState cSatipPluginSetup::ProcessKey(eKeys keyP)
|
|||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
||||||
void cSatipPluginSetup::StoreCicams(const char *nameP, int *cicamsP)
|
|
||||||
{
|
|
||||||
cString buffer = "";
|
|
||||||
int n = 0;
|
|
||||||
for (int i = 0; i < MAX_CICAM_COUNT; ++i) {
|
|
||||||
if (cicamsP[i] < 0)
|
|
||||||
break;
|
|
||||||
if (n++ > 0)
|
|
||||||
buffer = cString::sprintf("%s %d", *buffer, cicamsP[i]);
|
|
||||||
else
|
|
||||||
buffer = cString::sprintf("%d", cicamsP[i]);
|
|
||||||
}
|
|
||||||
debug3("%s (%s, %s)", __PRETTY_FUNCTION__, nameP, *buffer);
|
|
||||||
SetupStore(nameP, *buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
void cSatipPluginSetup::StoreSources(const char *nameP, int *sourcesP)
|
|
||||||
{
|
|
||||||
cString buffer = "";
|
|
||||||
int n = 0;
|
|
||||||
for (int i = 0; i < MAX_DISABLED_SOURCES_COUNT; ++i) {
|
|
||||||
if (sourcesP[i] == cSource::stNone)
|
|
||||||
break;
|
|
||||||
if (n++ > 0)
|
|
||||||
buffer = cString::sprintf("%s %s", *buffer, *cSource::ToString(sourcesP[i]));
|
|
||||||
else
|
|
||||||
buffer = cString::sprintf("%s", *cSource::ToString(sourcesP[i]));
|
|
||||||
}
|
|
||||||
debug3("%s (%s, %s)", __PRETTY_FUNCTION__, nameP, *buffer);
|
|
||||||
SetupStore(nameP, *buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
void cSatipPluginSetup::StoreFilters(const char *nameP, int *valuesP)
|
void cSatipPluginSetup::StoreFilters(const char *nameP, int *valuesP)
|
||||||
{
|
{
|
||||||
cString buffer = "";
|
char buffer[SECTION_FILTER_TABLE_SIZE * 4];
|
||||||
int n = 0;
|
char *q = buffer;
|
||||||
for (int i = 0; i < SECTION_FILTER_TABLE_SIZE; ++i) {
|
for (int i = 0; i < SECTION_FILTER_TABLE_SIZE; ++i) {
|
||||||
|
char s[3];
|
||||||
if (valuesP[i] < 0)
|
if (valuesP[i] < 0)
|
||||||
break;
|
break;
|
||||||
if (n++ > 0)
|
if (q > buffer)
|
||||||
buffer = cString::sprintf("%s %d", *buffer, valuesP[i]);
|
*q++ = ' ';
|
||||||
else
|
snprintf(s, sizeof(s), "%d", valuesP[i]);
|
||||||
buffer = cString::sprintf("%d", valuesP[i]);
|
strncpy(q, s, strlen(s));
|
||||||
|
q += strlen(s);
|
||||||
}
|
}
|
||||||
debug3("%s (%s, %s)", __PRETTY_FUNCTION__, nameP, *buffer);
|
*q = 0;
|
||||||
SetupStore(nameP, *buffer);
|
debug("cSatipPluginSetup::%s(%s, %s)", __FUNCTION__, nameP, buffer);
|
||||||
|
SetupStore(nameP, buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void cSatipPluginSetup::Store(void)
|
void cSatipPluginSetup::Store(void)
|
||||||
{
|
{
|
||||||
// Store values into setup.conf
|
// Store values into setup.conf
|
||||||
SetupStore("OperatingMode", operatingModeM);
|
SetupStore("OperatingMode", operatingModeM);
|
||||||
SetupStore("TransportMode", transportModeM);
|
|
||||||
SetupStore("EnableCIExtension", ciExtensionM);
|
|
||||||
SetupStore("EnableFrontendReuse", frontendReuseM);
|
|
||||||
SetupStore("EnableEITScan", eitScanM);
|
SetupStore("EnableEITScan", eitScanM);
|
||||||
StoreCicams("CICAM", cicamsM);
|
|
||||||
StoreSources("DisabledSources", disabledSourcesM);
|
|
||||||
StoreFilters("DisabledFilters", disabledFilterIndexesM);
|
StoreFilters("DisabledFilters", disabledFilterIndexesM);
|
||||||
// Update global config
|
// Update global config
|
||||||
SatipConfig.SetOperatingMode(operatingModeM);
|
SatipConfig.SetOperatingMode(operatingModeM);
|
||||||
SatipConfig.SetTransportMode(transportModeM);
|
|
||||||
SatipConfig.SetCIExtension(ciExtensionM);
|
|
||||||
SatipConfig.SetEITScan(eitScanM);
|
SatipConfig.SetEITScan(eitScanM);
|
||||||
for (int i = 0; i < MAX_CICAM_COUNT; ++i)
|
|
||||||
SatipConfig.SetCICAM(i, cicamsM[i]);
|
|
||||||
for (int i = 0; i < MAX_DISABLED_SOURCES_COUNT; ++i)
|
|
||||||
SatipConfig.SetDisabledSources(i, disabledSourcesM[i]);
|
|
||||||
for (int i = 0; i < SECTION_FILTER_TABLE_SIZE; ++i)
|
for (int i = 0; i < SECTION_FILTER_TABLE_SIZE; ++i)
|
||||||
SatipConfig.SetDisabledFilters(i, disabledFilterIndexesM[i]);
|
SatipConfig.SetDisabledFilters(i, disabledFilterIndexesM[i]);
|
||||||
}
|
}
|
||||||
|
12
setup.h
12
setup.h
@ -15,19 +15,10 @@
|
|||||||
class cSatipPluginSetup : public cMenuSetupPage
|
class cSatipPluginSetup : public cMenuSetupPage
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
bool detachedModeM;
|
|
||||||
int deviceCountM;
|
int deviceCountM;
|
||||||
int operatingModeM;
|
int operatingModeM;
|
||||||
int transportModeM;
|
|
||||||
const char *operatingModeTextsM[cSatipConfig::eOperatingModeCount];
|
const char *operatingModeTextsM[cSatipConfig::eOperatingModeCount];
|
||||||
const char *transportModeTextsM[cSatipConfig::eTransportModeCount];
|
|
||||||
int ciExtensionM;
|
|
||||||
int frontendReuseM;
|
|
||||||
int cicamsM[MAX_CICAM_COUNT];
|
|
||||||
const char *cicamTextsM[CA_SYSTEMS_TABLE_SIZE];
|
|
||||||
int eitScanM;
|
int eitScanM;
|
||||||
int numDisabledSourcesM;
|
|
||||||
int disabledSourcesM[MAX_DISABLED_SOURCES_COUNT];
|
|
||||||
int numDisabledFiltersM;
|
int numDisabledFiltersM;
|
||||||
int disabledFilterIndexesM[SECTION_FILTER_TABLE_SIZE];
|
int disabledFilterIndexesM[SECTION_FILTER_TABLE_SIZE];
|
||||||
const char *disabledFilterNamesM[SECTION_FILTER_TABLE_SIZE];
|
const char *disabledFilterNamesM[SECTION_FILTER_TABLE_SIZE];
|
||||||
@ -35,11 +26,8 @@ private:
|
|||||||
|
|
||||||
eOSState DeviceScan(void);
|
eOSState DeviceScan(void);
|
||||||
eOSState DeviceInfo(void);
|
eOSState DeviceInfo(void);
|
||||||
eOSState ShowDeviceStatus(void);
|
|
||||||
eOSState ShowInfo(void);
|
eOSState ShowInfo(void);
|
||||||
void Setup(void);
|
void Setup(void);
|
||||||
void StoreCicams(const char *nameP, int *cicamsP);
|
|
||||||
void StoreSources(const char *nameP, int *sourcesP);
|
|
||||||
void StoreFilters(const char *nameP, int *valuesP);
|
void StoreFilters(const char *nameP, int *valuesP);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
347
socket.c
347
socket.c
@ -16,61 +16,31 @@
|
|||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "log.h"
|
|
||||||
#include "socket.h"
|
#include "socket.h"
|
||||||
|
|
||||||
#if defined(__GLIBC__)
|
|
||||||
#if defined(__GLIBC_PREREQ)
|
|
||||||
#if !__GLIBC_PREREQ(2,12)
|
|
||||||
#define __SATIP_DISABLE_RECVMMSG__
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
cSatipSocket::cSatipSocket()
|
cSatipSocket::cSatipSocket()
|
||||||
: socketPortM(0),
|
: socketPortM(0),
|
||||||
socketDescM(-1),
|
socketDescM(-1),
|
||||||
isMulticastM(false),
|
lastErrorReportM(0),
|
||||||
useSsmM(false),
|
packetErrorsM(0),
|
||||||
streamAddrM(htonl(INADDR_ANY)),
|
sequenceNumberM(-1)
|
||||||
sourceAddrM(htonl(INADDR_ANY)),
|
|
||||||
rcvBufSizeM(0)
|
|
||||||
{
|
{
|
||||||
debug1("%s", __PRETTY_FUNCTION__);
|
debug("cSatipSocket::%s()", __FUNCTION__);
|
||||||
memset(&sockAddrM, 0, sizeof(sockAddrM));
|
|
||||||
}
|
|
||||||
|
|
||||||
cSatipSocket::cSatipSocket(size_t rcvBufSizeP)
|
|
||||||
: socketPortM(0),
|
|
||||||
socketDescM(-1),
|
|
||||||
isMulticastM(false),
|
|
||||||
useSsmM(false),
|
|
||||||
streamAddrM(htonl(INADDR_ANY)),
|
|
||||||
sourceAddrM(htonl(INADDR_ANY)),
|
|
||||||
rcvBufSizeM(rcvBufSizeP)
|
|
||||||
{
|
|
||||||
debug1("%s", __PRETTY_FUNCTION__);
|
|
||||||
memset(&sockAddrM, 0, sizeof(sockAddrM));
|
memset(&sockAddrM, 0, sizeof(sockAddrM));
|
||||||
}
|
}
|
||||||
|
|
||||||
cSatipSocket::~cSatipSocket()
|
cSatipSocket::~cSatipSocket()
|
||||||
{
|
{
|
||||||
debug1("%s", __PRETTY_FUNCTION__);
|
debug("cSatipSocket::%s()", __FUNCTION__);
|
||||||
// Close the socket
|
// Close the socket
|
||||||
Close();
|
Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool cSatipSocket::Open(const int portP, const bool reuseP)
|
bool cSatipSocket::Open(const int portP)
|
||||||
{
|
{
|
||||||
// If socket is there already and it is bound to a different port, it must
|
debug("cSatipSocket::%s(%d)", __FUNCTION__, portP);
|
||||||
// be closed first
|
|
||||||
if (portP != socketPortM) {
|
|
||||||
debug1("%s (%d, %d) Socket tear-down", __PRETTY_FUNCTION__, portP, reuseP);
|
|
||||||
Close();
|
|
||||||
}
|
|
||||||
// Bind to the socket if it is not active already
|
// Bind to the socket if it is not active already
|
||||||
if (socketDescM < 0) {
|
if (socketDescM < 0) {
|
||||||
int yes;
|
|
||||||
socklen_t len = sizeof(sockAddrM);
|
socklen_t len = sizeof(sockAddrM);
|
||||||
// Create socket
|
// Create socket
|
||||||
socketDescM = socket(PF_INET, SOCK_DGRAM, 0);
|
socketDescM = socket(PF_INET, SOCK_DGRAM, 0);
|
||||||
@ -79,24 +49,9 @@ bool cSatipSocket::Open(const int portP, const bool reuseP)
|
|||||||
ERROR_IF_FUNC(fcntl(socketDescM, F_SETFL, O_NONBLOCK), "fcntl(O_NONBLOCK)",
|
ERROR_IF_FUNC(fcntl(socketDescM, F_SETFL, O_NONBLOCK), "fcntl(O_NONBLOCK)",
|
||||||
Close(), return false);
|
Close(), return false);
|
||||||
// Allow multiple sockets to use the same PORT number
|
// Allow multiple sockets to use the same PORT number
|
||||||
yes = reuseP;
|
int yes = 1;
|
||||||
ERROR_IF_FUNC(setsockopt(socketDescM, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) < 0,
|
ERROR_IF_FUNC(setsockopt(socketDescM, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) < 0,
|
||||||
"setsockopt(SO_REUSEADDR)", Close(), return false);
|
"setsockopt(SO_REUSEADDR)", Close(), return false);
|
||||||
yes = reuseP;
|
|
||||||
#ifdef SO_REUSEPORT
|
|
||||||
ERROR_IF_FUNC(setsockopt(socketDescM, SOL_SOCKET, SO_REUSEPORT, &yes, sizeof(yes)) < 0 && errno != ENOPROTOOPT,
|
|
||||||
"setsockopt(SO_REUSEPORT)", Close(), return false);
|
|
||||||
#endif
|
|
||||||
#ifndef __FreeBSD__
|
|
||||||
// Allow packet information to be fetched
|
|
||||||
ERROR_IF_FUNC(setsockopt(socketDescM, SOL_IP, IP_PKTINFO, &yes, sizeof(yes)) < 0,
|
|
||||||
"setsockopt(IP_PKTINFO)", Close(), return false);
|
|
||||||
#endif // __FreeBSD__
|
|
||||||
// Tweak receive buffer size if requested
|
|
||||||
if (rcvBufSizeM > 0) {
|
|
||||||
ERROR_IF_FUNC(setsockopt(socketDescM, SOL_SOCKET, SO_RCVBUF, &rcvBufSizeM, sizeof(rcvBufSizeM)) < 0,
|
|
||||||
"setsockopt(SO_RCVBUF)", Close(), return false);
|
|
||||||
}
|
|
||||||
// Bind socket
|
// Bind socket
|
||||||
memset(&sockAddrM, 0, sizeof(sockAddrM));
|
memset(&sockAddrM, 0, sizeof(sockAddrM));
|
||||||
sockAddrM.sin_family = AF_INET;
|
sockAddrM.sin_family = AF_INET;
|
||||||
@ -105,47 +60,34 @@ bool cSatipSocket::Open(const int portP, const bool reuseP)
|
|||||||
ERROR_IF_FUNC(bind(socketDescM, (struct sockaddr *)&sockAddrM, sizeof(sockAddrM)) < 0,
|
ERROR_IF_FUNC(bind(socketDescM, (struct sockaddr *)&sockAddrM, sizeof(sockAddrM)) < 0,
|
||||||
"bind()", Close(), return false);
|
"bind()", Close(), return false);
|
||||||
// Update socket port
|
// Update socket port
|
||||||
ERROR_IF_FUNC(getsockname(socketDescM, (struct sockaddr*)&sockAddrM, &len) < 0,
|
ERROR_IF_FUNC(getsockname(socketDescM,(struct sockaddr*)&sockAddrM, &len) < 0,
|
||||||
"getsockname()", Close(), return false);
|
"getsockname()", Close(), return false);
|
||||||
socketPortM = ntohs(sockAddrM.sin_port);
|
socketPortM = ntohs(sockAddrM.sin_port);
|
||||||
isMulticastM = false;
|
|
||||||
}
|
}
|
||||||
debug1("%s (%d) socketPort=%d", __PRETTY_FUNCTION__, portP, socketPortM);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool cSatipSocket::OpenMulticast(const int portP, const char *streamAddrP, const char *sourceAddrP)
|
|
||||||
{
|
|
||||||
debug1("%s (%d, %s, %s)", __PRETTY_FUNCTION__, portP, streamAddrP, sourceAddrP);
|
|
||||||
if (Open(portP)) {
|
|
||||||
CheckAddress(streamAddrP, &streamAddrM);
|
|
||||||
if (!isempty(sourceAddrP))
|
|
||||||
useSsmM = CheckAddress(sourceAddrP, &sourceAddrM);
|
|
||||||
return Join();
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void cSatipSocket::Close(void)
|
void cSatipSocket::Close(void)
|
||||||
{
|
{
|
||||||
debug1("%s socketPort=%d", __PRETTY_FUNCTION__, socketPortM);
|
debug("cSatipSocket::%s()", __FUNCTION__);
|
||||||
// Check if socket exists
|
// Check if socket exists
|
||||||
if (socketDescM >= 0) {
|
if (socketDescM >= 0) {
|
||||||
Leave();
|
|
||||||
close(socketDescM);
|
close(socketDescM);
|
||||||
socketDescM = -1;
|
socketDescM = -1;
|
||||||
socketPortM = 0;
|
socketPortM = 0;
|
||||||
|
sequenceNumberM = -1;
|
||||||
memset(&sockAddrM, 0, sizeof(sockAddrM));
|
memset(&sockAddrM, 0, sizeof(sockAddrM));
|
||||||
streamAddrM = htonl(INADDR_ANY);
|
}
|
||||||
sourceAddrM = htonl(INADDR_ANY);
|
if (packetErrorsM) {
|
||||||
isMulticastM = false;
|
info("detected %d RTP packet errors", packetErrorsM);
|
||||||
useSsmM = false;
|
packetErrorsM = 0;
|
||||||
|
lastErrorReportM = time(NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool cSatipSocket::Flush(void)
|
bool cSatipSocket::Flush(void)
|
||||||
{
|
{
|
||||||
debug1("%s", __PRETTY_FUNCTION__);
|
debug("cSatipSocket::%s()", __FUNCTION__);
|
||||||
if (socketDescM < 0) {
|
if (socketDescM < 0) {
|
||||||
const unsigned int len = 65535;
|
const unsigned int len = 65535;
|
||||||
unsigned char *buf = MALLOC(unsigned char, len);
|
unsigned char *buf = MALLOC(unsigned char, len);
|
||||||
@ -162,102 +104,12 @@ bool cSatipSocket::Flush(void)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool cSatipSocket::CheckAddress(const char *addrP, in_addr_t *inAddrP)
|
|
||||||
{
|
|
||||||
if (inAddrP) {
|
|
||||||
// First try only the IP address
|
|
||||||
*inAddrP = inet_addr(addrP);
|
|
||||||
if (*inAddrP == htonl(INADDR_NONE)) {
|
|
||||||
debug1("%s (%s, ) Cannot convert to address", __PRETTY_FUNCTION__, addrP);
|
|
||||||
// It may be a host name, get the name
|
|
||||||
struct hostent *host = gethostbyname(addrP);
|
|
||||||
if (!host) {
|
|
||||||
char tmp[64];
|
|
||||||
error("gethostbyname() failed: %s is not valid address: %s", addrP,
|
|
||||||
strerror_r(h_errno, tmp, sizeof(tmp)));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
*inAddrP = inet_addr(*host->h_addr_list);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool cSatipSocket::Join(void)
|
|
||||||
{
|
|
||||||
debug1("%s", __PRETTY_FUNCTION__);
|
|
||||||
// Check if socket exists
|
|
||||||
if (socketDescM >= 0 && !isMulticastM) {
|
|
||||||
// Join a new multicast group
|
|
||||||
if (useSsmM) {
|
|
||||||
// Source-specific multicast (SSM) is used
|
|
||||||
struct group_source_req gsr;
|
|
||||||
struct sockaddr_in *grp;
|
|
||||||
struct sockaddr_in *src;
|
|
||||||
gsr.gsr_interface = 0; // if_nametoindex("any") ?
|
|
||||||
grp = (struct sockaddr_in*)&gsr.gsr_group;
|
|
||||||
grp->sin_family = AF_INET;
|
|
||||||
grp->sin_addr.s_addr = streamAddrM;
|
|
||||||
grp->sin_port = 0;
|
|
||||||
src = (struct sockaddr_in*)&gsr.gsr_source;
|
|
||||||
src->sin_family = AF_INET;
|
|
||||||
src->sin_addr.s_addr = sourceAddrM;
|
|
||||||
src->sin_port = 0;
|
|
||||||
ERROR_IF_RET(setsockopt(socketDescM, SOL_IP, MCAST_JOIN_SOURCE_GROUP, &gsr, sizeof(gsr)) < 0, "setsockopt(MCAST_JOIN_SOURCE_GROUP)", return false);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
struct ip_mreq mreq;
|
|
||||||
mreq.imr_multiaddr.s_addr = streamAddrM;
|
|
||||||
mreq.imr_interface.s_addr = htonl(INADDR_ANY);
|
|
||||||
ERROR_IF_RET(setsockopt(socketDescM, SOL_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0, "setsockopt(IP_ADD_MEMBERSHIP)", return false);
|
|
||||||
}
|
|
||||||
// Update multicasting flag
|
|
||||||
isMulticastM = true;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool cSatipSocket::Leave(void)
|
|
||||||
{
|
|
||||||
debug1("%s", __PRETTY_FUNCTION__);
|
|
||||||
// Check if socket exists
|
|
||||||
if (socketDescM >= 0 && isMulticastM) {
|
|
||||||
// Leave the existing multicast group
|
|
||||||
if (useSsmM) {
|
|
||||||
// Source-specific multicast (SSM) is used
|
|
||||||
struct group_source_req gsr;
|
|
||||||
struct sockaddr_in *grp;
|
|
||||||
struct sockaddr_in *src;
|
|
||||||
gsr.gsr_interface = 0; // if_nametoindex("any") ?
|
|
||||||
grp = (struct sockaddr_in*)&gsr.gsr_group;
|
|
||||||
grp->sin_family = AF_INET;
|
|
||||||
grp->sin_addr.s_addr = streamAddrM;
|
|
||||||
grp->sin_port = 0;
|
|
||||||
src = (struct sockaddr_in*)&gsr.gsr_source;
|
|
||||||
src->sin_family = AF_INET;
|
|
||||||
src->sin_addr.s_addr = sourceAddrM;
|
|
||||||
src->sin_port = 0;
|
|
||||||
ERROR_IF_RET(setsockopt(socketDescM, SOL_IP, MCAST_LEAVE_SOURCE_GROUP, &gsr, sizeof(gsr)) < 0, "setsockopt(MCAST_LEAVE_SOURCE_GROUP)", return false);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
struct ip_mreq mreq;
|
|
||||||
mreq.imr_multiaddr.s_addr = streamAddrM;
|
|
||||||
mreq.imr_interface.s_addr = htonl(INADDR_ANY);
|
|
||||||
ERROR_IF_RET(setsockopt(socketDescM, SOL_IP, IP_DROP_MEMBERSHIP, &mreq, sizeof(mreq)) < 0, "setsockopt(IP_DROP_MEMBERSHIP)", return false);
|
|
||||||
}
|
|
||||||
// Update multicasting flag
|
|
||||||
isMulticastM = false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
int cSatipSocket::Read(unsigned char *bufferAddrP, unsigned int bufferLenP)
|
int cSatipSocket::Read(unsigned char *bufferAddrP, unsigned int bufferLenP)
|
||||||
{
|
{
|
||||||
debug16("%s (, %d)", __PRETTY_FUNCTION__, bufferLenP);
|
//debug("cSatipSocket::%s()", __FUNCTION__);
|
||||||
// Error out if socket not initialized
|
// Error out if socket not initialized
|
||||||
if (socketDescM <= 0) {
|
if (socketDescM <= 0) {
|
||||||
error("%s Invalid socket", __PRETTY_FUNCTION__);
|
error("Invalid socket in cSatipUdpSocket::%s()", __FUNCTION__);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
int len = 0;
|
int len = 0;
|
||||||
@ -276,86 +128,123 @@ int cSatipSocket::Read(unsigned char *bufferAddrP, unsigned int bufferLenP)
|
|||||||
msgh.msg_controllen = sizeof(cbuf);
|
msgh.msg_controllen = sizeof(cbuf);
|
||||||
msgh.msg_name = &sockAddrM;
|
msgh.msg_name = &sockAddrM;
|
||||||
msgh.msg_namelen = addrlen;
|
msgh.msg_namelen = addrlen;
|
||||||
msgh.msg_iov = &iov;
|
msgh.msg_iov = &iov;
|
||||||
msgh.msg_iovlen = 1;
|
msgh.msg_iovlen = 1;
|
||||||
msgh.msg_flags = 0;
|
msgh.msg_flags = 0;
|
||||||
|
|
||||||
if (socketDescM && bufferAddrP && (bufferLenP > 0))
|
if (socketDescM && bufferAddrP && (bufferLenP > 0))
|
||||||
len = (int)recvmsg(socketDescM, &msgh, MSG_DONTWAIT);
|
len = (int)recvmsg(socketDescM, &msgh, MSG_DONTWAIT);
|
||||||
if (len > 0) {
|
if (len > 0)
|
||||||
#ifndef __FreeBSD__
|
return len;
|
||||||
if (isMulticastM) {
|
|
||||||
// Process auxiliary received data and validate source address
|
|
||||||
for (struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msgh); cmsg != NULL; cmsg = CMSG_NXTHDR(&msgh, cmsg)) {
|
|
||||||
if ((cmsg->cmsg_level == SOL_IP) && (cmsg->cmsg_type == IP_PKTINFO)) {
|
|
||||||
struct in_pktinfo *i = (struct in_pktinfo *)CMSG_DATA(cmsg);
|
|
||||||
if ((i->ipi_addr.s_addr == streamAddrM) || (htonl(INADDR_ANY) == streamAddrM))
|
|
||||||
return len;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
#endif // __FreeBSD__
|
|
||||||
return len;
|
|
||||||
}
|
|
||||||
} while (len > 0);
|
} while (len > 0);
|
||||||
ERROR_IF_RET(len < 0 && errno != EAGAIN && errno != EWOULDBLOCK, "recvmsg()", return -1);
|
ERROR_IF_RET(len < 0 && errno != EAGAIN, "recvmsg()", return -1);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int cSatipSocket::ReadMulti(unsigned char *bufferAddrP, unsigned int *elementRecvSizeP, unsigned int elementCountP, unsigned int elementBufferSizeP)
|
int cSatipSocket::ReadVideo(unsigned char *bufferAddrP, unsigned int bufferLenP)
|
||||||
{
|
{
|
||||||
debug16("%s (, , %d, %d)", __PRETTY_FUNCTION__, elementCountP, elementBufferSizeP);
|
//debug("cSatipSocket::%s()", __FUNCTION__);
|
||||||
int count = -1;
|
int len = Read(bufferAddrP, bufferLenP);
|
||||||
// Error out if socket not initialized
|
if (len > 0) {
|
||||||
if (socketDescM <= 0) {
|
if (bufferAddrP[0] == TS_SYNC_BYTE)
|
||||||
error("%s Invalid socket", __PRETTY_FUNCTION__);
|
return len;
|
||||||
return -1;
|
else if (len > 3) {
|
||||||
}
|
// http://tools.ietf.org/html/rfc3550
|
||||||
if (!bufferAddrP || !elementRecvSizeP || !elementCountP || !elementBufferSizeP) {
|
// http://tools.ietf.org/html/rfc2250
|
||||||
error("%s Invalid parameter(s)", __PRETTY_FUNCTION__);
|
// Version
|
||||||
return -1;
|
unsigned int v = (bufferAddrP[0] >> 6) & 0x03;
|
||||||
}
|
// Extension bit
|
||||||
#ifndef __SATIP_DISABLE_RECVMMSG__
|
unsigned int x = (bufferAddrP[0] >> 4) & 0x01;
|
||||||
// Initialize iov and msgh structures
|
// CSCR count
|
||||||
struct mmsghdr mmsgh[elementCountP];
|
unsigned int cc = bufferAddrP[0] & 0x0F;
|
||||||
struct iovec iov[elementCountP];
|
// Payload type: MPEG2 TS = 33
|
||||||
memset(mmsgh, 0, sizeof(mmsgh[0]) * elementCountP);
|
//unsigned int pt = bufferAddrP[1] & 0x7F;
|
||||||
for (unsigned int i = 0; i < elementCountP; ++i) {
|
// Sequence number
|
||||||
iov[i].iov_base = bufferAddrP + i * elementBufferSizeP;
|
int seq = ((bufferAddrP[2] & 0xFF) << 8) | (bufferAddrP[3] & 0xFF);
|
||||||
iov[i].iov_len = elementBufferSizeP;
|
if ((((sequenceNumberM + 1) % 0xFFFF) == 0) && (seq == 0xFFFF))
|
||||||
mmsgh[i].msg_hdr.msg_iov = &iov[i];
|
sequenceNumberM = -1;
|
||||||
mmsgh[i].msg_hdr.msg_iovlen = 1;
|
else if ((sequenceNumberM >= 0) && (((sequenceNumberM + 1) % 0xFFFF) != seq)) {
|
||||||
}
|
packetErrorsM++;
|
||||||
|
if (time(NULL) - lastErrorReportM > eReportIntervalS) {
|
||||||
// Read data from socket as a set
|
info("detected %d RTP packet errors", packetErrorsM);
|
||||||
count = (int)recvmmsg(socketDescM, mmsgh, elementCountP, MSG_DONTWAIT, NULL);
|
packetErrorsM = 0;
|
||||||
ERROR_IF_RET(count < 0 && errno != EAGAIN && errno != EWOULDBLOCK, "recvmmsg()", return -1);
|
lastErrorReportM = time(NULL);
|
||||||
for (int i = 0; i < count; ++i)
|
}
|
||||||
elementRecvSizeP[i] = mmsgh[i].msg_len;
|
sequenceNumberM = seq;
|
||||||
#else
|
}
|
||||||
count = 0;
|
else
|
||||||
while (count < (int)elementCountP) {
|
sequenceNumberM = seq;
|
||||||
int len = Read(bufferAddrP + count * elementBufferSizeP, elementBufferSizeP);
|
// Header lenght
|
||||||
if (len < 0)
|
unsigned int headerlen = (3 + cc) * (unsigned int)sizeof(uint32_t);
|
||||||
return -1;
|
// Check if extension
|
||||||
else if (len == 0)
|
if (x) {
|
||||||
break;
|
// Extension header length
|
||||||
elementRecvSizeP[count++] = len;
|
unsigned int ehl = (((bufferAddrP[headerlen + 2] & 0xFF) << 8) |
|
||||||
|
(bufferAddrP[headerlen + 3] & 0xFF));
|
||||||
|
// Update header length
|
||||||
|
headerlen += (ehl + 1) * (unsigned int)sizeof(uint32_t);
|
||||||
|
}
|
||||||
|
// Check that rtp is version 2 and payload contains multiple of TS packet data
|
||||||
|
if ((v == 2) && (((len - headerlen) % TS_SIZE) == 0) &&
|
||||||
|
(bufferAddrP[headerlen] == TS_SYNC_BYTE)) {
|
||||||
|
// Set argument point to payload in read buffer
|
||||||
|
memmove(bufferAddrP, &bufferAddrP[headerlen], (len - headerlen));
|
||||||
|
return (len - headerlen);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
}
|
||||||
debug16("%s Received %d packets size[0]=%d", __PRETTY_FUNCTION__, count, elementRecvSizeP[0]);
|
return 0;
|
||||||
|
|
||||||
return count;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int cSatipSocket::ReadApplication(unsigned char *bufferAddrP, unsigned int bufferLenP)
|
||||||
|
{
|
||||||
|
//debug("cSatipSocket::%s()", __FUNCTION__);
|
||||||
|
int len = Read(bufferAddrP, bufferLenP);
|
||||||
|
int offset = 0;
|
||||||
|
while (len > 0) {
|
||||||
|
// Version
|
||||||
|
unsigned int v = (bufferAddrP[offset] >> 6) & 0x03;
|
||||||
|
// Padding
|
||||||
|
//unsigned int p = (bufferAddrP[offset] >> 5) & 0x01;
|
||||||
|
// Subtype
|
||||||
|
//unsigned int st = bufferAddrP[offset] & 0x1F;
|
||||||
|
// Payload type
|
||||||
|
unsigned int pt = bufferAddrP[offset + 1] & 0xFF;
|
||||||
|
// Lenght
|
||||||
|
unsigned int length = ((bufferAddrP[offset + 2] & 0xFF) << 8) | (bufferAddrP[offset + 3] & 0xFF);
|
||||||
|
// Convert it to bytes
|
||||||
|
length = (length + 1) * 4;
|
||||||
|
// V=2, APP = 204
|
||||||
|
if ((v == 2) && (pt == 204)) {
|
||||||
|
// SSCR/CSCR
|
||||||
|
//unsigned int ssrc = ((bufferAddrP[offset + 4] & 0xFF) << 24) | ((bufferAddrP[offset + 5] & 0xFF) << 16) |
|
||||||
|
// ((bufferAddrP[offset + 6] & 0xFF) << 8) | (bufferAddrP[offset + 7] & 0xFF);
|
||||||
|
// Name
|
||||||
|
if ((bufferAddrP[offset + 8] == 'S') && (bufferAddrP[offset + 9] == 'E') &&
|
||||||
|
(bufferAddrP[offset + 10] == 'S') && (bufferAddrP[offset + 11] == '1')) {
|
||||||
|
// Identifier
|
||||||
|
//unsigned int id = ((bufferAddrP[offset + 12] & 0xFF) << 8) | (bufferAddrP[offset + 13] & 0xFF);
|
||||||
|
// String length
|
||||||
|
int string_length = ((bufferAddrP[offset + 14] & 0xFF) << 8) | (bufferAddrP[offset + 15] & 0xFF);
|
||||||
|
if (string_length > 0) {
|
||||||
|
// Set argument point to payload in read buffer
|
||||||
|
memmove(bufferAddrP, &bufferAddrP[offset + 16], string_length);
|
||||||
|
return string_length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
offset += length;
|
||||||
|
len -= length;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
bool cSatipSocket::Write(const char *addrP, const unsigned char *bufferAddrP, unsigned int bufferLenP)
|
bool cSatipSocket::Write(const char *addrP, const unsigned char *bufferAddrP, unsigned int bufferLenP)
|
||||||
{
|
{
|
||||||
debug1("%s (%s, , %d)", __PRETTY_FUNCTION__, addrP, bufferLenP);
|
debug("cSatipSocket::%s(%s)", __FUNCTION__, addrP);
|
||||||
// Error out if socket not initialized
|
// Error out if socket not initialized
|
||||||
if (socketDescM <= 0) {
|
if (socketDescM <= 0) {
|
||||||
error("%s Invalid socket", __PRETTY_FUNCTION__);
|
error("cSatipSocket::%s(): Invalid socket", __FUNCTION__);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
struct sockaddr_in sockAddr;
|
struct sockaddr_in sockAddr;
|
||||||
|
28
socket.h
28
socket.h
@ -12,33 +12,27 @@
|
|||||||
|
|
||||||
class cSatipSocket {
|
class cSatipSocket {
|
||||||
private:
|
private:
|
||||||
|
enum {
|
||||||
|
eReportIntervalS = 300 // in seconds
|
||||||
|
};
|
||||||
int socketPortM;
|
int socketPortM;
|
||||||
int socketDescM;
|
int socketDescM;
|
||||||
struct sockaddr_in sockAddrM;
|
struct sockaddr_in sockAddrM;
|
||||||
bool isMulticastM;
|
time_t lastErrorReportM;
|
||||||
bool useSsmM;
|
int packetErrorsM;
|
||||||
in_addr_t streamAddrM;
|
int sequenceNumberM;
|
||||||
in_addr_t sourceAddrM;
|
|
||||||
size_t rcvBufSizeM;
|
|
||||||
|
|
||||||
bool CheckAddress(const char *addrP, in_addr_t *inAddrP);
|
|
||||||
bool Join(void);
|
|
||||||
bool Leave(void);
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
cSatipSocket();
|
cSatipSocket();
|
||||||
explicit cSatipSocket(size_t rcvBufSizeP);
|
~cSatipSocket();
|
||||||
virtual ~cSatipSocket();
|
bool Open(const int portP = 0);
|
||||||
bool Open(const int portP = 0, const bool reuseP = false);
|
void Close(void);
|
||||||
bool OpenMulticast(const int portP, const char *streamAddrP, const char *sourceAddrP);
|
|
||||||
virtual void Close(void);
|
|
||||||
int Fd(void) { return socketDescM; }
|
|
||||||
int Port(void) { return socketPortM; }
|
int Port(void) { return socketPortM; }
|
||||||
bool IsMulticast(void) { return isMulticastM; }
|
|
||||||
bool IsOpen(void) { return (socketDescM >= 0); }
|
bool IsOpen(void) { return (socketDescM >= 0); }
|
||||||
bool Flush(void);
|
bool Flush(void);
|
||||||
int Read(unsigned char *bufferAddrP, unsigned int bufferLenP);
|
int Read(unsigned char *bufferAddrP, unsigned int bufferLenP);
|
||||||
int ReadMulti(unsigned char *bufferAddrP, unsigned int *elementRecvSizeP, unsigned int elementCountP, unsigned int elementBufferSizeP);
|
int ReadVideo(unsigned char *bufferAddrP, unsigned int bufferLenP);
|
||||||
|
int ReadApplication(unsigned char *bufferAddrP, unsigned int bufferLenP);
|
||||||
bool Write(const char *addrP, const unsigned char *bufferAddrP, unsigned int bufferLenP);
|
bool Write(const char *addrP, const unsigned char *bufferAddrP, unsigned int bufferLenP);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
41
statistics.c
41
statistics.c
@ -9,7 +9,6 @@
|
|||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "statistics.h"
|
#include "statistics.h"
|
||||||
#include "log.h"
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
// Section statistics class
|
// Section statistics class
|
||||||
@ -19,17 +18,17 @@ cSatipSectionStatistics::cSatipSectionStatistics()
|
|||||||
timerM(),
|
timerM(),
|
||||||
mutexM()
|
mutexM()
|
||||||
{
|
{
|
||||||
debug16("%s", __PRETTY_FUNCTION__);
|
//debug("cSatipSectionStatistics::%s()", __FUNCTION__);
|
||||||
}
|
}
|
||||||
|
|
||||||
cSatipSectionStatistics::~cSatipSectionStatistics()
|
cSatipSectionStatistics::~cSatipSectionStatistics()
|
||||||
{
|
{
|
||||||
debug16("%s", __PRETTY_FUNCTION__);
|
//debug("cSatipSectionStatistics::%s()", __FUNCTION__);
|
||||||
}
|
}
|
||||||
|
|
||||||
cString cSatipSectionStatistics::GetSectionStatistic()
|
cString cSatipSectionStatistics::GetSectionStatistic()
|
||||||
{
|
{
|
||||||
debug16("%s", __PRETTY_FUNCTION__);
|
//debug("cSatipSectionStatistics::%s()", __FUNCTION__);
|
||||||
cMutexLock MutexLock(&mutexM);
|
cMutexLock MutexLock(&mutexM);
|
||||||
uint64_t elapsed = timerM.Elapsed(); /* in milliseconds */
|
uint64_t elapsed = timerM.Elapsed(); /* in milliseconds */
|
||||||
timerM.Set();
|
timerM.Set();
|
||||||
@ -45,7 +44,7 @@ cString cSatipSectionStatistics::GetSectionStatistic()
|
|||||||
|
|
||||||
void cSatipSectionStatistics::AddSectionStatistic(long bytesP, long callsP)
|
void cSatipSectionStatistics::AddSectionStatistic(long bytesP, long callsP)
|
||||||
{
|
{
|
||||||
debug16("%s (%ld, %ld)", __PRETTY_FUNCTION__, bytesP, callsP);
|
//debug("cSatipSectionStatistics::%s(%ld, %ld)", __FUNCTION__, bytesP, callsP);
|
||||||
cMutexLock MutexLock(&mutexM);
|
cMutexLock MutexLock(&mutexM);
|
||||||
filteredDataM += bytesP;
|
filteredDataM += bytesP;
|
||||||
numberOfCallsM += callsP;
|
numberOfCallsM += callsP;
|
||||||
@ -58,7 +57,7 @@ cSatipPidStatistics::cSatipPidStatistics()
|
|||||||
: timerM(),
|
: timerM(),
|
||||||
mutexM()
|
mutexM()
|
||||||
{
|
{
|
||||||
debug1("%s", __PRETTY_FUNCTION__);
|
debug("cSatipPidStatistics::%s()", __FUNCTION__);
|
||||||
const int numberOfElements = sizeof(mostActivePidsM) / sizeof(pidStruct);
|
const int numberOfElements = sizeof(mostActivePidsM) / sizeof(pidStruct);
|
||||||
for (int i = 0; i < numberOfElements; ++i) {
|
for (int i = 0; i < numberOfElements; ++i) {
|
||||||
mostActivePidsM[i].pid = -1;
|
mostActivePidsM[i].pid = -1;
|
||||||
@ -68,12 +67,12 @@ cSatipPidStatistics::cSatipPidStatistics()
|
|||||||
|
|
||||||
cSatipPidStatistics::~cSatipPidStatistics()
|
cSatipPidStatistics::~cSatipPidStatistics()
|
||||||
{
|
{
|
||||||
debug1("%s", __PRETTY_FUNCTION__);
|
debug("cSatipPidStatistics::%s()", __FUNCTION__);
|
||||||
}
|
}
|
||||||
|
|
||||||
cString cSatipPidStatistics::GetPidStatistic()
|
cString cSatipPidStatistics::GetPidStatistic()
|
||||||
{
|
{
|
||||||
debug16("%s", __PRETTY_FUNCTION__);
|
//debug("cSatipPidStatistics::%s()", __FUNCTION__);
|
||||||
cMutexLock MutexLock(&mutexM);
|
cMutexLock MutexLock(&mutexM);
|
||||||
const int numberOfElements = sizeof(mostActivePidsM) / sizeof(pidStruct);
|
const int numberOfElements = sizeof(mostActivePidsM) / sizeof(pidStruct);
|
||||||
uint64_t elapsed = timerM.Elapsed(); /* in milliseconds */
|
uint64_t elapsed = timerM.Elapsed(); /* in milliseconds */
|
||||||
@ -98,7 +97,7 @@ cString cSatipPidStatistics::GetPidStatistic()
|
|||||||
|
|
||||||
int cSatipPidStatistics::SortPids(const void* data1P, const void* data2P)
|
int cSatipPidStatistics::SortPids(const void* data1P, const void* data2P)
|
||||||
{
|
{
|
||||||
debug16("%s", __PRETTY_FUNCTION__);
|
//debug("cSatipPidStatistics::%s()", __FUNCTION__);
|
||||||
const pidStruct *comp1 = reinterpret_cast<const pidStruct*>(data1P);
|
const pidStruct *comp1 = reinterpret_cast<const pidStruct*>(data1P);
|
||||||
const pidStruct *comp2 = reinterpret_cast<const pidStruct*>(data2P);
|
const pidStruct *comp2 = reinterpret_cast<const pidStruct*>(data2P);
|
||||||
if (comp1->dataAmount > comp2->dataAmount)
|
if (comp1->dataAmount > comp2->dataAmount)
|
||||||
@ -110,7 +109,7 @@ int cSatipPidStatistics::SortPids(const void* data1P, const void* data2P)
|
|||||||
|
|
||||||
void cSatipPidStatistics::AddPidStatistic(int pidP, long payloadP)
|
void cSatipPidStatistics::AddPidStatistic(int pidP, long payloadP)
|
||||||
{
|
{
|
||||||
debug16("%s (%d, %ld)", __PRETTY_FUNCTION__, pidP, payloadP);
|
//debug("cSatipPidStatistics::%s(%ld, %ld)", __FUNCTION__, pidP, payloadP);
|
||||||
cMutexLock MutexLock(&mutexM);
|
cMutexLock MutexLock(&mutexM);
|
||||||
const int numberOfElements = sizeof(mostActivePidsM) / sizeof(pidStruct);
|
const int numberOfElements = sizeof(mostActivePidsM) / sizeof(pidStruct);
|
||||||
// If our statistic already is in the array, update it and quit
|
// If our statistic already is in the array, update it and quit
|
||||||
@ -140,33 +139,31 @@ cSatipTunerStatistics::cSatipTunerStatistics()
|
|||||||
timerM(),
|
timerM(),
|
||||||
mutexM()
|
mutexM()
|
||||||
{
|
{
|
||||||
debug1("%s", __PRETTY_FUNCTION__);
|
debug("cSatipTunerStatistics::%s()", __FUNCTION__);
|
||||||
}
|
}
|
||||||
|
|
||||||
cSatipTunerStatistics::~cSatipTunerStatistics()
|
cSatipTunerStatistics::~cSatipTunerStatistics()
|
||||||
{
|
{
|
||||||
debug1("%s", __PRETTY_FUNCTION__);
|
debug("cSatipTunerStatistics::%s()", __FUNCTION__);
|
||||||
}
|
}
|
||||||
|
|
||||||
cString cSatipTunerStatistics::GetTunerStatistic()
|
cString cSatipTunerStatistics::GetTunerStatistic()
|
||||||
{
|
{
|
||||||
debug16("%s", __PRETTY_FUNCTION__);
|
//debug("cSatipTunerStatistics::%s()", __FUNCTION__);
|
||||||
mutexM.Lock();
|
cMutexLock MutexLock(&mutexM);
|
||||||
uint64_t elapsed = timerM.Elapsed(); /* in milliseconds */
|
uint64_t elapsed = timerM.Elapsed(); /* in milliseconds */
|
||||||
timerM.Set();
|
timerM.Set();
|
||||||
long bitrate = elapsed ? (long)(1000.0L * dataBytesM / KILOBYTE(1) / elapsed) : 0L;
|
long bitrate = elapsed ? (long)(1000.0L * dataBytesM / KILOBYTE(1) / elapsed) : 0L;
|
||||||
dataBytesM = 0;
|
|
||||||
mutexM.Unlock();
|
|
||||||
|
|
||||||
if (!SatipConfig.GetUseBytes())
|
if (!SatipConfig.GetUseBytes())
|
||||||
bitrate *= 8;
|
bitrate *= 8;
|
||||||
cString s = cString::sprintf("%ld k%s/s", bitrate, SatipConfig.GetUseBytes() ? "B" : "bit");
|
cString s = cString::sprintf("%ld k%s/s", bitrate, SatipConfig.GetUseBytes() ? "B" : "bit");
|
||||||
|
dataBytesM = 0;
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
void cSatipTunerStatistics::AddTunerStatistic(long bytesP)
|
void cSatipTunerStatistics::AddTunerStatistic(long bytesP)
|
||||||
{
|
{
|
||||||
debug16("%s (%ld)", __PRETTY_FUNCTION__, bytesP);
|
//debug("cSatipTunerStatistics::%s(%ld)", __FUNCTION__, bytesP);
|
||||||
cMutexLock MutexLock(&mutexM);
|
cMutexLock MutexLock(&mutexM);
|
||||||
dataBytesM += bytesP;
|
dataBytesM += bytesP;
|
||||||
}
|
}
|
||||||
@ -180,17 +177,17 @@ cSatipBufferStatistics::cSatipBufferStatistics()
|
|||||||
timerM(),
|
timerM(),
|
||||||
mutexM()
|
mutexM()
|
||||||
{
|
{
|
||||||
debug1("%s", __PRETTY_FUNCTION__);
|
debug("cSatipBufferStatistics::%s()", __FUNCTION__);
|
||||||
}
|
}
|
||||||
|
|
||||||
cSatipBufferStatistics::~cSatipBufferStatistics()
|
cSatipBufferStatistics::~cSatipBufferStatistics()
|
||||||
{
|
{
|
||||||
debug1("%s", __PRETTY_FUNCTION__);
|
debug("cSatipBufferStatistics::%s()", __FUNCTION__);
|
||||||
}
|
}
|
||||||
|
|
||||||
cString cSatipBufferStatistics::GetBufferStatistic()
|
cString cSatipBufferStatistics::GetBufferStatistic()
|
||||||
{
|
{
|
||||||
debug16("%s", __PRETTY_FUNCTION__);
|
//debug("cSatipBufferStatistics::%s()", __FUNCTION__);
|
||||||
cMutexLock MutexLock(&mutexM);
|
cMutexLock MutexLock(&mutexM);
|
||||||
uint64_t elapsed = timerM.Elapsed(); /* in milliseconds */
|
uint64_t elapsed = timerM.Elapsed(); /* in milliseconds */
|
||||||
timerM.Set();
|
timerM.Set();
|
||||||
@ -214,7 +211,7 @@ cString cSatipBufferStatistics::GetBufferStatistic()
|
|||||||
|
|
||||||
void cSatipBufferStatistics::AddBufferStatistic(long bytesP, long usedP)
|
void cSatipBufferStatistics::AddBufferStatistic(long bytesP, long usedP)
|
||||||
{
|
{
|
||||||
debug16("%s (%ld, %ld)", __PRETTY_FUNCTION__, bytesP, usedP);
|
//debug("cSatipBufferStatistics::%s(%ld, %ld)", __FUNCTION__, bytesP, usedP);
|
||||||
cMutexLock MutexLock(&mutexM);
|
cMutexLock MutexLock(&mutexM);
|
||||||
dataBytesM += bytesP;
|
dataBytesM += bytesP;
|
||||||
if (usedP > usedSpaceM)
|
if (usedP > usedSpaceM)
|
||||||
|
159
tuner.h
159
tuner.h
@ -8,141 +8,69 @@
|
|||||||
#ifndef __SATIP_TUNER_H
|
#ifndef __SATIP_TUNER_H
|
||||||
#define __SATIP_TUNER_H
|
#define __SATIP_TUNER_H
|
||||||
|
|
||||||
|
#include <curl/curl.h>
|
||||||
|
#include <curl/easy.h>
|
||||||
|
|
||||||
|
#ifndef CURLOPT_RTSPHEADER
|
||||||
|
#error "libcurl is missing required RTSP support"
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <vdr/thread.h>
|
#include <vdr/thread.h>
|
||||||
#include <vdr/tools.h>
|
#include <vdr/tools.h>
|
||||||
|
|
||||||
#include "deviceif.h"
|
#include "deviceif.h"
|
||||||
#include "discover.h"
|
|
||||||
#include "rtp.h"
|
|
||||||
#include "rtcp.h"
|
|
||||||
#include "rtsp.h"
|
|
||||||
#include "server.h"
|
#include "server.h"
|
||||||
#include "statistics.h"
|
#include "statistics.h"
|
||||||
|
#include "socket.h"
|
||||||
|
|
||||||
class cSatipPid : public cVector<int> {
|
class cSatipTuner : public cThread, public cSatipTunerStatistics {
|
||||||
private:
|
|
||||||
static int PidCompare(const void *aPidP, const void *bPidP)
|
|
||||||
{
|
|
||||||
return (*(int*)aPidP - *(int*)bPidP);
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
void RemovePid(const int &pidP)
|
|
||||||
{
|
|
||||||
if (RemoveElement(pidP))
|
|
||||||
Sort(PidCompare);
|
|
||||||
}
|
|
||||||
void AddPid(int pidP)
|
|
||||||
{
|
|
||||||
if (AppendUnique(pidP))
|
|
||||||
Sort(PidCompare);
|
|
||||||
}
|
|
||||||
cString ListPids(void)
|
|
||||||
{
|
|
||||||
cString list = "";
|
|
||||||
if (Size()) {
|
|
||||||
for (int i = 0; i < Size(); ++i)
|
|
||||||
list = cString::sprintf("%s%d,", *list, At(i));
|
|
||||||
list = list.Truncate(-1);
|
|
||||||
}
|
|
||||||
return list;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class cSatipTunerServer
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
cSatipServer *serverM;
|
|
||||||
int deviceIdM;
|
|
||||||
int transponderM;
|
|
||||||
|
|
||||||
public:
|
|
||||||
cSatipTunerServer(cSatipServer *serverP, const int deviceIdP, const int transponderP) : serverM(serverP), deviceIdM(deviceIdP), transponderM(transponderP) {}
|
|
||||||
~cSatipTunerServer() {}
|
|
||||||
cSatipTunerServer(const cSatipTunerServer &objP) { serverM = NULL; deviceIdM = -1; transponderM = 0; }
|
|
||||||
cSatipTunerServer& operator= (const cSatipTunerServer &objP) { serverM = objP.serverM; deviceIdM = objP.deviceIdM; transponderM = objP.transponderM; return *this; }
|
|
||||||
bool IsValid(void) { return !!serverM; }
|
|
||||||
bool IsQuirk(int quirkP) { return (serverM && cSatipDiscover::GetInstance()->IsServerQuirk(serverM, quirkP)); }
|
|
||||||
bool HasCI(void) { return (serverM && cSatipDiscover::GetInstance()->HasServerCI(serverM)); }
|
|
||||||
void Attach(void) { if (serverM) cSatipDiscover::GetInstance()->AttachServer(serverM, deviceIdM, transponderM); }
|
|
||||||
void Detach(void) { if (serverM) cSatipDiscover::GetInstance()->DetachServer(serverM, deviceIdM, transponderM); }
|
|
||||||
void Set(cSatipServer *serverP, const int transponderP) { serverM = serverP; transponderM = transponderP; }
|
|
||||||
void Reset(void) { serverM = NULL; transponderM = 0; }
|
|
||||||
cString GetAddress(void) { return serverM ? cSatipDiscover::GetInstance()->GetServerAddress(serverM) : ""; }
|
|
||||||
cString GetSrcAddress(void) { return serverM ? cSatipDiscover::GetInstance()->GetSourceAddress(serverM) : ""; }
|
|
||||||
int GetPort(void) { return serverM ? cSatipDiscover::GetInstance()->GetServerPort(serverM) : SATIP_DEFAULT_RTSP_PORT; }
|
|
||||||
cString GetInfo(void) { return cString::sprintf("server=%s deviceid=%d transponder=%d", serverM ? "assigned" : "null", deviceIdM, transponderM); }
|
|
||||||
};
|
|
||||||
|
|
||||||
class cSatipTuner : public cThread, public cSatipTunerStatistics, public cSatipTunerIf
|
|
||||||
{
|
|
||||||
private:
|
private:
|
||||||
enum {
|
enum {
|
||||||
eDummyPid = 100,
|
eConnectTimeoutMs = 1500, // in milliseconds
|
||||||
eDefaultSignalStrengthDBm = -25,
|
ePidUpdateIntervalMs = 250, // in milliseconds
|
||||||
eDefaultSignalStrength = 224,
|
eReConnectTimeoutMs = 5000, // in milliseconds
|
||||||
eDefaultSignalQuality = 15,
|
eMinKeepAliveIntervalMs = 30000 // in milliseconds
|
||||||
eSleepTimeoutMs = 250, // in milliseconds
|
|
||||||
eStatusUpdateTimeoutMs = 1000, // in milliseconds
|
|
||||||
ePidUpdateIntervalMs = 250, // in milliseconds
|
|
||||||
eConnectTimeoutMs = 5000, // in milliseconds
|
|
||||||
eIdleCheckTimeoutMs = 15000, // in milliseconds
|
|
||||||
eTuningTimeoutMs = 20000, // in milliseconds
|
|
||||||
eMinKeepAliveIntervalMs = 30000, // in milliseconds
|
|
||||||
eKeepAlivePreBufferMs = 2000, // in milliseconds
|
|
||||||
eSetupTimeoutMs = 2000 // in milliseconds
|
|
||||||
};
|
};
|
||||||
enum eTunerState { tsIdle, tsRelease, tsSet, tsTuned, tsLocked };
|
|
||||||
enum eStateMode { smInternal, smExternal };
|
static size_t HeaderCallback(void *ptrP, size_t sizeP, size_t nmembP, void *dataP);
|
||||||
|
|
||||||
cCondWait sleepM;
|
cCondWait sleepM;
|
||||||
cSatipDeviceIf* deviceM;
|
cSatipDeviceIf* deviceM;
|
||||||
int deviceIdM;
|
unsigned char* packetBufferM;
|
||||||
cSatipRtsp rtspM;
|
unsigned int packetBufferLenM;
|
||||||
cSatipRtp rtpM;
|
cSatipSocket *rtpSocketM;
|
||||||
cSatipRtcp rtcpM;
|
cSatipSocket *rtcpSocketM;
|
||||||
cString streamAddrM;
|
cString streamAddrM;
|
||||||
cString streamParamM;
|
cString streamParamM;
|
||||||
cString lastAddrM;
|
cSatipServer *currentServerM;
|
||||||
cString lastParamM;
|
cSatipServer *nextServerM;
|
||||||
cString tnrParamM;
|
|
||||||
int streamPortM;
|
|
||||||
cSatipTunerServer currentServerM;
|
|
||||||
cSatipTunerServer nextServerM;
|
|
||||||
cMutex mutexM;
|
cMutex mutexM;
|
||||||
cTimeMs reConnectM;
|
CURL *handleM;
|
||||||
|
struct curl_slist *headerListM;
|
||||||
cTimeMs keepAliveM;
|
cTimeMs keepAliveM;
|
||||||
cTimeMs statusUpdateM;
|
cTimeMs signalInfoCacheM;
|
||||||
cTimeMs pidUpdateCacheM;
|
cTimeMs pidUpdateCacheM;
|
||||||
cTimeMs setupTimeoutM;
|
|
||||||
cString sessionM;
|
cString sessionM;
|
||||||
eTunerState currentStateM;
|
|
||||||
cVector<eTunerState> internalStateM;
|
|
||||||
cVector<eTunerState> externalStateM;
|
|
||||||
int timeoutM;
|
int timeoutM;
|
||||||
|
bool openedM;
|
||||||
|
bool tunedM;
|
||||||
bool hasLockM;
|
bool hasLockM;
|
||||||
double signalStrengthDBmM;
|
|
||||||
int signalStrengthM;
|
int signalStrengthM;
|
||||||
int signalQualityM;
|
int signalQualityM;
|
||||||
int frontendIdM;
|
|
||||||
int streamIdM;
|
int streamIdM;
|
||||||
int pmtPidM;
|
cVector<int> addPidsM;
|
||||||
cSatipPid addPidsM;
|
cVector<int> delPidsM;
|
||||||
cSatipPid delPidsM;
|
cVector<int> pidsM;
|
||||||
cSatipPid pidsM;
|
|
||||||
|
|
||||||
bool Connect(void);
|
bool Connect(void);
|
||||||
bool Disconnect(void);
|
bool Disconnect(void);
|
||||||
bool Receive(void);
|
bool ValidateLatestResponse(void);
|
||||||
bool KeepAlive(bool forceP = false);
|
void ParseReceptionParameters(const char *paramP);
|
||||||
bool ReadReceptionStatus(bool forceP = false);
|
void SetStreamId(int streamIdP);
|
||||||
|
void SetSessionTimeout(const char *sessionP, int timeoutP = 0);
|
||||||
|
bool KeepAlive(void);
|
||||||
|
bool UpdateSignalInfoCache(void);
|
||||||
bool UpdatePids(bool forceP = false);
|
bool UpdatePids(bool forceP = false);
|
||||||
void UpdateCurrentState(void);
|
|
||||||
bool StateRequested(void);
|
|
||||||
bool RequestState(eTunerState stateP, eStateMode modeP);
|
|
||||||
const char *StateModeString(eStateMode modeP);
|
|
||||||
const char *TunerStateString(eTunerState stateP);
|
|
||||||
cString GetBaseUrl(const char *addressP, const int portP);
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void Action(void);
|
virtual void Action(void);
|
||||||
@ -150,29 +78,16 @@ protected:
|
|||||||
public:
|
public:
|
||||||
cSatipTuner(cSatipDeviceIf &deviceP, unsigned int packetLenP);
|
cSatipTuner(cSatipDeviceIf &deviceP, unsigned int packetLenP);
|
||||||
virtual ~cSatipTuner();
|
virtual ~cSatipTuner();
|
||||||
bool IsTuned(void) const { return (currentStateM >= tsTuned); }
|
bool IsTuned(void) const { return tunedM; }
|
||||||
bool SetSource(cSatipServer *serverP, const int transponderP, const char *parameterP, const int indexP);
|
bool SetSource(cSatipServer *serverP, const char *parameterP, const int indexP);
|
||||||
bool SetPid(int pidP, int typeP, bool onP);
|
bool SetPid(int pidP, int typeP, bool onP);
|
||||||
bool Open(void);
|
bool Open(void);
|
||||||
bool Close(void);
|
bool Close(void);
|
||||||
int FrontendId(void);
|
|
||||||
int SignalStrength(void);
|
int SignalStrength(void);
|
||||||
double SignalStrengthDBm(void);
|
|
||||||
int SignalQuality(void);
|
int SignalQuality(void);
|
||||||
bool HasLock(void);
|
bool HasLock(void);
|
||||||
cString GetSignalStatus(void);
|
cString GetSignalStatus(void);
|
||||||
cString GetInformation(void);
|
cString GetInformation(void);
|
||||||
|
|
||||||
// for internal tuner interface
|
|
||||||
public:
|
|
||||||
virtual void ProcessVideoData(u_char *bufferP, int lengthP);
|
|
||||||
virtual void ProcessApplicationData(u_char *bufferP, int lengthP);
|
|
||||||
virtual void ProcessRtpData(u_char *bufferP, int lengthP);
|
|
||||||
virtual void ProcessRtcpData(u_char *bufferP, int lengthP);
|
|
||||||
virtual void SetStreamId(int streamIdP);
|
|
||||||
virtual void SetSessionTimeout(const char *sessionP, int timeoutP);
|
|
||||||
virtual void SetupTransport(int rtpPortP, int rtcpPortP, const char *streamAddrP, const char *sourceAddrP);
|
|
||||||
virtual int GetId(void);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // __SATIP_TUNER_H
|
#endif // __SATIP_TUNER_H
|
||||||
|
29
tunerif.h
29
tunerif.h
@ -1,29 +0,0 @@
|
|||||||
/*
|
|
||||||
* tunerif.h: SAT>IP plugin for the Video Disk Recorder
|
|
||||||
*
|
|
||||||
* See the README file for copyright information and how to reach the author.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef __SATIP_TUNERIF_H
|
|
||||||
#define __SATIP_TUNERIF_H
|
|
||||||
|
|
||||||
class cSatipTunerIf {
|
|
||||||
public:
|
|
||||||
cSatipTunerIf() {}
|
|
||||||
virtual ~cSatipTunerIf() {}
|
|
||||||
virtual void ProcessVideoData(u_char *bufferP, int lengthP) = 0;
|
|
||||||
virtual void ProcessApplicationData(u_char *bufferP, int lengthP) = 0;
|
|
||||||
virtual void ProcessRtpData(u_char *bufferP, int lengthP) = 0;
|
|
||||||
virtual void ProcessRtcpData(u_char *bufferP, int lengthP) = 0;
|
|
||||||
virtual void SetStreamId(int streamIdP) = 0;
|
|
||||||
virtual void SetSessionTimeout(const char *sessionP, int timeoutP) = 0;
|
|
||||||
virtual void SetupTransport(int rtpPortP, int rtcpPortP, const char *streamAddrP, const char *sourceAddrP) = 0;
|
|
||||||
virtual int GetId(void) = 0;
|
|
||||||
|
|
||||||
private:
|
|
||||||
explicit cSatipTunerIf(const cSatipTunerIf&);
|
|
||||||
cSatipTunerIf& operator=(const cSatipTunerIf&);
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // __SATIP_TUNERIF_H
|
|
Loading…
x
Reference in New Issue
Block a user