1
0
mirror of https://github.com/rofafor/vdr-plugin-satip.git synced 2023-10-10 11:37:42 +00:00

99 Commits

Author SHA1 Message Date
Rolf Ahrenberg
0a216f1cf9 Update HISTORY 2021-05-30 19:54:39 +03:00
Rolf Ahrenberg
02296fa8d7 Update README 2021-05-29 17:47:45 +03:00
Rolf Ahrenberg
417d4ed8fc Fix keepalive interval 2021-05-26 22:11:54 +03:00
Rolf Ahrenberg
1ad0a81d16 Update web links 2021-03-13 19:53:15 +02:00
Rolf Ahrenberg
27122747a7 Update detectsatip for Python3 2021-03-13 19:28:17 +02:00
Winfried Koehler
ba0b04ba12 HasLock(): add timeout feature (#71) 2021-03-02 21:50:43 +02:00
Rolf Ahrenberg
55362a2db6 Always retune without lock 2021-02-28 22:43:42 +02:00
Rolf Ahrenberg
0115ba1725 Use quirk to TEARDOWN before PLAY to avoid possible glitches 2021-02-28 20:36:21 +02:00
Winfried Koehler
43b60b1566 Add DeviceHooksProvidesEIT() from vdr-2.4.3+ (#68) 2021-01-31 13:41:04 +02:00
maazl
df81905821 Fix rofafor#65 RTSP streams not disconnected on error (#66)
Fix for #65 RTSP streams not disconnected on error
2020-12-28 21:01:12 +02:00
Rolf Ahrenberg
cc19cff5e9 Merge pull request #64 from madmartin/translation
Fix / extend german translation de_DE.
2020-12-27 19:44:12 +02:00
Martin Dummer
63d3c4370b Fix / extend german translation de_DE. 2020-09-26 12:50:55 +02:00
Rolf Ahrenberg
a7625c028c Make Inverto IDL-400s detection more common. 2020-02-18 19:06:53 +02:00
Rolf Ahrenberg
17c36fa9d2 Added quirks for Inverto IDL-400s. 2020-02-18 17:55:22 +02:00
Rolf Ahrenberg
826dea4ba8 Fixed a channel switching logic bug (Thanks to REELcoder). 2020-01-03 23:02:52 +02:00
Rolf Ahrenberg
a3fa5865f3 Add a preliminary ATSC support. 2020-01-03 22:05:18 +02:00
Rolf Ahrenberg
19e3057f34 Added an option to enable/disable frontend reuse. 2019-10-27 19:29:37 +02:00
Rolf Ahrenberg
b697e435d4 Fix URL parameter creation. 2019-02-09 00:01:13 +02:00
Rolf Ahrenberg
66d7aae89d Add a workaround for detecting Panasonic devices. 2019-01-06 16:18:45 +02:00
Rolf Ahrenberg
a4051bf88c Removed quirks from FRITZ!Box 6490 Cable due to new firmware. 2018-10-21 20:42:15 +03:00
Rolf Ahrenberg
98ecd22a27 Fix RTP over TCP with a nasty hack. 2018-10-21 20:22:37 +03:00
Rolf Ahrenberg
8130a4b4e5 Fix RTCP over TCP. 2018-10-21 13:35:48 +03:00
Rolf Ahrenberg
5254bb7ca2 Merge pull request #53 from mjanser/fix-uri-generation
Fix URI for x_pmt
2018-10-21 12:30:54 +03:00
Rolf Ahrenberg
6c74c10cbb Add an upper limit for pid validity according to the SAT>IP specification. 2018-10-21 12:25:15 +03:00
Martin Janser
6e6cd42c84 Fix URI for x_pmt if it's the only parameter
Fixes #52
2018-10-18 01:35:31 +02:00
Rolf Ahrenberg
299296bbb1 Updated for vdr-2.4.0. 2018-04-15 22:42:21 +03:00
Rolf Ahrenberg
43373b6951 Silence "misleading-indentation" warning. 2018-03-14 23:22:24 +02:00
Rolf Ahrenberg
0a15717245 Remove speed limit. 2018-02-13 17:22:25 +02:00
Rolf Ahrenberg
82cf5488a7 Avoid closing RTP/RTCP ports. 2018-02-06 22:54:36 +02:00
Rolf Ahrenberg
8dc4844db8 Fixed transport media change for RTCP. 2018-02-06 22:35:48 +02:00
Rolf Ahrenberg
e008ee04b2 Strip off the constructor delegation after all to broaden compiler compability. 2017-11-19 15:29:07 +02:00
Stefan Rehm
8be58070ad Added command line parameter to make the RTP receive bufferr size configurable. 2017-11-19 15:28:52 +02:00
Rolf Ahrenberg
72c3247dc2 Serialize channel switching to prevent device allocation failures. 2017-11-18 12:20:45 +02:00
Rolf Ahrenberg
dbe67a2242 Merge pull request #45 from pipelka/sectionfilter-poll-fix
Ignore handlers without any data.
2017-10-04 19:56:00 +03:00
Alexander Pipelka
f4454b0f0d Ignore handlers without any data. 2017-10-04 18:42:37 +02:00
Rolf Ahrenberg
0a9bb96dd4 Cleanup section filter code. 2017-10-01 22:34:18 +03:00
Rolf Ahrenberg
3cc63dadac Merge pull request #44 from pipelka/sectionfilter-send
Added transfer timeout for sectionfilter data.
2017-10-01 22:32:48 +03:00
Alexander Pipelka
46a197d8f8 Moved send loop one level down. 2017-09-28 10:29:41 +02:00
Alexander Pipelka
ece52576dd Changed include header. 2017-09-26 18:23:34 +02:00
Alexander Pipelka
5159508f2d Use error() to display error messages. 2017-09-25 20:48:20 +02:00
Alexander Pipelka
c4c2ba8d14 Defined section filter send timeout. 2017-09-25 20:37:57 +02:00
Alexander Pipelka
e90926d5f6 Minor coding-style fix. 2017-09-25 20:34:38 +02:00
Alexander Pipelka
27e86dd3ea Removed dead sleep code (comment) in cSatipSectionFilterHandler::Action(). 2017-09-25 20:32:51 +02:00
Alexander Pipelka
7e6b722747 Added transfer timeout for sectionfilter data. 2017-09-25 13:04:11 +02:00
Rolf Ahrenberg
97097f74af Merge pull request #43 from pipelka/sectionfilter-mem-leak
Fixed memory leak in cSatipSectionFilter
2017-09-24 23:24:42 +03:00
Alexander Pipelka
1de063ca38 Fixed memory leak in cSatipSectionFilter. 2017-09-24 22:23:08 +02:00
Rolf Ahrenberg
bf5b058725 Update HISTORY. 2017-08-15 09:22:39 +03:00
Rolf Ahrenberg
470fee436f Merge pull request #40 from CvH/gcc7
Fix GCC7 compiling
2017-08-14 19:07:52 +03:00
Sascha Kuehndel (InuSasha)
c10372bb4f fix gcc7 compiling 2017-08-14 17:17:47 +02:00
Rolf Ahrenberg
1984ec662c Fix info messages. 2017-07-31 16:18:45 +03:00
Rolf Ahrenberg
537c0ad000 Refactor the server detection script. 2017-07-31 16:18:02 +03:00
Rolf Ahrenberg
732e28d0f0 Add a server detection script. 2017-07-22 13:39:16 +03:00
Rolf Ahrenberg
3a9dc9a634 Add support for interface binding via a defined source address. 2017-07-22 13:38:54 +03:00
Rolf Ahrenberg
438f5c9254 Update quirks for FRITZ!WLAN Repeater DVB-C and FRITZ!Box 6490 Cable devices. 2017-07-18 14:13:24 +03:00
Rolf Ahrenberg
5e524a969e Update HISTORY. 2017-06-25 14:21:41 +03:00
Rolf Ahrenberg
8b1d8de468 Adapt VDR's Makefile style again. 2017-06-04 23:01:25 +03:00
Rolf Ahrenberg
12b5dac447 Adapt VDR's new Makefile style. 2017-05-25 15:11:25 +03:00
Rolf Ahrenberg
40943b8bd2 Add support for cDevice::SignalStats(). 2017-05-25 14:51:51 +03:00
Rolf Ahrenberg
e092d085b8 Merge pull request #36 from kavanu/master
Added support for Kathrein ExIP 414/E.
2017-05-17 19:03:10 +03:00
kavanu
1158141d35 added name of "KATHREIN SatIP Server" 2017-05-17 09:43:51 +02:00
Rolf Ahrenberg
c6145e1ed9 Adapt decryption for vdr-2.3.4 (Thanks to Klaus Schmidinger). 2017-04-17 22:10:29 +03:00
Rolf Ahrenberg
c5da1074f3 Merge pull request #35 from tmn505/polish_language
Add polish language
2017-02-28 21:52:35 +02:00
Tomasz Maciej Nowak
69795ec82a Add polish language 2017-02-28 16:36:50 +01:00
Rolf Ahrenberg
3cf32a64eb Remove non-compatible RTP-over-TCP devices. 2017-02-25 14:03:49 +02:00
Frank Neumann
3fd4928d75 Update Catalan and Espanol translations. 2017-02-11 19:32:18 +02:00
Rolf Ahrenberg
941a13b794 Add musl-libc compatibility. 2017-01-05 17:27:13 +02:00
Rolf Ahrenberg
20e9dc99f9 Updated HISTORY. 2016-12-18 17:25:24 +02:00
Rolf Ahrenberg
d26658a22e Prefer section pids. 2016-12-16 08:17:41 +02:00
Rolf Ahrenberg
a5d57e9390 Add a preliminary RTP-over-TCP support. 2016-12-15 23:47:30 +02:00
Frank Neumann
af64cb3011 Update German translations. 2016-12-15 08:10:48 +02:00
Rolf Ahrenberg
48862f99d3 Add a preliminary multicast support. 2016-12-14 00:37:36 +02:00
Rolf Ahrenberg
6ed729c153 Add a new ForcePilot quirk. 2016-11-10 16:47:30 +02:00
Rolf Ahrenberg
0fc044a316 Update README. 2016-11-10 16:47:10 +02:00
Rolf Ahrenberg
94b7f1132f Add command-line support for setting server quirks. 2016-10-09 18:53:40 +03:00
Rolf Ahrenberg
e7c9b04ad2 Add preliminary support for DVBViewer CI. 2016-09-11 13:08:20 +03:00
Rolf Ahrenberg
9c91e01a87 Handle Out-of-Range responses as a normal operation. 2016-09-09 19:59:12 +03:00
Rolf Ahrenberg
7a84ba78c8 Check source validity also in server assign (Thanks to Patrick Boettcher). 2016-07-31 12:00:55 +03:00
Rolf Ahrenberg
c2fe2b748d Add support for source filtering. 2016-07-30 13:42:44 +03:00
Rolf Ahrenberg
13a6b5938f Fix command-line examples to match defined quirks. 2016-07-23 17:37:07 +03:00
Rolf Ahrenberg
5db9f93a11 Fix active device check. 2016-06-23 15:36:51 +03:00
Rolf Ahrenberg
cede4743cb Add support for activating/deactivating server on-the-fly. 2016-06-22 22:49:04 +03:00
Rolf Ahrenberg
4e9b6f11eb Add support for RTP-over-TCP. 2016-06-21 23:02:46 +03:00
Rolf Ahrenberg
4b1892d754 Change EINTR handling in poller. 2016-06-05 14:19:46 +03:00
Rolf Ahrenberg
473e016152 Use 2MB ringbuffer per device. 2016-05-12 23:46:27 +03:00
Rolf Ahrenberg
793aab17d7 Set SO_REUSEPORT only if it's defined. 2016-05-07 21:43:49 +03:00
Rolf Ahrenberg
8222d05f5d Re-enable to reuse address for msearch protocol. 2016-04-11 23:02:12 +03:00
Rolf Ahrenberg
9d7c745fe1 Reset device name when the device is idling. 2016-03-19 20:33:00 +02:00
Rolf Ahrenberg
c8a5245b6c Fix statistics output a bit more. 2016-02-28 18:23:31 +02:00
Rolf Ahrenberg
ff459f426e Fix statistics output. 2016-02-28 15:32:28 +02:00
Rolf Ahrenberg
4c216d81c8 Added support for X-SATIP-RTSP-Port header. 2016-02-27 17:28:13 +02:00
Rolf Ahrenberg
23e2b4d54d Merge pull request #18 from e-tobi/master
C++11 requires a mandatory space when concatenating string literals
2016-01-30 21:43:42 +02:00
Rolf Ahrenberg
954e1be6b3 Add a missing device name update. 2016-01-30 21:41:10 +02:00
Tobias Grimm
e46340f5f3 C++11 requires a mandatory space when concatenating string literals 2016-01-23 18:38:44 +01:00
Rolf Ahrenberg
d5e9b1050e Merge pull request #16 from chriszero/master
Make it possible to specify the rtp and rtcp ports
2016-01-08 20:22:51 +02:00
chriszero
6e9b5fc414 Make it possible to specify the rtp and rtcp ports
this makes it possible to use the satip through a
NAT (e.g. a docker bridged network)
2016-01-07 21:09:39 +01:00
Rolf Ahrenberg
6e9b43b0d8 Reorder also terrestrial and cable query parameters as introduced in the satip specification 1.2.2, although the ordering shouldn't matter according to it. 2015-12-05 20:23:32 +02:00
Rolf Ahrenberg
97aba6db0f Merge pull request #14 from e-tobi/master
Reorderd the transponder URL parameter in a way the Panasonic CXW804 …
2015-12-05 20:13:50 +02:00
Tobias Grimm
660c48a9f4 Reorderd the transponder URL parameter in a way the Panasonic CXW804 expects them
(src/freq/pol/ro/msys/mtype/plts/sr/fec)

This only applies to DVB-S. DVB-C and DVB-T might need further tweaking.
It's actually a bug of the Panasonic TV to expect the transponder parameters in
a specific order in the query string, but for now this seems to be the most
pragmatic workaround.
2015-12-05 17:11:44 +01:00
Rolf Ahrenberg
67b6c9f4f7 Removed support for older version than vdr-2.3.1. 2015-09-18 18:58:07 +03:00
25 changed files with 547 additions and 226 deletions

62
HISTORY
View File

@@ -165,3 +165,65 @@ VDR Plugin 'satip' Revision History
- Added support for FRITZ!Box 6490 Cable (Thanks to 9000h). - Added support for FRITZ!Box 6490 Cable (Thanks to 9000h).
- Updated FRITZ!WLAN Repeater DVB-C detection for the latest firmware (Thanks to 9000h). - Updated FRITZ!WLAN Repeater DVB-C detection for the latest firmware (Thanks to 9000h).
- Added GCC7 compatibility (Thanks to Sascha Kuehndel). - 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.

View File

@@ -88,14 +88,15 @@ all: $(SOFILE) i18n
### Implicit rules: ### Implicit rules:
%.o: %.c %.o: %.c
$(CXX) $(CXXFLAGS) -c $(DEFINES) $(INCLUDES) -o $@ $< @echo CC $@
$(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
@$(MAKEDEP) $(CXXFLAGS) $(DEFINES) $(INCLUDES) $(OBJS:%.o=%.c) > $@ $(Q)$(MAKEDEP) $(CXXFLAGS) $(DEFINES) $(INCLUDES) $(OBJS:%.o=%.c) > $@
-include $(DEPFILE) -include $(DEPFILE)
@@ -108,17 +109,21 @@ I18Nmsgs = $(addprefix $(DESTDIR)$(LOCDIR)/, $(addsuffix /LC_MESSAGES/vdr-$(PLU
I18Npot = $(PODIR)/$(PLUGIN).pot I18Npot = $(PODIR)/$(PLUGIN).pot
%.mo: %.po %.mo: %.po
msgfmt -c -o $@ $< @echo MO $@
$(Q)msgfmt -c -o $@ $<
$(I18Npot): $(wildcard *.c) $(I18Npot): $(wildcard *.c)
xgettext -C -cTRANSLATORS --no-wrap --no-location -k -ktr -ktrNOOP --package-name=vdr-$(PLUGIN) --package-version=$(VERSION) --msgid-bugs-address='<see README>' -o $@ `ls $^` @echo GT $@
$(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)
msgmerge -U --no-wrap --no-location --backup=none -q -N $@ $< @echo PO $@
$(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
install -D -m644 $< $@ @echo IN $@
$(Q)install -D -m644 $< $@
.PHONY: i18n .PHONY: i18n
i18n: $(I18Nmo) $(I18Npot) i18n: $(I18Nmo) $(I18Npot)
@@ -128,11 +133,13 @@ install-i18n: $(I18Nmsgs)
### Targets: ### Targets:
$(SOFILE): $(OBJS) $(SOFILE): $(OBJS)
$(CXX) $(CXXFLAGS) $(LDFLAGS) -shared $(OBJS) $(LIBS) -o $@ @echo LD $@
@$(STRIP) $@ $(Q)$(CXX) $(CXXFLAGS) $(LDFLAGS) -shared $(OBJS) $(LIBS) -o $@
$(Q)$(STRIP) $@
install-lib: $(SOFILE) install-lib: $(SOFILE)
install -D $^ $(DESTDIR)$(LIBDIR)/$^.$(APIVERSION) @echo IN $(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)
@@ -153,4 +160,4 @@ clean:
.PHONY: cppcheck .PHONY: cppcheck
cppcheck: cppcheck:
@cppcheck --language=c++ --enable=all -v -f $(OBJS:%.o=%.c) $(Q)cppcheck --language=c++ --enable=all -v -f $(OBJS:%.o=%.c)

127
README
View File

@@ -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: http://www.saunalahti.fi/~rahrenbe/vdr/satip/ Project's homepage: https://github.com/rofafor/vdr-plugin-satip
Latest version available at: http://www.saunalahti.fi/~rahrenbe/vdr/satip/ Latest version available at: https://github.com/rofafor/vdr-plugin-satip/releases
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
@@ -47,12 +47,38 @@ be received, if there are available SAT>IP tuners.
The plugin accepts also a "--server" (-s) command-line parameter, that The plugin accepts also a "--server" (-s) command-line parameter, that
can be used to manually configure static SAT>IP servers if autodetection can be used to manually configure static SAT>IP servers if autodetection
via UPnP somehow can't be used. The parameter string is a semicolon via UPnP somehow can't be used. Multiple service entries can be given
separated list of "<ipaddress>|<model>|<description>" entries. The model separated by a semicolon:
consists of a DVB system (DVBS2,DVBT2,DVBT,DVBC) and number of available
frontends separated by a hyphen: [<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 [<srcaddress>@]<ipaddress>[:<port>]|<model>[:<filter>]|<description>[:<quirk>];...'
vdr -P 'satip -s 192.168.0.1|DVBS2-2,DVBT2-2|OctopusNet' 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|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' 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'
@@ -86,46 +112,50 @@ 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 - Use CI extension = no If you want to use the CI extension found
in some SAT>IP hardware (e.g. Digital in some SAT>IP hardware (e.g. Digital
Devices OctopusNet), set this option to Devices OctopusNet), set this option to
"yes". "yes".
- CICAM #<slot> = <system> If you want to assign a CA system into - CICAM #<slot> = <system> If you want to assign a CA system into
a specific CI slot, set this option to a specific CI slot, set this option to
a named one. Use "---" for autoselection. a named one. Use "---" for autoselection.
- Enable EPG scanning = yes If you want exclude all SAT>IP devices - Enable EPG scanning = yes If you want exclude all SAT>IP devices
from VDR's EIT background scanning, set from VDR's EIT background scanning, set
this option to "no". this option to "no".
- Disabled sources = none If your SAT>IP servers don't have certain - Disabled sources = none If your SAT>IP servers don't have certain
satellite positions available you can satellite positions available you can
disable them via this option. disable them via this option.
- Disabled filters = none Certain section filters might cause some - Disabled filters = none Certain section filters might cause some
unwanted behaviour to VDR such as time unwanted behaviour to VDR such as time
being falsely synchronized etc. This option being falsely synchronized etc. This option
allows creation of blacklists of ill-behaving allows creation of blacklists of ill-behaving
filters. If this option is set to a non-zero filters. If this option is set to a non-zero
value, the menu page will contain that many value, the menu page will contain that many
"Disable filter" options which allow you "Disable filter" options which allow you
to disable the individual section filters. to disable the individual section filters.
Valid range: "none" = 0 ... 7 Valid range: "none" = 0 ... 7
- Transport mode = unicast If you want to use the non-standard - Transport mode = unicast If you want to use the non-standard
multicast RTP-over-TCP transport mode, set this option multicast RTP-over-TCP transport mode, set this option
rtp-o-tcp accordingly. Otherwise, the transport rtp-o-tcp accordingly. Otherwise, the transport
mode will be RTP-over-UDP via unicast or mode will be RTP-over-UDP via unicast or
multicast. multicast.
- [Red:Scan] Forces network scanning of SAT>IP hardware. - Enable frontend reuse = yes Certain devices might have artifacts if
- [Yellow:Devices] Opens SAT>IP device status menu. multiple channels are assigned to the same
- [Blue:Info] Opens SAT>IP information/statistics menu. frontend. If you want to avoid such a
- [Ok] Opens information menu of selected SAT>IP frontend assignment, set this option to "no".
device. - [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:
@@ -159,6 +189,9 @@ Notes:
from their webpage: http://www.inverto.tv/support/ from their webpage: http://www.inverto.tv/support/
An update to a newer firmware should be offered afterwards. 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 - If you are experiencing glitches in the video stream, one possible
reason can be buffer overflows in RTP receive sockets. You can verify reason can be buffer overflows in RTP receive sockets. You can verify
this by checking "receive buffer errors" counter by running "netstat -s" this by checking "receive buffer errors" counter by running "netstat -s"

View File

@@ -15,6 +15,7 @@ cSatipConfig::cSatipConfig(void)
: operatingModeM(eOperatingModeLow), : operatingModeM(eOperatingModeLow),
traceModeM(eTraceModeNormal), traceModeM(eTraceModeNormal),
ciExtensionM(0), ciExtensionM(0),
frontendReuseM(1),
eitScanM(1), eitScanM(1),
useBytesM(1), useBytesM(1),
portRangeStartM(0), portRangeStartM(0),

View File

@@ -17,6 +17,7 @@ private:
unsigned int operatingModeM; unsigned int operatingModeM;
unsigned int traceModeM; unsigned int traceModeM;
unsigned int ciExtensionM; unsigned int ciExtensionM;
unsigned int frontendReuseM;
unsigned int eitScanM; unsigned int eitScanM;
unsigned int useBytesM; unsigned int useBytesM;
unsigned int portRangeStartM; unsigned int portRangeStartM;
@@ -74,6 +75,7 @@ public:
unsigned int GetTraceMode(void) const { return traceModeM; } unsigned int GetTraceMode(void) const { return traceModeM; }
bool IsTraceMode(eTraceMode modeP) const { return (traceModeM & modeP); } bool IsTraceMode(eTraceMode modeP) const { return (traceModeM & modeP); }
unsigned int GetCIExtension(void) const { return ciExtensionM; } unsigned int GetCIExtension(void) const { return ciExtensionM; }
unsigned int GetFrontendReuse(void) const { return frontendReuseM; }
int GetCICAM(unsigned int indexP) const; 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; }
@@ -95,6 +97,7 @@ public:
void SetOperatingMode(unsigned int operatingModeP) { operatingModeM = operatingModeP; } void SetOperatingMode(unsigned int operatingModeP) { operatingModeM = operatingModeP; }
void SetTraceMode(unsigned int modeP) { traceModeM = (modeP & eTraceModeMask); } void SetTraceMode(unsigned int modeP) { traceModeM = (modeP & eTraceModeMask); }
void SetCIExtension(unsigned int onOffP) { ciExtensionM = onOffP; } void SetCIExtension(unsigned int onOffP) { ciExtensionM = onOffP; }
void SetFrontendReuse(unsigned int onOffP) { frontendReuseM = onOffP; }
void SetCICAM(unsigned int indexP, int cicamP); 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; }

View File

@@ -1,5 +1,4 @@
#!/usr/bin/env python2 #!/usr/bin/env python3
# -*- coding: utf-8 -*-
""" Simple tool to detect SAT>IP devices as JSON. """ Simple tool to detect SAT>IP devices as JSON.
""" """
import json import json
@@ -8,21 +7,26 @@ import sys
import xml.etree.ElementTree as ET import xml.etree.ElementTree as ET
import requests import requests
SSDP_BIND = '0.0.0.0' SSDP_BIND = "0.0.0.0"
SSDP_ADDR = '239.255.255.250' SSDP_ADDR = "239.255.255.250"
SSDP_PORT = 1900 SSDP_PORT = 1900
SSDP_MX = 1 SSDP_MX = 1
SSDP_ST = 'urn:ses-com:device:SatIPServer:1' SSDP_ST = "urn:ses-com:device:SatIPServer:1"
SSDP_REQUEST = 'M-SEARCH * HTTP/1.1\r\n' + \ SSDP_REQUEST = "\r\n".join(
'HOST: %s:%d\r\n' % (SSDP_ADDR, SSDP_PORT) + \ [
'MAN: "ssdp:discover"\r\n' + \ "M-SEARCH * HTTP/1.1",
'MX: %d\r\n' % (SSDP_MX, ) + \ f"HOST: {SSDP_ADDR}:{SSDP_PORT}",
'ST: %s\r\n' % (SSDP_ST, ) + \ 'MAN: "ssdp:discover"',
'\r\n' f"MX: {SSDP_MX}",
f"ST: {SSDP_ST}",
"USER-AGENT: vdr-detectsatip",
"\r\n",
]
)
def parse_satip_xml(data): def parse_satip_xml(data):
""" Parse SAT>IP XML data. """Parse SAT>IP XML data.
Args: Args:
data (str): XML input data.. data (str): XML input data..
@@ -30,12 +34,15 @@ def parse_satip_xml(data):
Returns: Returns:
dict: Parsed SAT>IP device name and frontend information. dict: Parsed SAT>IP device name and frontend information.
""" """
result = {'name': '', 'frontends': {}} result = {"name": "", "frontends": {}}
if data: if data:
root = ET.fromstring(data) root = ET.fromstring(data)
name = root.find('.//*/{urn:schemas-upnp-org:device-1-0}friendlyName') name = root.find(".//*/{urn:schemas-upnp-org:device-1-0}friendlyName")
result['name'] = name.text result["name"] = name.text
satipcap = root.find('.//*/{urn:ses-com:satip}X_SATIPCAP') 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 = {} caps = {}
for system in satipcap.text.split(","): for system in satipcap.text.split(","):
cap = system.split("-") cap = system.split("-")
@@ -44,12 +51,12 @@ def parse_satip_xml(data):
if cap[0] in caps: if cap[0] in caps:
count = count + caps[cap[0]] count = count + caps[cap[0]]
caps[cap[0]] = count caps[cap[0]] = count
result['frontends'] = caps result["frontends"] = caps
return result return result
def detect_satip_devices(): def detect_satip_devices():
""" Detect available SAT>IP devices by sending a broadcast message. """Detect available SAT>IP devices by sending a broadcast message.
Returns: Returns:
list: Found SAT>IP devices. list: Found SAT>IP devices.
@@ -66,14 +73,14 @@ def detect_satip_devices():
pass pass
sock.settimeout(1) sock.settimeout(1)
sock.bind((SSDP_BIND, SSDP_PORT)) sock.bind((SSDP_BIND, SSDP_PORT))
sock.sendto(SSDP_REQUEST, (SSDP_ADDR, SSDP_PORT)) sock.sendto(SSDP_REQUEST.encode("utf-8"), (SSDP_ADDR, SSDP_PORT))
try: try:
while 1: while 1:
data = sock.recv(1024) data = sock.recv(1024).decode("utf-8")
if data: if data:
for row in data.split('\r\n'): for row in data.split("\r\n"):
if 'LOCATION:' in row: if "LOCATION:" in row:
url = row.replace('LOCATION:', '').strip() url = row.replace("LOCATION:", "").strip()
if url in urls: if url in urls:
continue continue
urls.append(url) urls.append(url)
@@ -87,5 +94,5 @@ def detect_satip_devices():
return devices return devices
if __name__ == '__main__': if __name__ == "__main__":
json.dump(detect_satip_devices(), fp=sys.stdout, sort_keys=True, indent=2) json.dump(detect_satip_devices(), fp=sys.stdout, sort_keys=True, indent=2)

View File

@@ -19,8 +19,9 @@ cMutex cSatipDevice::mutexS = cMutex();
cSatipDevice::cSatipDevice(unsigned int indexP) cSatipDevice::cSatipDevice(unsigned int indexP)
: deviceIndexM(indexP), : deviceIndexM(indexP),
isPacketDeliveredM(false), bytesDeliveredM(0),
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),
@@ -107,12 +108,8 @@ cString cSatipDevice::GetSatipStatus(void)
bool live = (device == cDevice::ActualDevice()); bool live = (device == cDevice::ActualDevice());
bool lock = device->HasLock(); bool lock = device->HasLock();
const cChannel *channel = device->GetCurrentlyTunedTransponder(); const cChannel *channel = device->GetCurrentlyTunedTransponder();
#if defined(APIVERSNUM) && APIVERSNUM >= 20301
LOCK_TIMERS_READ; LOCK_TIMERS_READ;
for (const cTimer *timer = Timers->First(); timer; timer = Timers->Next(timer)) { for (const cTimer *timer = Timers->First(); timer; timer = Timers->Next(timer)) {
#else
for (cTimer *timer = Timers.First(); timer; timer = Timers.Next(timer)) {
#endif
if (timer->Recording()) { if (timer->Recording()) {
cRecordControl *control = cRecordControls::GetRecordControl(timer); cRecordControl *control = cRecordControls::GetRecordControl(timer);
if (control && control->Device() == device) if (control && control->Device() == device)
@@ -141,20 +138,14 @@ cString cSatipDevice::GetSatipStatus(void)
cString cSatipDevice::GetGeneralInformation(void) cString cSatipDevice::GetGeneralInformation(void)
{ {
debug16("%s [device %u]", __PRETTY_FUNCTION__, deviceIndexM); debug16("%s [device %u]", __PRETTY_FUNCTION__, deviceIndexM);
#if defined(APIVERSNUM) && APIVERSNUM >= 20301
LOCK_CHANNELS_READ; LOCK_CHANNELS_READ;
#endif
return cString::sprintf("SAT>IP device: %d\nCardIndex: %d\nStream: %s\nSignal: %s\nStream bitrate: %s\n%sChannel: %s\n", 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(),
#if defined(APIVERSNUM) && APIVERSNUM >= 20301
*Channels->GetByNumber(cDevice::CurrentChannel())->ToText()); *Channels->GetByNumber(cDevice::CurrentChannel())->ToText());
#else
*Channels.GetByNumber(cDevice::CurrentChannel())->ToText());
#endif
} }
cString cSatipDevice::GetPidsInformation(void) cString cSatipDevice::GetPidsInformation(void)
@@ -225,6 +216,21 @@ bool cSatipDevice::AvoidRecording(void) const
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); debug16("%s [device %u]", __PRETTY_FUNCTION__, deviceIndexM);
@@ -289,10 +295,10 @@ bool cSatipDevice::ProvidesChannel(const cChannel *channelP, int priorityP, bool
result = true; result = true;
} }
else else
result = true; result = !!SatipConfig.GetFrontendReuse();
} }
else else
needsDetachReceivers = Receiving(); needsDetachReceivers = true;
} }
} }
} }
@@ -303,7 +309,11 @@ 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
@@ -384,7 +394,7 @@ void cSatipDevice::SetChannelTuned(void)
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); debug12("%s (%d, %d, %d) [device %u]", __PRETTY_FUNCTION__, handleP ? handleP->pid : -1, typeP, onP, deviceIndexM);
if (pTunerM && handleP && handleP->pid >= 0) { if (pTunerM && handleP && handleP->pid >= 0 && handleP->pid <= 8191) {
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 && pSectionFilterHandlerM && !pSectionFilterHandlerM->Exists(handleP->pid))
@@ -419,7 +429,7 @@ void cSatipDevice::CloseFilter(int handleP)
bool cSatipDevice::OpenDvr(void) bool cSatipDevice::OpenDvr(void)
{ {
debug9("%s [device %u]", __PRETTY_FUNCTION__, deviceIndexM); debug9("%s [device %u]", __PRETTY_FUNCTION__, deviceIndexM);
isPacketDeliveredM = false; bytesDeliveredM = 0;
tsBufferM->Clear(); tsBufferM->Clear();
if (pTunerM) if (pTunerM)
pTunerM->Open(); pTunerM->Open();
@@ -438,6 +448,14 @@ 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); debug16("%s (%d) [device %d]", __PRETTY_FUNCTION__, timeoutMsP, deviceIndexM);
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());
} }
@@ -505,13 +523,17 @@ bool cSatipDevice::IsIdle(void)
return !Receiving(); return !Receiving();
} }
uchar *cSatipDevice::GetData(int *availableP) uchar *cSatipDevice::GetData(int *availableP, bool checkTsBuffer)
{ {
debug16("%s [device %u]", __PRETTY_FUNCTION__, deviceIndexM); debug16("%s [device %u]", __PRETTY_FUNCTION__, deviceIndexM);
if (isOpenDvrM && tsBufferM) { if (isOpenDvrM && tsBufferM) {
int count = 0; int count = 0;
if (isPacketDeliveredM) if (bytesDeliveredM) {
SkipData(TS_SIZE); tsBufferM->Del(bytesDeliveredM);
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) {
@@ -525,7 +547,7 @@ uchar *cSatipDevice::GetData(int *availableP)
info("Skipped %d bytes to sync on TS packet", count); info("Skipped %d bytes to sync on TS packet", count);
return NULL; return NULL;
} }
isPacketDeliveredM = true; bytesDeliveredM = TS_SIZE;
if (availableP) if (availableP)
*availableP = count; *availableP = count;
// Update pid statistics // Update pid statistics
@@ -539,8 +561,7 @@ uchar *cSatipDevice::GetData(int *availableP)
void cSatipDevice::SkipData(int countP) void cSatipDevice::SkipData(int countP)
{ {
debug16("%s [device %u]", __PRETTY_FUNCTION__, deviceIndexM); debug16("%s [device %u]", __PRETTY_FUNCTION__, deviceIndexM);
tsBufferM->Del(countP); bytesDeliveredM = countP;
isPacketDeliveredM = false;
// Update buffer statistics // Update buffer statistics
AddBufferStatistic(countP, tsBufferM->Available()); AddBufferStatistic(countP, tsBufferM->Available());
} }
@@ -554,11 +575,12 @@ bool cSatipDevice::GetTSPacket(uchar *&dataP)
if (cCamSlot *cs = CamSlot()) { if (cCamSlot *cs = CamSlot()) {
if (cs->WantsTsData()) { if (cs->WantsTsData()) {
int available; int available;
dataP = GetData(&available); dataP = GetData(&available, checkTsBufferM);
if (dataP) { if (!dataP)
dataP = cs->Decrypt(dataP, available); available = 0;
SkipData(available); dataP = cs->Decrypt(dataP, available);
} SkipData(available);
checkTsBufferM = dataP != NULL;
return true; return true;
} }
} }

View File

@@ -32,8 +32,9 @@ private:
eTuningTimeoutMs = 1000 // in milliseconds eTuningTimeoutMs = 1000 // in milliseconds
}; };
unsigned int deviceIndexM; unsigned int deviceIndexM;
bool isPacketDeliveredM; int bytesDeliveredM;
bool isOpenDvrM; bool isOpenDvrM;
bool checkTsBufferM;
cString deviceNameM; cString deviceNameM;
cChannel channelM; cChannel channelM;
cRingBufferLinear *tsBufferM; cRingBufferLinear *tsBufferM;
@@ -64,6 +65,7 @@ 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;
@@ -83,7 +85,7 @@ protected:
// for recording // for recording
private: private:
uchar *GetData(int *availableP = NULL); uchar *GetData(int *availableP = NULL, bool checkTsBuffer = false);
void SkipData(int countP); void SkipData(int countP);
protected: protected:
@@ -99,7 +101,7 @@ public:
// for transponder lock // for transponder lock
public: public:
virtual bool HasLock(int timeoutMsP) const; virtual bool HasLock(int timeoutMsP = 0) const;
// for common interface // for common interface
public: public:

62
param.c
View File

@@ -59,6 +59,10 @@ static const tSatipParameterMap SatipCodeRateValues[] = {
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" },
@@ -85,6 +89,11 @@ static const tSatipParameterMap SatipSystemValuesCable[] = {
{ -1, NULL } { -1, NULL }
}; };
static const tSatipParameterMap SatipSystemValuesAtsc[] = {
{ 0, "&msys=atsc" },
{ -1, NULL }
};
static const tSatipParameterMap SatipTransmissionValues[] = { static const tSatipParameterMap SatipTransmissionValues[] = {
{ TRANSMISSION_MODE_1K, "&tmode=1k" }, { TRANSMISSION_MODE_1K, "&tmode=1k" },
{ TRANSMISSION_MODE_2K, "&tmode=2k" }, { TRANSMISSION_MODE_2K, "&tmode=2k" },
@@ -165,33 +174,36 @@ cString GetTransponderUrlParameters(const cChannel *channelP)
} }
if ((channelP->Rid() % 100) > 0) if ((channelP->Rid() % 100) > 0)
q += snprintf(q, STBUFLEFT, "&fe=%d", channelP->Rid() % 100); q += snprintf(q, STBUFLEFT, "&fe=%d", channelP->Rid() % 100);
ST(" S *") q += snprintf(q, STBUFLEFT, "src=%d&", ((src > 0) && (src <= 255)) ? src : 1); ST(" S *") q += snprintf(q, STBUFLEFT, "&src=%d", ((src > 0) && (src <= 255)) ? src : 1);
if (freq >= 0L) if (freq >= 0L)
q += snprintf(q, STBUFLEFT, "freq=%s", *dtoa(freq, "%lg")); q += snprintf(q, STBUFLEFT, "&freq=%s", *dtoa(freq, "%lg"));
ST(" S *") q += snprintf(q, STBUFLEFT, "&pol=%c", tolower(dtp.Polarization())); ST(" S *") q += snprintf(q, STBUFLEFT, "&pol=%c", tolower(dtp.Polarization()));
ST(" S *") q += PrintUrlString(q, STBUFLEFT, dtp.RollOff(), SatipRollOffValues); ST(" S *") q += PrintUrlString(q, STBUFLEFT, dtp.RollOff(), SatipRollOffValues);
ST("C 2") q += snprintf(q, STBUFLEFT, "&c2tft=%d", C2TuningFrequencyType); ST(" C 2") q += snprintf(q, STBUFLEFT, "&c2tft=%d", C2TuningFrequencyType);
ST(" T*") q += PrintUrlString(q, STBUFLEFT, dtp.Bandwidth(), SatipBandwidthValues); ST(" T*") q += PrintUrlString(q, STBUFLEFT, dtp.Bandwidth(), SatipBandwidthValues);
ST("C 2") q += PrintUrlString(q, STBUFLEFT, dtp.Bandwidth(), SatipBandwidthValues); 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(" S *") q += PrintUrlString(q, STBUFLEFT, dtp.Modulation(), SatipModulationValues); ST(" T*") q += PrintUrlString(q, STBUFLEFT, dtp.Transmission(), SatipTransmissionValues);
ST(" T*") q += PrintUrlString(q, STBUFLEFT, dtp.Modulation(), SatipModulationValues); ST(" S *") q += PrintUrlString(q, STBUFLEFT, dtp.Modulation(), SatipModulationValues);
ST("C 1") q += PrintUrlString(q, STBUFLEFT, dtp.Modulation(), SatipModulationValues); ST(" T*") q += PrintUrlString(q, STBUFLEFT, dtp.Modulation(), SatipModulationValues);
ST(" S *") q += PrintUrlString(q, STBUFLEFT, dtp.Pilot(), SatipPilotValues); ST(" C 1") q += PrintUrlString(q, STBUFLEFT, dtp.Modulation(), SatipModulationValues);
ST(" S *") q += snprintf(q, STBUFLEFT, "&sr=%d", channelP->Srate()); ST("A *") q += PrintUrlString(q, STBUFLEFT, dtp.Modulation(), SatipModulationValues);
ST("C 1") q += snprintf(q, STBUFLEFT, "&sr=%d", channelP->Srate()); ST(" S *") q += PrintUrlString(q, STBUFLEFT, dtp.Pilot(), SatipPilotValues);
ST(" T*") q += PrintUrlString(q, STBUFLEFT, dtp.Guard(), SatipGuardValues); ST(" S *") q += snprintf(q, STBUFLEFT, "&sr=%d", channelP->Srate());
ST("CST*") q += PrintUrlString(q, STBUFLEFT, dtp.CoderateH(), SatipCodeRateValues); ST(" C 1") q += snprintf(q, STBUFLEFT, "&sr=%d", channelP->Srate());
ST("C 2") q += snprintf(q, STBUFLEFT, "&ds=%d", DataSlice); ST(" T*") q += PrintUrlString(q, STBUFLEFT, dtp.Guard(), SatipGuardValues);
ST("C T2") q += snprintf(q, STBUFLEFT, "&plp=%d", dtp.StreamId()); ST(" CST*") q += PrintUrlString(q, STBUFLEFT, dtp.CoderateH(), SatipCodeRateValues);
ST(" T2") q += snprintf(q, STBUFLEFT, "&t2id=%d", dtp.T2SystemId()); ST(" C 2") q += snprintf(q, STBUFLEFT, "&ds=%d", DataSlice);
ST(" T2") q += PrintUrlString(q, STBUFLEFT, dtp.SisoMiso(), SatipSisoMisoValues); ST(" C T2") q += snprintf(q, STBUFLEFT, "&plp=%d", dtp.StreamId());
ST("C 1") q += PrintUrlString(q, STBUFLEFT, dtp.Inversion(), SatipInversionValues); 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; return &buffer[1];
} }
return NULL; return NULL;
} }

View File

@@ -1,14 +1,14 @@
# VDR plugin language source file. # VDR plugin language source file.
# Copyright (C) 2007-2017 Rolf Ahrenberg # Copyright (C) 2007-2019 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-2017
# #
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: vdr-satip 2.2.5\n" "Project-Id-Version: vdr-satip 2.4.0\n"
"Report-Msgid-Bugs-To: <see README>\n" "Report-Msgid-Bugs-To: <see README>\n"
"POT-Creation-Date: 2017-08-15 08:15+0300\n" "POT-Creation-Date: 2019-10-27 19:12+0200\n"
"PO-Revision-Date: 2017-08-15 08:15+0300\n" "PO-Revision-Date: 2019-10-27 10:27+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"
@@ -196,6 +196,12 @@ msgid ""
"Unicast, Multicast, RTP-over-TCP" "Unicast, Multicast, RTP-over-TCP"
msgstr "" 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:" msgid "Active SAT>IP servers:"
msgstr "Activa SAT>IP servers:" msgstr "Activa SAT>IP servers:"

View File

@@ -1,14 +1,14 @@
# VDR plugin language source file. # VDR plugin language source file.
# Copyright (C) 2007-2017 Rolf Ahrenberg # Copyright (C) 2007-2019 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-2017
# #
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: vdr-satip 2.2.5\n" "Project-Id-Version: vdr-satip 2.4.0\n"
"Report-Msgid-Bugs-To: <see README>\n" "Report-Msgid-Bugs-To: <see README>\n"
"POT-Creation-Date: 2017-08-15 08:15+0300\n" "POT-Creation-Date: 2019-10-27 19:12+0200\n"
"PO-Revision-Date: 2017-08-15 08:15+0300\n" "PO-Revision-Date: 2019-10-27 10:27+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"
@@ -56,7 +56,7 @@ msgid "Creation date"
msgstr "Zeitpunkt der Erstellung" msgstr "Zeitpunkt der Erstellung"
msgid "SAT>IP Device Status" msgid "SAT>IP Device Status"
msgstr "SAT>IP Geräte Status" msgstr "SAT>IP Gerätestatus"
msgid "SAT>IP Information" msgid "SAT>IP Information"
msgstr "SAT>IP Informationen" msgstr "SAT>IP Informationen"
@@ -110,10 +110,10 @@ msgid ""
msgstr "" msgstr ""
"Bestimme die Betriebsart für alle SAT>IP Geräte:\n" "Bestimme die Betriebsart für alle SAT>IP Geräte:\n"
"\n" "\n"
"aus - Geräte sind abgeschaltet\n" "aus - Geräte sind deaktiviert\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öchste Priorität" "hoch - Geräte arbeiten mit höchster Priorität"
msgid "Enable CI extension" msgid "Enable CI extension"
msgstr "Aktiviere CI Erweiterung" msgstr "Aktiviere CI Erweiterung"
@@ -149,7 +149,7 @@ msgid ""
msgstr "" msgstr ""
"Legt fest ob EPG im Hintergrund aktualisiert werden soll oder nicht.\n" "Legt fest 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." "Diese Einstellung schaltet die automatische EIT Aktualisierung für alle SAT>IP Geräte aus."
msgid "Disabled sources" msgid "Disabled sources"
msgstr "Deaktivierte Quellen" msgstr "Deaktivierte Quellen"
@@ -199,6 +199,12 @@ msgstr ""
"\n" "\n"
"Unicast, Multicast, RTP-over-TCP" "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:" msgid "Active SAT>IP servers:"
msgstr "Aktive SAT>IP Server:" msgstr "Aktive SAT>IP Server:"

View File

@@ -1,14 +1,14 @@
# VDR plugin language source file. # VDR plugin language source file.
# Copyright (C) 2007-2017 Rolf Ahrenberg # Copyright (C) 2007-2019 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-2017
# #
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: vdr-satip 2.2.5\n" "Project-Id-Version: vdr-satip 2.4.0\n"
"Report-Msgid-Bugs-To: <see README>\n" "Report-Msgid-Bugs-To: <see README>\n"
"POT-Creation-Date: 2017-08-15 08:15+0300\n" "POT-Creation-Date: 2019-10-27 19:12+0200\n"
"PO-Revision-Date: 2017-08-15 08:15+0300\n" "PO-Revision-Date: 2019-10-27 10:27+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"
@@ -196,6 +196,12 @@ msgid ""
"Unicast, Multicast, RTP-over-TCP" "Unicast, Multicast, RTP-over-TCP"
msgstr "" 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:" msgid "Active SAT>IP servers:"
msgstr "Activa SAT>IP servers:" msgstr "Activa SAT>IP servers:"

View File

@@ -1,14 +1,14 @@
# VDR plugin language source file. # VDR plugin language source file.
# Copyright (C) 2007-2017 Rolf Ahrenberg # Copyright (C) 2007-2019 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-2017 # Rolf Ahrenberg, 2015-2019
# #
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: vdr-satip 2.2.5\n" "Project-Id-Version: vdr-satip 2.4.0\n"
"Report-Msgid-Bugs-To: <see README>\n" "Report-Msgid-Bugs-To: <see README>\n"
"POT-Creation-Date: 2017-08-15 08:15+0300\n" "POT-Creation-Date: 2019-10-27 19:12+0200\n"
"PO-Revision-Date: 2017-08-15 08:15+0300\n" "PO-Revision-Date: 2019-10-27 10:27+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"
@@ -198,6 +198,12 @@ msgstr ""
"\n" "\n"
"Unicast, Multicast, RTP-over-TCP" "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:" msgid "Active SAT>IP servers:"
msgstr "Aktiiviset SAT>IP-palvelimet:" msgstr "Aktiiviset SAT>IP-palvelimet:"

View File

@@ -1,14 +1,14 @@
# VDR plugin language source file. # VDR plugin language source file.
# Copyright (C) 2007-2017 Rolf Ahrenberg # Copyright (C) 2007-2019 Rolf Ahrenberg
# This file is distributed under the same license as the vdr-satip package. # This file is distributed under the same license as the vdr-satip package.
# Tomasz Maciej Nowak, 2017 # Tomasz Maciej Nowak, 2017
# #
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: vdr-satip 2.2.5\n" "Project-Id-Version: vdr-satip 2.4.0\n"
"Report-Msgid-Bugs-To: <see README>\n" "Report-Msgid-Bugs-To: <see README>\n"
"POT-Creation-Date: 2017-08-15 08:15+0300\n" "POT-Creation-Date: 2019-10-27 19:12+0200\n"
"PO-Revision-Date: 2017-08-15 08:15+0300\n" "PO-Revision-Date: 2019-10-27 10:27+0200\n"
"Last-Translator: Tomasz Maciej Nowak <tomek_n@o2.pl>\n" "Last-Translator: Tomasz Maciej Nowak <tomek_n@o2.pl>\n"
"Language-Team: Polish <vdr@linuxtv.org>\n" "Language-Team: Polish <vdr@linuxtv.org>\n"
"Language: pl_PL\n" "Language: pl_PL\n"
@@ -199,6 +199,12 @@ msgstr ""
"Określa tryb transmisji.\n" "Określa tryb transmisji.\n"
"Unicast, Multicast, RTP-over-TCP." "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:" msgid "Active SAT>IP servers:"
msgstr "Aktywne serwery SAT>IP:" msgstr "Aktywne serwery SAT>IP:"

28
rtcp.c
View File

@@ -34,7 +34,7 @@ int cSatipRtcp::GetFd(void)
return Fd(); return Fd();
} }
int cSatipRtcp::GetApplicationOffset(int *lengthP) int cSatipRtcp::GetApplicationOffset(unsigned char *bufferP, int *lengthP)
{ {
debug16("%s (%d) [device %d]", __PRETTY_FUNCTION__, lengthP ? *lengthP : -1, tunerM.GetId()); debug16("%s (%d) [device %d]", __PRETTY_FUNCTION__, lengthP ? *lengthP : -1, tunerM.GetId());
if (!lengthP) if (!lengthP)
@@ -43,29 +43,29 @@ int cSatipRtcp::GetApplicationOffset(int *lengthP)
int total = *lengthP; int total = *lengthP;
while (total > 0) { while (total > 0) {
// Version // Version
unsigned int v = (bufferM[offset] >> 6) & 0x03; unsigned int v = (bufferP[offset] >> 6) & 0x03;
// Padding // Padding
//unsigned int p = (bufferM[offset] >> 5) & 0x01; //unsigned int p = (bufferP[offset] >> 5) & 0x01;
// Subtype // Subtype
//unsigned int st = bufferM[offset] & 0x1F; //unsigned int st = bufferP[offset] & 0x1F;
// Payload type // Payload type
unsigned int pt = bufferM[offset + 1] & 0xFF; unsigned int pt = bufferP[offset + 1] & 0xFF;
// Length // Length
unsigned int length = ((bufferM[offset + 2] & 0xFF) << 8) | (bufferM[offset + 3] & 0xFF); unsigned int length = ((bufferP[offset + 2] & 0xFF) << 8) | (bufferP[offset + 3] & 0xFF);
// Convert it to bytes // Convert it to bytes
length = (length + 1) * 4; length = (length + 1) * 4;
// V=2, APP = 204 // V=2, APP = 204
if ((v == 2) && (pt == 204)) { if ((v == 2) && (pt == 204)) {
// SSCR/CSCR // SSCR/CSCR
//unsigned int ssrc = ((bufferM[offset + 4] & 0xFF) << 24) | ((bufferM[offset + 5] & 0xFF) << 16) | //unsigned int ssrc = ((bufferP[offset + 4] & 0xFF) << 24) | ((bufferP[offset + 5] & 0xFF) << 16) |
// ((bufferM[offset + 6] & 0xFF) << 8) | (bufferM[offset + 7] & 0xFF); // ((bufferP[offset + 6] & 0xFF) << 8) | (bufferP[offset + 7] & 0xFF);
// Name // Name
if ((bufferM[offset + 8] == 'S') && (bufferM[offset + 9] == 'E') && if ((bufferP[offset + 8] == 'S') && (bufferP[offset + 9] == 'E') &&
(bufferM[offset + 10] == 'S') && (bufferM[offset + 11] == '1')) { (bufferP[offset + 10] == 'S') && (bufferP[offset + 11] == '1')) {
// Identifier // Identifier
//unsigned int id = ((bufferM[offset + 12] & 0xFF) << 8) | (bufferM[offset + 13] & 0xFF); //unsigned int id = ((bufferP[offset + 12] & 0xFF) << 8) | (bufferP[offset + 13] & 0xFF);
// String length // String length
int string_length = ((bufferM[offset + 14] & 0xFF) << 8) | (bufferM[offset + 15] & 0xFF); int string_length = ((bufferP[offset + 14] & 0xFF) << 8) | (bufferP[offset + 15] & 0xFF);
if (string_length > 0) { if (string_length > 0) {
*lengthP = string_length; *lengthP = string_length;
return (offset + 16); return (offset + 16);
@@ -85,7 +85,7 @@ void cSatipRtcp::Process(void)
if (bufferM) { if (bufferM) {
int length; int length;
while ((length = Read(bufferM, bufferLenM)) > 0) { while ((length = Read(bufferM, bufferLenM)) > 0) {
int offset = GetApplicationOffset(&length); int offset = GetApplicationOffset(bufferM, &length);
if (offset >= 0) if (offset >= 0)
tunerM.ProcessApplicationData(bufferM + offset, length); tunerM.ProcessApplicationData(bufferM + offset, length);
} }
@@ -96,7 +96,7 @@ void cSatipRtcp::Process(unsigned char *dataP, int lengthP)
{ {
debug16("%s [device %d]", __PRETTY_FUNCTION__, tunerM.GetId()); debug16("%s [device %d]", __PRETTY_FUNCTION__, tunerM.GetId());
if (dataP && lengthP > 0) { if (dataP && lengthP > 0) {
int offset = GetApplicationOffset(&lengthP); int offset = GetApplicationOffset(dataP, &lengthP);
if (offset >= 0) if (offset >= 0)
tunerM.ProcessApplicationData(dataP + offset, lengthP); tunerM.ProcessApplicationData(dataP + offset, lengthP);
} }

2
rtcp.h
View File

@@ -20,7 +20,7 @@ private:
cSatipTunerIf &tunerM; cSatipTunerIf &tunerM;
unsigned int bufferLenM; unsigned int bufferLenM;
unsigned char *bufferM; unsigned char *bufferM;
int GetApplicationOffset(int *lengthP); int GetApplicationOffset(unsigned char *bufferP, int *lengthP);
public: public:
explicit cSatipRtcp(cSatipTunerIf &tunerP); explicit cSatipRtcp(cSatipTunerIf &tunerP);

22
rtsp.c
View File

@@ -206,6 +206,28 @@ bool cSatipRtsp::SetInterface(const char *bindAddrP)
return result; 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) bool cSatipRtsp::Options(const char *uriP)
{ {
debug1("%s (%s) [device %d]", __PRETTY_FUNCTION__, uriP, tunerM.GetId()); debug1("%s (%s) [device %d]", __PRETTY_FUNCTION__, uriP, tunerM.GetId());

1
rtsp.h
View File

@@ -59,6 +59,7 @@ public:
cString RtspUnescapeString(const char *strP); cString RtspUnescapeString(const char *strP);
void Reset(void); void Reset(void);
bool SetInterface(const char *bindAddrP); bool SetInterface(const char *bindAddrP);
bool Receive(const char *uriP);
bool Options(const char *uriP); bool Options(const char *uriP);
bool Setup(const char *uriP, int rtpPortP, int rtcpPortP, bool useTcpP); bool Setup(const char *uriP, int rtpPortP, int rtcpPortP, bool useTcpP);
bool SetSession(const char *sessionP); bool SetSession(const char *sessionP);

35
satip.c
View File

@@ -20,15 +20,15 @@
#warning "CURL version >= 7.36.0 is recommended" #warning "CURL version >= 7.36.0 is recommended"
#endif #endif
#if defined(APIVERSNUM) && APIVERSNUM < 20200 #if defined(APIVERSNUM) && APIVERSNUM < 20400
#error "VDR-2.2.0 API version or greater is required!" #error "VDR-2.4.0 API version or greater is required!"
#endif #endif
#ifndef GITVERSION #ifndef GITVERSION
#define GITVERSION "" #define GITVERSION ""
#endif #endif
const char VERSION[] = "2.2.5" GITVERSION; const char VERSION[] = "2.4.1" 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 {
@@ -85,8 +85,31 @@ const char *cPluginSatip::CommandLineHelp(void)
// 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> set number of devices to be created\n"
" -t <mode>, --trace=<mode> set the tracing mode\n" " -t <mode>, --trace=<mode> set the tracing mode\n"
" -s <ipaddr>|<model>|<desc>, --server=<ipaddr1>|<model1>|<desc1>;<ipaddr2>:<port>|<model2>:<filter>|<desc2>:<quirk>\n" " -s <ipaddr>|<model>|<desc>, --server=[<srcaddress>@]<ipaddress>[:<port>]|<model>[:<filter>]|<description>[:<quirk>];...\n"
" define hard-coded SAT>IP server(s)\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" " -D, --detach set the detached mode on\n"
" -S, --single set the single model server mode on\n" " -S, --single set the single model server mode on\n"
" -n, --noquirks disable autodetection of the server quirks\n" " -n, --noquirks disable autodetection of the server quirks\n"
@@ -392,6 +415,8 @@ bool cPluginSatip::SetupParse(const char *nameP, const char *valueP)
SatipConfig.SetOperatingMode(atoi(valueP)); SatipConfig.SetOperatingMode(atoi(valueP));
else if (!strcasecmp(nameP, "EnableCIExtension")) else if (!strcasecmp(nameP, "EnableCIExtension"))
SatipConfig.SetCIExtension(atoi(valueP)); SatipConfig.SetCIExtension(atoi(valueP));
else if (!strcasecmp(nameP, "EnableFrontendReuse"))
SatipConfig.SetFrontendReuse(atoi(valueP));
else if (!strcasecmp(nameP, "CICAM")) { else if (!strcasecmp(nameP, "CICAM")) {
int Cicams[MAX_CICAM_COUNT]; int Cicams[MAX_CICAM_COUNT];
for (unsigned int i = 0; i < ELEMENTS(Cicams); ++i) for (unsigned int i = 0; i < ELEMENTS(Cicams); ++i)

View File

@@ -119,6 +119,7 @@ cSatipServer::cSatipServer(const char *srcAddressP, const char *addressP, const
// Elgato EyeTV Netstream 4Sat ? // Elgato EyeTV Netstream 4Sat ?
if (strstr(*descriptionM, "GSSBOX") || // Grundig Sat Systems GSS.box DSI 400 if (strstr(*descriptionM, "GSSBOX") || // Grundig Sat Systems GSS.box DSI 400
strstr(*descriptionM, "DIGIBIT") || // Telestar Digibit R1 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, "Triax SatIP Converter") // Triax TSS 400
) )
quirkM |= eSatipQuirkSessionId; quirkM |= eSatipQuirkSessionId;
@@ -128,34 +129,38 @@ cSatipServer::cSatipServer(const char *srcAddressP, const char *addressP, const
) )
quirkM |= eSatipQuirkRtpOverTcp; quirkM |= eSatipQuirkRtpOverTcp;
// These devices contain a play (add/delpids) parameter bug: // These devices contain a play (add/delpids) parameter bug:
if (strstr(*descriptionM, "FRITZ!Box 6490 Cable") || // FRITZ!Box 6490 Cable if (strstr(*descriptionM, "FRITZ!WLAN Repeater DVB-C") || // FRITZ!WLAN Repeater DVB-C
strstr(*descriptionM, "FRITZ!WLAN Repeater DVB-C") || // FRITZ!WLAN Repeater DVB-C
strstr(*descriptionM, "fritzdvbc") // FRITZ!WLAN Repeater DVB-C (old firmware) strstr(*descriptionM, "fritzdvbc") // FRITZ!WLAN Repeater DVB-C (old firmware)
) )
quirkM |= eSatipQuirkPlayPids; quirkM |= eSatipQuirkPlayPids;
// These devices contain a frontend locking bug: // These devices contain a frontend locking bug:
if (strstr(*descriptionM, "FRITZ!Box 6490 Cable") || // FRITZ!Box 6490 Cable if (strstr(*descriptionM, "FRITZ!WLAN Repeater DVB-C") || // FRITZ!WLAN Repeater DVB-C
strstr(*descriptionM, "FRITZ!WLAN Repeater DVB-C") || // FRITZ!WLAN Repeater DVB-C
strstr(*descriptionM, "fritzdvbc") || // FRITZ!WLAN Repeater DVB-C (old firmware) strstr(*descriptionM, "fritzdvbc") || // FRITZ!WLAN Repeater DVB-C (old firmware)
strstr(*descriptionM, "Schwaiger Sat>IP Server") // Schwaiger MS41IP strstr(*descriptionM, "Schwaiger Sat>IP Server") // Schwaiger MS41IP
) )
quirkM |= eSatipQuirkForceLock; quirkM |= eSatipQuirkForceLock;
// These devices support the X_PMT protocol extension // These devices support the X_PMT protocol extension:
if (strstr(*descriptionM, "OctopusNet") || // Digital Devices OctopusNet if (strstr(*descriptionM, "OctopusNet") || // Digital Devices OctopusNet
strstr(*descriptionM, "minisatip") // minisatip server strstr(*descriptionM, "minisatip") // minisatip server
) )
quirkM |= eSatipQuirkCiXpmt; quirkM |= eSatipQuirkCiXpmt;
// These devices support the TNR protocol extension // These devices support the TNR protocol extension:
if (strstr(*descriptionM, "DVBViewer") // DVBViewer Media Server if (strstr(*descriptionM, "DVBViewer") // DVBViewer Media Server
) )
quirkM |= eSatipQuirkCiTnr; quirkM |= eSatipQuirkCiTnr;
// These devices don't support auto-detection of pilot tones // These devices don't support auto-detection of pilot tones:
if (strstr(*descriptionM, "GSSBOX") || // Grundig Sat Systems GSS.box DSI 400 if (strstr(*descriptionM, "GSSBOX") || // Grundig Sat Systems GSS.box DSI 400
strstr(*descriptionM, "DIGIBIT") || // Telestar Digibit R1 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, "Triax SatIP Converter") || // Triax TSS 400
strstr(*descriptionM, "KATHREIN SatIP Server") // Kathrein ExIP 414/E strstr(*descriptionM, "KATHREIN SatIP Server") // Kathrein ExIP 414/E
) )
quirkM |= eSatipQuirkForcePilot; 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) if ((quirkM & eSatipQuirkMask) & eSatipQuirkSessionId)
quirksM = cString::sprintf("%s%sSessionId", *quirksM, isempty(*quirksM) ? "" : ","); quirksM = cString::sprintf("%s%sSessionId", *quirksM, isempty(*quirksM) ? "" : ",");
@@ -208,6 +213,11 @@ cSatipServer::cSatipServer(const char *srcAddressP, const char *addressP, const
for (int i = 1; i <= count; ++i) for (int i = 1; i <= count; ++i)
frontendsM[eSatipFrontendDVBC2].Add(new cSatipFrontend(i, "DVB-C2")); 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_POINTER(p);
@@ -260,6 +270,8 @@ bool cSatipServer::Assign(int deviceIdP, int sourceP, int systemP, int transpond
else else
result = frontendsM[eSatipFrontendDVBC].Assign(deviceIdP, transponderP) || frontendsM[eSatipFrontendDVBC2].Assign(deviceIdP, transponderP); 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; return result;
} }
@@ -273,6 +285,8 @@ bool cSatipServer::Matches(int sourceP)
return GetModulesDVBT() || GetModulesDVBT2(); return GetModulesDVBT() || GetModulesDVBT2();
else if (cSource::IsType(sourceP, 'C')) else if (cSource::IsType(sourceP, 'C'))
return GetModulesDVBC() || GetModulesDVBC2(); return GetModulesDVBC() || GetModulesDVBC2();
else if (cSource::IsType(sourceP, 'A'))
return GetModulesATSC();
} }
return false; return false;
} }
@@ -295,6 +309,8 @@ bool cSatipServer::Matches(int deviceIdP, int sourceP, int systemP, int transpon
else else
result = frontendsM[eSatipFrontendDVBC].Matches(deviceIdP, transponderP) || frontendsM[eSatipFrontendDVBC2].Matches(deviceIdP, transponderP); 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; return result;
} }
@@ -340,6 +356,11 @@ int cSatipServer::GetModulesDVBC2(void)
return frontendsM[eSatipFrontendDVBC2].Count(); return frontendsM[eSatipFrontendDVBC2].Count();
} }
int cSatipServer::GetModulesATSC(void)
{
return frontendsM[eSatipFrontendATSC].Count();
}
// --- cSatipServers ---------------------------------------------------------- // --- cSatipServers ----------------------------------------------------------
cSatipServer *cSatipServers::Find(cSatipServer *serverP) cSatipServer *cSatipServers::Find(cSatipServer *serverP)
@@ -521,6 +542,8 @@ int cSatipServers::NumProvidedSystems(void)
count += s->GetModulesDVBC() * 3; count += s->GetModulesDVBC() * 3;
// DVB-C2: qam16, qam32, qam64, qam128, qam256 // DVB-C2: qam16, qam32, qam64, qam128, qam256
count += s->GetModulesDVBC2() * 5; count += s->GetModulesDVBC2() * 5;
// ATSC: 8vbs, 16vbs, qam256
count += s->GetModulesATSC() * 3;
} }
return count; return count;
} }

View File

@@ -52,6 +52,7 @@ private:
eSatipFrontendDVBT2, eSatipFrontendDVBT2,
eSatipFrontendDVBC, eSatipFrontendDVBC,
eSatipFrontendDVBC2, eSatipFrontendDVBC2,
eSatipFrontendATSC,
eSatipFrontendCount eSatipFrontendCount
}; };
enum { enum {
@@ -75,15 +76,16 @@ private:
public: public:
enum eSatipQuirk { enum eSatipQuirk {
eSatipQuirkNone = 0x00, eSatipQuirkNone = 0x00,
eSatipQuirkSessionId = 0x01, eSatipQuirkSessionId = 0x01,
eSatipQuirkPlayPids = 0x02, eSatipQuirkPlayPids = 0x02,
eSatipQuirkForceLock = 0x04, eSatipQuirkForceLock = 0x04,
eSatipQuirkRtpOverTcp = 0x08, eSatipQuirkRtpOverTcp = 0x08,
eSatipQuirkCiXpmt = 0x10, eSatipQuirkCiXpmt = 0x10,
eSatipQuirkCiTnr = 0x20, eSatipQuirkCiTnr = 0x20,
eSatipQuirkForcePilot = 0x40, eSatipQuirkForcePilot = 0x40,
eSatipQuirkMask = 0xFF 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); cSatipServer(const char *srcAddressP, const char *addressP, const int portP, const char *modelP, const char *filtersP, const char *descriptionP, const int quirkP);
virtual ~cSatipServer(); virtual ~cSatipServer();
@@ -98,6 +100,7 @@ public:
int GetModulesDVBT2(void); int GetModulesDVBT2(void);
int GetModulesDVBC(void); int GetModulesDVBC(void);
int GetModulesDVBC2(void); int GetModulesDVBC2(void);
int GetModulesATSC(void);
void Activate(bool onOffP) { activeM = onOffP; } void Activate(bool onOffP) { activeM = onOffP; }
const char *SrcAddress(void) { return *srcAddressM; } const char *SrcAddress(void) { return *srcAddressM; }
const char *Address(void) { return *addressM; } const char *Address(void) { return *addressM; }

View File

@@ -347,6 +347,7 @@ cSatipPluginSetup::cSatipPluginSetup()
operatingModeM(SatipConfig.GetOperatingMode()), operatingModeM(SatipConfig.GetOperatingMode()),
transportModeM(SatipConfig.GetTransportMode()), transportModeM(SatipConfig.GetTransportMode()),
ciExtensionM(SatipConfig.GetCIExtension()), ciExtensionM(SatipConfig.GetCIExtension()),
frontendReuseM(SatipConfig.GetFrontendReuse()),
eitScanM(SatipConfig.GetEITScan()), eitScanM(SatipConfig.GetEITScan()),
numDisabledSourcesM(SatipConfig.GetDisabledSourcesCount()), numDisabledSourcesM(SatipConfig.GetDisabledSourcesCount()),
numDisabledFiltersM(SatipConfig.GetDisabledFiltersCount()) numDisabledFiltersM(SatipConfig.GetDisabledFiltersCount())
@@ -418,6 +419,10 @@ void cSatipPluginSetup::Setup(void)
} }
Add(new cMenuEditStraItem(tr("Transport mode"), &transportModeM, ELEMENTS(transportModeTextsM), transportModeTextsM)); Add(new cMenuEditStraItem(tr("Transport mode"), &transportModeM, ELEMENTS(transportModeTextsM), transportModeTextsM));
helpM.Append(tr("Define which transport mode shall be used.\n\nUnicast, Multicast, RTP-over-TCP")); 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)); Add(new cOsdItem(tr("Active SAT>IP servers:"), osUnknown, false));
helpM.Append(""); helpM.Append("");
@@ -479,6 +484,7 @@ eOSState cSatipPluginSetup::ProcessKey(eKeys keyP)
bool hadSubMenu = HasSubMenu(); bool hadSubMenu = HasSubMenu();
int oldOperatingMode = operatingModeM; int oldOperatingMode = operatingModeM;
int oldCiExtension = ciExtensionM; int oldCiExtension = ciExtensionM;
int oldFrontendReuse = frontendReuseM;
int oldNumDisabledSources = numDisabledSourcesM; int oldNumDisabledSources = numDisabledSourcesM;
int oldNumDisabledFilters = numDisabledFiltersM; int oldNumDisabledFilters = numDisabledFiltersM;
eOSState state = cMenuSetupPage::ProcessKey(keyP); eOSState state = cMenuSetupPage::ProcessKey(keyP);
@@ -504,7 +510,7 @@ eOSState cSatipPluginSetup::ProcessKey(eKeys keyP)
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) || (detachedModeM != SatipConfig.GetDetachedMode()))) { if ((keyP != kNone) && ((numDisabledSourcesM != oldNumDisabledSources) || (numDisabledFiltersM != oldNumDisabledFilters) || (operatingModeM != oldOperatingMode) || (ciExtensionM != oldCiExtension) || ( oldFrontendReuse != frontendReuseM) || (detachedModeM != SatipConfig.GetDetachedMode()))) {
while ((numDisabledSourcesM < oldNumDisabledSources) && (oldNumDisabledSources > 0)) while ((numDisabledSourcesM < oldNumDisabledSources) && (oldNumDisabledSources > 0))
disabledSourcesM[--oldNumDisabledSources] = cSource::stNone; disabledSourcesM[--oldNumDisabledSources] = cSource::stNone;
while ((numDisabledFiltersM < oldNumDisabledFilters) && (oldNumDisabledFilters > 0)) while ((numDisabledFiltersM < oldNumDisabledFilters) && (oldNumDisabledFilters > 0))
@@ -569,6 +575,7 @@ void cSatipPluginSetup::Store(void)
SetupStore("OperatingMode", operatingModeM); SetupStore("OperatingMode", operatingModeM);
SetupStore("TransportMode", transportModeM); SetupStore("TransportMode", transportModeM);
SetupStore("EnableCIExtension", ciExtensionM); SetupStore("EnableCIExtension", ciExtensionM);
SetupStore("EnableFrontendReuse", frontendReuseM);
SetupStore("EnableEITScan", eitScanM); SetupStore("EnableEITScan", eitScanM);
StoreCicams("CICAM", cicamsM); StoreCicams("CICAM", cicamsM);
StoreSources("DisabledSources", disabledSourcesM); StoreSources("DisabledSources", disabledSourcesM);

View File

@@ -22,6 +22,7 @@ private:
const char *operatingModeTextsM[cSatipConfig::eOperatingModeCount]; const char *operatingModeTextsM[cSatipConfig::eOperatingModeCount];
const char *transportModeTextsM[cSatipConfig::eTransportModeCount]; const char *transportModeTextsM[cSatipConfig::eTransportModeCount];
int ciExtensionM; int ciExtensionM;
int frontendReuseM;
int cicamsM[MAX_CICAM_COUNT]; int cicamsM[MAX_CICAM_COUNT];
const char *cicamTextsM[CA_SYSTEMS_TABLE_SIZE]; const char *cicamTextsM[CA_SYSTEMS_TABLE_SIZE];
int eitScanM; int eitScanM;

89
tuner.c
View File

@@ -25,6 +25,8 @@ cSatipTuner::cSatipTuner(cSatipDeviceIf &deviceP, unsigned int packetLenP)
rtcpM(*this), rtcpM(*this),
streamAddrM(""), streamAddrM(""),
streamParamM(""), streamParamM(""),
lastAddrM(""),
lastParamM(""),
tnrParamM(""), tnrParamM(""),
streamPortM(SATIP_DEFAULT_RTSP_PORT), streamPortM(SATIP_DEFAULT_RTSP_PORT),
currentServerM(NULL, deviceP.GetId(), 0), currentServerM(NULL, deviceP.GetId(), 0),
@@ -34,12 +36,14 @@ cSatipTuner::cSatipTuner(cSatipDeviceIf &deviceP, unsigned int packetLenP)
keepAliveM(), keepAliveM(),
statusUpdateM(), statusUpdateM(),
pidUpdateCacheM(), pidUpdateCacheM(),
setupTimeoutM(-1),
sessionM(""), sessionM(""),
currentStateM(tsIdle), currentStateM(tsIdle),
internalStateM(), internalStateM(),
externalStateM(), externalStateM(),
timeoutM(eMinKeepAliveIntervalMs), timeoutM(eMinKeepAliveIntervalMs - eKeepAlivePreBufferMs),
hasLockM(false), hasLockM(false),
signalStrengthDBmM(0.0),
signalStrengthM(-1), signalStrengthM(-1),
signalQualityM(-1), signalQualityM(-1),
frontendIdM(-1), frontendIdM(-1),
@@ -116,6 +120,8 @@ void cSatipTuner::Action(void)
break; break;
case tsSet: case tsSet:
debug4("%s: tsSet [device %d]", __PRETTY_FUNCTION__, deviceIdM); debug4("%s: tsSet [device %d]", __PRETTY_FUNCTION__, deviceIdM);
if (currentServerM.IsQuirk(cSatipServer::eSatipQuirkTearAndPlay))
Disconnect();
if (Connect()) { if (Connect()) {
tuning.Set(eTuningTimeoutMs); tuning.Set(eTuningTimeoutMs);
RequestState(tsTuned, smInternal); RequestState(tsTuned, smInternal);
@@ -135,6 +141,7 @@ void cSatipTuner::Action(void)
// Quirk for devices without valid reception data // Quirk for devices without valid reception data
if (currentServerM.IsQuirk(cSatipServer::eSatipQuirkForceLock)) { if (currentServerM.IsQuirk(cSatipServer::eSatipQuirkForceLock)) {
hasLockM = true; hasLockM = true;
signalStrengthDBmM = eDefaultSignalStrengthDBm;
signalStrengthM = eDefaultSignalStrength; signalStrengthM = eDefaultSignalStrength;
signalQualityM = eDefaultSignalQuality; signalQualityM = eDefaultSignalQuality;
} }
@@ -173,6 +180,7 @@ void cSatipTuner::Action(void)
idleCheck.Set(eIdleCheckTimeoutMs); idleCheck.Set(eIdleCheckTimeoutMs);
break; break;
} }
Receive();
break; break;
default: default:
error("Unknown tuner status %d [device %d]", currentStateM, deviceIdM); error("Unknown tuner status %d [device %d]", currentStateM, deviceIdM);
@@ -189,8 +197,6 @@ bool cSatipTuner::Open(void)
cMutexLock MutexLock(&mutexM); cMutexLock MutexLock(&mutexM);
debug1("%s [device %d]", __PRETTY_FUNCTION__, deviceIdM); debug1("%s [device %d]", __PRETTY_FUNCTION__, deviceIdM);
RequestState(tsSet, smExternal);
// return always true // return always true
return true; return true;
} }
@@ -200,7 +206,8 @@ bool cSatipTuner::Close(void)
cMutexLock MutexLock(&mutexM); cMutexLock MutexLock(&mutexM);
debug1("%s [device %d]", __PRETTY_FUNCTION__, deviceIdM); debug1("%s [device %d]", __PRETTY_FUNCTION__, deviceIdM);
RequestState(tsRelease, smExternal); if (setupTimeoutM.TimedOut())
RequestState(tsRelease, smExternal);
// return always true // return always true
return true; return true;
@@ -216,10 +223,15 @@ bool cSatipTuner::Connect(void)
tnrParamM = ""; tnrParamM = "";
// Just retune // Just retune
if (streamIdM >= 0) { if (streamIdM >= 0) {
if (!strcmp(*streamParamM, *lastParamM) && hasLockM) {
debug1("%s Identical parameters [device %d]", __PRETTY_FUNCTION__, deviceIdM);
return true;
}
cString uri = cString::sprintf("%sstream=%d?%s", *connectionUri, streamIdM, *streamParamM); cString uri = cString::sprintf("%sstream=%d?%s", *connectionUri, streamIdM, *streamParamM);
debug1("%s Retuning [device %d]", __PRETTY_FUNCTION__, deviceIdM); debug1("%s Retuning [device %d]", __PRETTY_FUNCTION__, deviceIdM);
if (rtspM.Play(*uri)) { if (rtspM.Play(*uri)) {
keepAliveM.Set(timeoutM); keepAliveM.Set(timeoutM);
lastParamM = streamParamM;
return true; return true;
} }
} }
@@ -237,6 +249,7 @@ bool cSatipTuner::Connect(void)
currentServerM = nextServerM; currentServerM = nextServerM;
nextServerM.Reset(); nextServerM.Reset();
} }
lastAddrM = connectionUri;
currentServerM.Attach(); currentServerM.Attach();
return true; return true;
} }
@@ -254,8 +267,8 @@ bool cSatipTuner::Disconnect(void)
cMutexLock MutexLock(&mutexM); cMutexLock MutexLock(&mutexM);
debug1("%s [device %d]", __PRETTY_FUNCTION__, deviceIdM); debug1("%s [device %d]", __PRETTY_FUNCTION__, deviceIdM);
if (!isempty(*streamAddrM) && (streamIdM >= 0)) { if (!isempty(*lastAddrM) && (streamIdM >= 0)) {
cString uri = cString::sprintf("%sstream=%d", *GetBaseUrl(*streamAddrM, streamPortM), streamIdM); cString uri = cString::sprintf("%sstream=%d", *lastAddrM, streamIdM);
rtspM.Teardown(*uri); rtspM.Teardown(*uri);
// some devices requires a teardown for TCP connection also // some devices requires a teardown for TCP connection also
rtspM.Reset(); rtspM.Reset();
@@ -264,13 +277,14 @@ bool cSatipTuner::Disconnect(void)
// Reset signal parameters // Reset signal parameters
hasLockM = false; hasLockM = false;
signalStrengthDBmM = 0.0;
signalStrengthM = -1; signalStrengthM = -1;
signalQualityM = -1; signalQualityM = -1;
frontendIdM = -1; frontendIdM = -1;
currentServerM.Detach(); currentServerM.Detach();
statusUpdateM.Set(0); statusUpdateM.Set(0);
timeoutM = eMinKeepAliveIntervalMs; timeoutM = eMinKeepAliveIntervalMs - eKeepAlivePreBufferMs;
pmtPidM = -1; pmtPidM = -1;
addPidsM.Clear(); addPidsM.Clear();
delPidsM.Clear(); delPidsM.Clear();
@@ -333,8 +347,9 @@ void cSatipTuner::ProcessApplicationData(u_char *bufferP, int lengthP)
// No signal corresponds to 0 // No signal corresponds to 0
c = strstr(c, ","); c = strstr(c, ",");
value = min(atoi(++c), 255); value = min(atoi(++c), 255);
signalStrengthDBmM = (value >= 0) ? 40.0 * (value - 32) / 192.0 - 65.0 : 0.0;
// Scale value to 0-100 // Scale value to 0-100
signalStrengthM = (value >= 0) ? (value * 100 / 255) : -1; signalStrengthM = (value >= 0) ? value * 100 / 255 : -1;
// lock: // lock:
// lock Set to one of the following values: // lock Set to one of the following values:
@@ -378,6 +393,7 @@ void cSatipTuner::SetSessionTimeout(const char *sessionP, int timeoutP)
if (nextServerM.IsQuirk(cSatipServer::eSatipQuirkSessionId) && !isempty(*sessionM) && startswith(*sessionM, "0")) if (nextServerM.IsQuirk(cSatipServer::eSatipQuirkSessionId) && !isempty(*sessionM) && startswith(*sessionM, "0"))
rtspM.SetSession(SkipZeroes(*sessionM)); rtspM.SetSession(SkipZeroes(*sessionM));
timeoutM = (timeoutP > eMinKeepAliveIntervalMs) ? timeoutP : eMinKeepAliveIntervalMs; timeoutM = (timeoutP > eMinKeepAliveIntervalMs) ? timeoutP : eMinKeepAliveIntervalMs;
timeoutM -= eKeepAlivePreBufferMs;
} }
void cSatipTuner::SetupTransport(int rtpPortP, int rtcpPortP, const char *streamAddrP, const char *sourceAddrP) void cSatipTuner::SetupTransport(int rtpPortP, int rtcpPortP, const char *streamAddrP, const char *sourceAddrP)
@@ -442,7 +458,13 @@ bool cSatipTuner::SetSource(cSatipServer *serverP, const int transponderP, const
if (nextServerM.IsQuirk(cSatipServer::eSatipQuirkForcePilot) && strstr(parameterP, "msys=dvbs2") && !strstr(parameterP, "plts=")) if (nextServerM.IsQuirk(cSatipServer::eSatipQuirkForcePilot) && strstr(parameterP, "msys=dvbs2") && !strstr(parameterP, "plts="))
streamParamM = rtspM.RtspUnescapeString(*cString::sprintf("%s&plts=on", parameterP)); streamParamM = rtspM.RtspUnescapeString(*cString::sprintf("%s&plts=on", parameterP));
// Reconnect // Reconnect
if (!isempty(*lastAddrM)) {
cString connectionUri = GetBaseUrl(*streamAddrM, streamPortM);
if (strcmp(*connectionUri, *lastAddrM))
RequestState(tsRelease, smInternal);
}
RequestState(tsSet, smExternal); RequestState(tsSet, smExternal);
setupTimeoutM.Set(eSetupTimeoutMs);
} }
} }
else { else {
@@ -482,17 +504,24 @@ bool cSatipTuner::UpdatePids(bool forceP)
cString uri = cString::sprintf("%sstream=%d", *GetBaseUrl(*streamAddrM, streamPortM), streamIdM); cString uri = cString::sprintf("%sstream=%d", *GetBaseUrl(*streamAddrM, streamPortM), streamIdM);
bool useci = (SatipConfig.GetCIExtension() && currentServerM.HasCI()); bool useci = (SatipConfig.GetCIExtension() && currentServerM.HasCI());
bool usedummy = currentServerM.IsQuirk(cSatipServer::eSatipQuirkPlayPids); bool usedummy = currentServerM.IsQuirk(cSatipServer::eSatipQuirkPlayPids);
bool paramadded = false;
if (forceP || usedummy) { if (forceP || usedummy) {
if (pidsM.Size()) if (pidsM.Size()) {
uri = cString::sprintf("%s?pids=%s", *uri, *pidsM.ListPids()); uri = cString::sprintf("%s%spids=%s", *uri, paramadded ? "&" : "?", *pidsM.ListPids());
if (usedummy && (pidsM.Size() == 1) && (pidsM[0] < 0x20)) if (usedummy && (pidsM.Size() == 1) && (pidsM[0] < 0x20))
uri = cString::sprintf("%s,%d", *uri, eDummyPid); uri = cString::sprintf("%s,%d", *uri, eDummyPid);
paramadded = true;
}
} }
else { else {
if (addPidsM.Size()) if (addPidsM.Size()) {
uri = cString::sprintf("%s?addpids=%s", *uri, *addPidsM.ListPids()); uri = cString::sprintf("%s%saddpids=%s", *uri, paramadded ? "&" : "?", *addPidsM.ListPids());
if (delPidsM.Size()) paramadded = true;
uri = cString::sprintf("%s%sdelpids=%s", *uri, addPidsM.Size() ? "&" : "?", *delPidsM.ListPids()); }
if (delPidsM.Size()) {
uri = cString::sprintf("%s%sdelpids=%s", *uri, paramadded ? "&" : "?", *delPidsM.ListPids());
paramadded = true;
}
} }
if (useci) { if (useci) {
if (currentServerM.IsQuirk(cSatipServer::eSatipQuirkCiXpmt)) { if (currentServerM.IsQuirk(cSatipServer::eSatipQuirkCiXpmt)) {
@@ -505,9 +534,10 @@ bool cSatipTuner::UpdatePids(bool forceP)
int pid = deviceM->GetPmtPid(); int pid = deviceM->GetPmtPid();
if ((pid > 0) && (pid != pmtPidM)) { if ((pid > 0) && (pid != pmtPidM)) {
int slot = deviceM->GetCISlot(); int slot = deviceM->GetCISlot();
uri = cString::sprintf("%s&x_pmt=%d", *uri, pid); uri = cString::sprintf("%s%sx_pmt=%d", *uri, paramadded ? "&" : "?", pid);
if (slot > 0) if (slot > 0)
uri = cString::sprintf("%s&x_ci=%d", *uri, slot); uri = cString::sprintf("%s&x_ci=%d", *uri, slot);
paramadded = true;
} }
pmtPidM = pid; pmtPidM = pid;
} }
@@ -515,8 +545,10 @@ bool cSatipTuner::UpdatePids(bool forceP)
// CI extension parameters: // CI extension parameters:
// - tnr : specifies a channel config entry // - tnr : specifies a channel config entry
cString param = deviceM->GetTnrParameterString(); cString param = deviceM->GetTnrParameterString();
if (!isempty(*param) && strcmp(*tnrParamM, *param) != 0) if (!isempty(*param) && strcmp(*tnrParamM, *param) != 0) {
uri = cString::sprintf("%s&tnr=%s", *uri, *param); uri = cString::sprintf("%s%stnr=%s", *uri, paramadded ? "&" : "?", *param);
paramadded = true;
}
tnrParamM = param; tnrParamM = param;
} }
} }
@@ -530,6 +562,19 @@ bool cSatipTuner::UpdatePids(bool forceP)
return true; return true;
} }
bool cSatipTuner::Receive(void)
{
debug16("%s tunerState=%s [device %d]", __PRETTY_FUNCTION__, TunerStateString(currentStateM), deviceIdM);
cMutexLock MutexLock(&mutexM);
if (!isempty(*streamAddrM)) {
cString uri = GetBaseUrl(*streamAddrM, streamPortM);
if (!rtspM.Receive(*uri))
return false;
}
return true;
}
bool cSatipTuner::KeepAlive(bool forceP) bool cSatipTuner::KeepAlive(bool forceP)
{ {
debug16("%s (%d) tunerState=%s [device %d]", __PRETTY_FUNCTION__, forceP, TunerStateString(currentStateM), deviceIdM); debug16("%s (%d) tunerState=%s [device %d]", __PRETTY_FUNCTION__, forceP, TunerStateString(currentStateM), deviceIdM);
@@ -670,6 +715,12 @@ int cSatipTuner::SignalStrength(void)
return signalStrengthM; return signalStrengthM;
} }
double cSatipTuner::SignalStrengthDBm(void)
{
debug16("%s [device %d]", __PRETTY_FUNCTION__, deviceIdM);
return signalStrengthDBmM;
}
int cSatipTuner::SignalQuality(void) int cSatipTuner::SignalQuality(void)
{ {
debug16("%s [device %d]", __PRETTY_FUNCTION__, deviceIdM); debug16("%s [device %d]", __PRETTY_FUNCTION__, deviceIdM);

29
tuner.h
View File

@@ -78,16 +78,19 @@ class cSatipTuner : public cThread, public cSatipTunerStatistics, public cSatipT
{ {
private: private:
enum { enum {
eDummyPid = 100, eDummyPid = 100,
eDefaultSignalStrength = 15, eDefaultSignalStrengthDBm = -25,
eDefaultSignalQuality = 224, eDefaultSignalStrength = 224,
eSleepTimeoutMs = 250, // in milliseconds eDefaultSignalQuality = 15,
eStatusUpdateTimeoutMs = 1000, // in milliseconds eSleepTimeoutMs = 250, // in milliseconds
ePidUpdateIntervalMs = 250, // in milliseconds eStatusUpdateTimeoutMs = 1000, // in milliseconds
eConnectTimeoutMs = 5000, // in milliseconds ePidUpdateIntervalMs = 250, // in milliseconds
eIdleCheckTimeoutMs = 15000, // in milliseconds eConnectTimeoutMs = 5000, // in milliseconds
eTuningTimeoutMs = 20000, // in milliseconds eIdleCheckTimeoutMs = 15000, // in milliseconds
eMinKeepAliveIntervalMs = 30000 // 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 eTunerState { tsIdle, tsRelease, tsSet, tsTuned, tsLocked };
enum eStateMode { smInternal, smExternal }; enum eStateMode { smInternal, smExternal };
@@ -100,6 +103,8 @@ private:
cSatipRtcp rtcpM; cSatipRtcp rtcpM;
cString streamAddrM; cString streamAddrM;
cString streamParamM; cString streamParamM;
cString lastAddrM;
cString lastParamM;
cString tnrParamM; cString tnrParamM;
int streamPortM; int streamPortM;
cSatipTunerServer currentServerM; cSatipTunerServer currentServerM;
@@ -109,12 +114,14 @@ private:
cTimeMs keepAliveM; cTimeMs keepAliveM;
cTimeMs statusUpdateM; cTimeMs statusUpdateM;
cTimeMs pidUpdateCacheM; cTimeMs pidUpdateCacheM;
cTimeMs setupTimeoutM;
cString sessionM; cString sessionM;
eTunerState currentStateM; eTunerState currentStateM;
cVector<eTunerState> internalStateM; cVector<eTunerState> internalStateM;
cVector<eTunerState> externalStateM; cVector<eTunerState> externalStateM;
int timeoutM; int timeoutM;
bool hasLockM; bool hasLockM;
double signalStrengthDBmM;
int signalStrengthM; int signalStrengthM;
int signalQualityM; int signalQualityM;
int frontendIdM; int frontendIdM;
@@ -126,6 +133,7 @@ private:
bool Connect(void); bool Connect(void);
bool Disconnect(void); bool Disconnect(void);
bool Receive(void);
bool KeepAlive(bool forceP = false); bool KeepAlive(bool forceP = false);
bool ReadReceptionStatus(bool forceP = false); bool ReadReceptionStatus(bool forceP = false);
bool UpdatePids(bool forceP = false); bool UpdatePids(bool forceP = false);
@@ -149,6 +157,7 @@ public:
bool Close(void); bool Close(void);
int FrontendId(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);