mirror of
https://github.com/rofafor/vdr-plugin-satip.git
synced 2023-10-10 11:37:42 +00:00
Compare commits
74 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
299296bbb1 | ||
|
43373b6951 | ||
|
0a15717245 | ||
|
82cf5488a7 | ||
|
8dc4844db8 | ||
|
e008ee04b2 | ||
|
8be58070ad | ||
|
72c3247dc2 | ||
|
dbe67a2242 | ||
|
f4454b0f0d | ||
|
0a9bb96dd4 | ||
|
3cc63dadac | ||
|
46a197d8f8 | ||
|
ece52576dd | ||
|
5159508f2d | ||
|
c4c2ba8d14 | ||
|
e90926d5f6 | ||
|
27e86dd3ea | ||
|
7e6b722747 | ||
|
97097f74af | ||
|
1de063ca38 | ||
|
bf5b058725 | ||
|
470fee436f | ||
|
c10372bb4f | ||
|
1984ec662c | ||
|
537c0ad000 | ||
|
732e28d0f0 | ||
|
3a9dc9a634 | ||
|
438f5c9254 | ||
|
5e524a969e | ||
|
8b1d8de468 | ||
|
12b5dac447 | ||
|
40943b8bd2 | ||
|
e092d085b8 | ||
|
1158141d35 | ||
|
c6145e1ed9 | ||
|
c5da1074f3 | ||
|
69795ec82a | ||
|
3cf32a64eb | ||
|
3fd4928d75 | ||
|
941a13b794 | ||
|
20e9dc99f9 | ||
|
d26658a22e | ||
|
a5d57e9390 | ||
|
af64cb3011 | ||
|
48862f99d3 | ||
|
6ed729c153 | ||
|
0fc044a316 | ||
|
94b7f1132f | ||
|
e7c9b04ad2 | ||
|
9c91e01a87 | ||
|
7a84ba78c8 | ||
|
c2fe2b748d | ||
|
13a6b5938f | ||
|
5db9f93a11 | ||
|
cede4743cb | ||
|
4e9b6f11eb | ||
|
4b1892d754 | ||
|
473e016152 | ||
|
793aab17d7 | ||
|
8222d05f5d | ||
|
9d7c745fe1 | ||
|
c8a5245b6c | ||
|
ff459f426e | ||
|
4c216d81c8 | ||
|
23e2b4d54d | ||
|
954e1be6b3 | ||
|
e46340f5f3 | ||
|
d5e9b1050e | ||
|
6e9b5fc414 | ||
|
6e9b43b0d8 | ||
|
97aba6db0f | ||
|
660c48a9f4 | ||
|
67b6c9f4f7 |
63
HISTORY
63
HISTORY
@@ -144,3 +144,66 @@ VDR Plugin 'satip' Revision History
|
|||||||
- Reset the RTSP connection after any failed connect.
|
- Reset the RTSP connection after any failed connect.
|
||||||
- Added tweaks for minisatip and Schwaiger MS41IP.
|
- Added tweaks for minisatip and Schwaiger MS41IP.
|
||||||
- Updated for vdr-2.3.1 (Thanks to Klaus Schmidinger).
|
- Updated for vdr-2.3.1 (Thanks to Klaus Schmidinger).
|
||||||
|
|
||||||
|
2016-12-18: Version 2.2.4
|
||||||
|
|
||||||
|
- Updated German translation (Thanks to Frank Neumann).
|
||||||
|
- Fixed Panasonic CXW804 support (Thanks to Tobias Grimm).
|
||||||
|
- Fixed C++11 support (Thanks to Tobias Grimm).
|
||||||
|
- Fixed server assigment with source validation (Thanks to Patrick Boettcher).
|
||||||
|
- Added configurable RTP/RTCP ports (Thanks to chriszero).
|
||||||
|
- Added support for X-SATIP-RTSP-Port header.
|
||||||
|
- Added multicast and RTP-over-TCP support.
|
||||||
|
- Added support for activating/deactivating server on-the-fly.
|
||||||
|
- Extended command-line parameters for setting server quirks.
|
||||||
|
|
||||||
|
2017-08-15: Version 2.2.5
|
||||||
|
|
||||||
|
- Added Polish translation (Thanks to Tomasz Nowak).
|
||||||
|
- Updated Catalan and Spanish translations (Thanks to Gabriel Bonich).
|
||||||
|
- Added support for KATHREIN SatIP Server (Thanks to kavanu).
|
||||||
|
- Added support for FRITZ!Box 6490 Cable (Thanks to 9000h).
|
||||||
|
- Updated FRITZ!WLAN Repeater DVB-C detection for the latest firmware (Thanks to 9000h).
|
||||||
|
- Added GCC7 compatibility (Thanks to Sascha Kuehndel).
|
||||||
|
|
||||||
|
|
||||||
|
===================================
|
||||||
|
VDR Plugin 'satip' Revision History
|
||||||
|
===================================
|
||||||
|
|
||||||
|
2016-12-18: Version 2.3.0
|
||||||
|
|
||||||
|
- Updated for vdr-2.3.1.
|
||||||
|
- Updated German translation (Thanks to Frank Neumann).
|
||||||
|
- Fixed Panasonic CXW804 support (Thanks to Tobias Grimm).
|
||||||
|
- Fixed C++11 support (Thanks to Tobias Grimm).
|
||||||
|
- Fixed server assigment with source validation (Thanks to Patrick Boettcher).
|
||||||
|
- Added configurable RTP/RTCP ports (Thanks to chriszero).
|
||||||
|
- Added support for X-SATIP-RTSP-Port header.
|
||||||
|
- Added multicast and RTP-over-TCP support.
|
||||||
|
- Added support for activating/deactivating server on-the-fly.
|
||||||
|
- Extended command-line parameters for setting server quirks.
|
||||||
|
|
||||||
|
2017-08-15: Version 2.3.1
|
||||||
|
|
||||||
|
- Updated for vdr-2.3.7 (Thanks to Klaus Schmidinger).
|
||||||
|
- Added Polish translation (Thanks to Tomasz Nowak).
|
||||||
|
- Updated Catalan and Spanish translations (Thanks to Gabriel Bonich).
|
||||||
|
- Added support for KATHREIN SatIP Server (Thanks to kavanu).
|
||||||
|
- Added support for FRITZ!Box 6490 Cable (Thanks to 9000h).
|
||||||
|
- Updated FRITZ!WLAN Repeater DVB-C detection for the latest firmware (Thanks to 9000h).
|
||||||
|
- Added GCC7 compatibility (Thanks to Sascha Kuehndel).
|
||||||
|
|
||||||
|
|
||||||
|
===================================
|
||||||
|
VDR Plugin 'satip' Revision History
|
||||||
|
===================================
|
||||||
|
|
||||||
|
2018-04-15: Version 2.4.0
|
||||||
|
|
||||||
|
- Updated for vdr-2.4.0.
|
||||||
|
- Removed speed limit.
|
||||||
|
- Fixed transport media changes.
|
||||||
|
- Fixed memory leak in cSatipSectionFilter (Thanks to Alexander Pipelka).
|
||||||
|
- Added more robust section filter handling (Thanks to Alexander Pipelka).
|
||||||
|
- Added a command line parameter for the RTP receive buffer size (Thanks to Stefan Rehm).
|
||||||
|
27
Makefile
27
Makefile
@@ -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)
|
||||||
|
33
README
33
README
@@ -52,9 +52,15 @@ separated list of "<ipaddress>|<model>|<description>" entries. The model
|
|||||||
consists of a DVB system (DVBS2,DVBT2,DVBT,DVBC) and number of available
|
consists of a DVB system (DVBS2,DVBT2,DVBT,DVBC) and number of available
|
||||||
frontends separated by a hyphen:
|
frontends separated by a hyphen:
|
||||||
|
|
||||||
vdr -P 'satip -s <ipaddress>|<model>|<description>;...'
|
vdr -P 'satip -s [<srcaddress>@]<ipaddress>[:<port>]|<model>[:<filter>]|<description>[:<quirk>];...'
|
||||||
vdr -P 'satip -s 192.168.0.1|DVBS2-2,DVBT2-2|Octo1'
|
vdr -P 'satip -s 192.168.0.1|DVBS2-2,DVBT2-2|OctopusNet'
|
||||||
vdr -P 'satip -s 192.168.0.1|DVBS2-4|Octo1;192.168.0.2|DVBT2-4|Octo2'
|
vdr -P 'satip -s 192.168.0.1|DVBS2-4|OctopusNet;192.168.0.2|DVBT2-4|minisatip:0x18'
|
||||||
|
vdr -P 'satip -s 192.168.0.1:554|DVBS2-2:S19.2E|OctopusNet;192.168.0.2:8554|DVBS2-4:S19.2E,S1W|minisatip'
|
||||||
|
|
||||||
|
The plugin accepts a "--portrange" (-p) command-line parameter, that can
|
||||||
|
be used to manually specify the RTP & RTCP port range and therefore
|
||||||
|
enables using the plugin through a NAT (e.g. Docker bridged network).
|
||||||
|
A minimum of 2 ports per device is required.
|
||||||
|
|
||||||
SAT>IP satellite positions (aka. signal sources) shall be defined via
|
SAT>IP satellite positions (aka. signal sources) shall be defined via
|
||||||
sources.conf. If the source description begins with a number, it's used
|
sources.conf. If the source description begins with a number, it's used
|
||||||
@@ -110,6 +116,11 @@ Setup menu:
|
|||||||
"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
|
||||||
|
multicast RTP-over-TCP transport mode, set this option
|
||||||
|
rtp-o-tcp accordingly. Otherwise, the transport
|
||||||
|
mode will be RTP-over-UDP via unicast or
|
||||||
|
multicast.
|
||||||
- [Red:Scan] Forces network scanning of SAT>IP hardware.
|
- [Red:Scan] Forces network scanning of SAT>IP hardware.
|
||||||
- [Yellow:Devices] Opens SAT>IP device status menu.
|
- [Yellow:Devices] Opens SAT>IP device status menu.
|
||||||
- [Blue:Info] Opens SAT>IP information/statistics menu.
|
- [Blue:Info] Opens SAT>IP information/statistics menu.
|
||||||
@@ -125,6 +136,9 @@ Information menu:
|
|||||||
|
|
||||||
Notes:
|
Notes:
|
||||||
|
|
||||||
|
- If you are having problems receiving DVB-S2 channels, make sure your
|
||||||
|
channels.conf entry contains correct pilot tone setting.
|
||||||
|
|
||||||
- The stream id "-1" states about unsuccessful tuning. This might be a
|
- The stream id "-1" states about unsuccessful tuning. This might be a
|
||||||
result of invalid channel parameters or lack of free SAT>IP tuners.
|
result of invalid channel parameters or lack of free SAT>IP tuners.
|
||||||
|
|
||||||
@@ -145,6 +159,19 @@ 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.
|
||||||
|
|
||||||
|
- If you are experiencing glitches in the video stream, one possible
|
||||||
|
reason can be buffer overflows in RTP receive sockets. You can verify
|
||||||
|
this by checking "receive buffer errors" counter by running "netstat -s"
|
||||||
|
command. If the counter increases every time a video glitch happens,
|
||||||
|
you should try to tweak the RTP receive buffer size with the "--rcvbuf"
|
||||||
|
(-r) plugin parameter.
|
||||||
|
A good starting point for the buffer size is to double the operating
|
||||||
|
system default value until errors disappear or the maximum value is
|
||||||
|
reached. You can check these values in Linux by checking the kernel
|
||||||
|
parameters:
|
||||||
|
$ cat /proc/sys/net/core/rmem_default
|
||||||
|
$ cat /proc/sys/net/core/rmem_max
|
||||||
|
|
||||||
Acknowledgements:
|
Acknowledgements:
|
||||||
|
|
||||||
- Big thanks to Digital Devices GmbH for providing the Octopus Net
|
- Big thanks to Digital Devices GmbH for providing the Octopus Net
|
||||||
|
4
common.h
4
common.h
@@ -13,9 +13,11 @@
|
|||||||
#include <vdr/config.h>
|
#include <vdr/config.h>
|
||||||
#include <vdr/i18n.h>
|
#include <vdr/i18n.h>
|
||||||
|
|
||||||
|
#define SATIP_DEFAULT_RTSP_PORT 554
|
||||||
|
|
||||||
#define SATIP_MAX_DEVICES MAXDEVICES
|
#define SATIP_MAX_DEVICES MAXDEVICES
|
||||||
|
|
||||||
#define SATIP_BUFFER_SIZE KILOBYTE(1024)
|
#define SATIP_BUFFER_SIZE KILOBYTE(2048)
|
||||||
|
|
||||||
#define SATIP_DEVICE_INFO_ALL 0
|
#define SATIP_DEVICE_INFO_ALL 0
|
||||||
#define SATIP_DEVICE_INFO_GENERAL 1
|
#define SATIP_DEVICE_INFO_GENERAL 1
|
||||||
|
6
config.c
6
config.c
@@ -17,9 +17,13 @@ cSatipConfig::cSatipConfig(void)
|
|||||||
ciExtensionM(0),
|
ciExtensionM(0),
|
||||||
eitScanM(1),
|
eitScanM(1),
|
||||||
useBytesM(1),
|
useBytesM(1),
|
||||||
|
portRangeStartM(0),
|
||||||
|
portRangeStopM(0),
|
||||||
|
transportModeM(eTransportModeUnicast),
|
||||||
detachedModeM(false),
|
detachedModeM(false),
|
||||||
disableServerQuirksM(false),
|
disableServerQuirksM(false),
|
||||||
useSingleModelServersM(false)
|
useSingleModelServersM(false),
|
||||||
|
rtpRcvBufSizeM(0)
|
||||||
{
|
{
|
||||||
for (unsigned int i = 0; i < ELEMENTS(cicamsM); ++i)
|
for (unsigned int i = 0; i < ELEMENTS(cicamsM); ++i)
|
||||||
cicamsM[i] = 0;
|
cicamsM[i] = 0;
|
||||||
|
21
config.h
21
config.h
@@ -19,12 +19,16 @@ private:
|
|||||||
unsigned int ciExtensionM;
|
unsigned int ciExtensionM;
|
||||||
unsigned int eitScanM;
|
unsigned int eitScanM;
|
||||||
unsigned int useBytesM;
|
unsigned int useBytesM;
|
||||||
|
unsigned int portRangeStartM;
|
||||||
|
unsigned int portRangeStopM;
|
||||||
|
unsigned int transportModeM;
|
||||||
bool detachedModeM;
|
bool detachedModeM;
|
||||||
bool disableServerQuirksM;
|
bool disableServerQuirksM;
|
||||||
bool useSingleModelServersM;
|
bool useSingleModelServersM;
|
||||||
int cicamsM[MAX_CICAM_COUNT];
|
int cicamsM[MAX_CICAM_COUNT];
|
||||||
int disabledSourcesM[MAX_DISABLED_SOURCES_COUNT];
|
int disabledSourcesM[MAX_DISABLED_SOURCES_COUNT];
|
||||||
int disabledFiltersM[SECTION_FILTER_TABLE_SIZE];
|
int disabledFiltersM[SECTION_FILTER_TABLE_SIZE];
|
||||||
|
size_t rtpRcvBufSizeM;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
enum eOperatingMode {
|
enum eOperatingMode {
|
||||||
@@ -34,6 +38,12 @@ public:
|
|||||||
eOperatingModeHigh,
|
eOperatingModeHigh,
|
||||||
eOperatingModeCount
|
eOperatingModeCount
|
||||||
};
|
};
|
||||||
|
enum eTransportMode {
|
||||||
|
eTransportModeUnicast = 0,
|
||||||
|
eTransportModeMulticast,
|
||||||
|
eTransportModeRtpOverTcp,
|
||||||
|
eTransportModeCount
|
||||||
|
};
|
||||||
enum eTraceMode {
|
enum eTraceMode {
|
||||||
eTraceModeNormal = 0x0000,
|
eTraceModeNormal = 0x0000,
|
||||||
eTraceModeDebug1 = 0x0001,
|
eTraceModeDebug1 = 0x0001,
|
||||||
@@ -67,6 +77,10 @@ public:
|
|||||||
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; }
|
||||||
|
unsigned int GetTransportMode(void) const { return transportModeM; }
|
||||||
|
bool IsTransportModeUnicast(void) const { return (transportModeM == eTransportModeUnicast); }
|
||||||
|
bool IsTransportModeRtpOverTcp(void) const { return (transportModeM == eTransportModeRtpOverTcp); }
|
||||||
|
bool IsTransportModeMulticast(void) const { return (transportModeM == eTransportModeMulticast); }
|
||||||
bool GetDetachedMode(void) const { return detachedModeM; }
|
bool GetDetachedMode(void) const { return detachedModeM; }
|
||||||
bool GetDisableServerQuirks(void) const { return disableServerQuirksM; }
|
bool GetDisableServerQuirks(void) const { return disableServerQuirksM; }
|
||||||
bool GetUseSingleModelServers(void) const { return useSingleModelServersM; }
|
bool GetUseSingleModelServers(void) const { return useSingleModelServersM; }
|
||||||
@@ -74,6 +88,9 @@ public:
|
|||||||
int GetDisabledSources(unsigned int indexP) const;
|
int GetDisabledSources(unsigned int indexP) const;
|
||||||
unsigned int GetDisabledFiltersCount(void) const;
|
unsigned int GetDisabledFiltersCount(void) const;
|
||||||
int GetDisabledFilters(unsigned int indexP) const;
|
int GetDisabledFilters(unsigned int indexP) const;
|
||||||
|
unsigned int GetPortRangeStart(void) const { return portRangeStartM; }
|
||||||
|
unsigned int GetPortRangeStop(void) const { return portRangeStopM; }
|
||||||
|
size_t GetRtpRcvBufSize(void) const { return rtpRcvBufSizeM; }
|
||||||
|
|
||||||
void SetOperatingMode(unsigned int operatingModeP) { operatingModeM = operatingModeP; }
|
void SetOperatingMode(unsigned int operatingModeP) { operatingModeM = operatingModeP; }
|
||||||
void SetTraceMode(unsigned int modeP) { traceModeM = (modeP & eTraceModeMask); }
|
void SetTraceMode(unsigned int modeP) { traceModeM = (modeP & eTraceModeMask); }
|
||||||
@@ -81,11 +98,15 @@ public:
|
|||||||
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; }
|
||||||
|
void SetTransportMode(unsigned int transportModeP) { transportModeM = transportModeP; }
|
||||||
void SetDetachedMode(bool onOffP) { detachedModeM = onOffP; }
|
void SetDetachedMode(bool onOffP) { detachedModeM = onOffP; }
|
||||||
void SetDisableServerQuirks(bool onOffP) { disableServerQuirksM = onOffP; }
|
void SetDisableServerQuirks(bool onOffP) { disableServerQuirksM = onOffP; }
|
||||||
void SetUseSingleModelServers(bool onOffP) { useSingleModelServersM = onOffP; }
|
void SetUseSingleModelServers(bool onOffP) { useSingleModelServersM = onOffP; }
|
||||||
void SetDisabledSources(unsigned int indexP, int sourceP);
|
void SetDisabledSources(unsigned int indexP, int sourceP);
|
||||||
void SetDisabledFilters(unsigned int indexP, int numberP);
|
void SetDisabledFilters(unsigned int indexP, int numberP);
|
||||||
|
void SetPortRangeStart(unsigned int rangeStartP) { portRangeStartM = rangeStartP; }
|
||||||
|
void SetPortRangeStop(unsigned int rangeStopP) { portRangeStopM = rangeStopP; }
|
||||||
|
void SetRtpRcvBufSize(size_t sizeP) { rtpRcvBufSizeM = sizeP; }
|
||||||
};
|
};
|
||||||
|
|
||||||
extern cSatipConfig SatipConfig;
|
extern cSatipConfig SatipConfig;
|
||||||
|
91
detectsatip.py
Executable file
91
detectsatip.py
Executable file
@@ -0,0 +1,91 @@
|
|||||||
|
#!/usr/bin/env python2
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
""" Simple tool to detect SAT>IP devices as JSON.
|
||||||
|
"""
|
||||||
|
import json
|
||||||
|
import socket
|
||||||
|
import sys
|
||||||
|
import xml.etree.ElementTree as ET
|
||||||
|
import requests
|
||||||
|
|
||||||
|
SSDP_BIND = '0.0.0.0'
|
||||||
|
SSDP_ADDR = '239.255.255.250'
|
||||||
|
SSDP_PORT = 1900
|
||||||
|
SSDP_MX = 1
|
||||||
|
SSDP_ST = 'urn:ses-com:device:SatIPServer:1'
|
||||||
|
SSDP_REQUEST = 'M-SEARCH * HTTP/1.1\r\n' + \
|
||||||
|
'HOST: %s:%d\r\n' % (SSDP_ADDR, SSDP_PORT) + \
|
||||||
|
'MAN: "ssdp:discover"\r\n' + \
|
||||||
|
'MX: %d\r\n' % (SSDP_MX, ) + \
|
||||||
|
'ST: %s\r\n' % (SSDP_ST, ) + \
|
||||||
|
'\r\n'
|
||||||
|
|
||||||
|
|
||||||
|
def parse_satip_xml(data):
|
||||||
|
""" Parse SAT>IP XML data.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
data (str): XML input data..
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
dict: Parsed SAT>IP device name and frontend information.
|
||||||
|
"""
|
||||||
|
result = {'name': '', 'frontends': {}}
|
||||||
|
if data:
|
||||||
|
root = ET.fromstring(data)
|
||||||
|
name = root.find('.//*/{urn:schemas-upnp-org:device-1-0}friendlyName')
|
||||||
|
result['name'] = name.text
|
||||||
|
satipcap = root.find('.//*/{urn:ses-com:satip}X_SATIPCAP')
|
||||||
|
caps = {}
|
||||||
|
for system in satipcap.text.split(","):
|
||||||
|
cap = system.split("-")
|
||||||
|
if cap:
|
||||||
|
count = int(cap[1])
|
||||||
|
if cap[0] in caps:
|
||||||
|
count = count + caps[cap[0]]
|
||||||
|
caps[cap[0]] = count
|
||||||
|
result['frontends'] = caps
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
def detect_satip_devices():
|
||||||
|
""" Detect available SAT>IP devices by sending a broadcast message.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
list: Found SAT>IP devices.
|
||||||
|
"""
|
||||||
|
urls = []
|
||||||
|
devices = []
|
||||||
|
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||||
|
sock.setblocking(0)
|
||||||
|
sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
|
||||||
|
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
||||||
|
try:
|
||||||
|
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1)
|
||||||
|
except BaseException:
|
||||||
|
pass
|
||||||
|
sock.settimeout(1)
|
||||||
|
sock.bind((SSDP_BIND, SSDP_PORT))
|
||||||
|
sock.sendto(SSDP_REQUEST, (SSDP_ADDR, SSDP_PORT))
|
||||||
|
try:
|
||||||
|
while 1:
|
||||||
|
data = sock.recv(1024)
|
||||||
|
if data:
|
||||||
|
for row in data.split('\r\n'):
|
||||||
|
if 'LOCATION:' in row:
|
||||||
|
url = row.replace('LOCATION:', '').strip()
|
||||||
|
if url in urls:
|
||||||
|
continue
|
||||||
|
urls.append(url)
|
||||||
|
info = requests.get(url, timeout=2)
|
||||||
|
devices.append(parse_satip_xml(info.text))
|
||||||
|
else:
|
||||||
|
break
|
||||||
|
except BaseException:
|
||||||
|
pass
|
||||||
|
sock.close()
|
||||||
|
return devices
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
json.dump(detect_satip_devices(), fp=sys.stdout, sort_keys=True, indent=2)
|
90
device.c
90
device.c
@@ -15,14 +15,17 @@
|
|||||||
|
|
||||||
static cSatipDevice * SatipDevicesS[SATIP_MAX_DEVICES] = { NULL };
|
static cSatipDevice * SatipDevicesS[SATIP_MAX_DEVICES] = { NULL };
|
||||||
|
|
||||||
|
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),
|
||||||
mutexM()
|
tunedM()
|
||||||
{
|
{
|
||||||
unsigned int bufsize = (unsigned int)SATIP_BUFFER_SIZE;
|
unsigned int bufsize = (unsigned int)SATIP_BUFFER_SIZE;
|
||||||
bufsize -= (bufsize % TS_SIZE);
|
bufsize -= (bufsize % TS_SIZE);
|
||||||
@@ -42,6 +45,8 @@ cSatipDevice::cSatipDevice(unsigned int indexP)
|
|||||||
cSatipDevice::~cSatipDevice()
|
cSatipDevice::~cSatipDevice()
|
||||||
{
|
{
|
||||||
debug1("%s [device %u]", __PRETTY_FUNCTION__, deviceIndexM);
|
debug1("%s [device %u]", __PRETTY_FUNCTION__, deviceIndexM);
|
||||||
|
// Release immediately any pending conditional wait
|
||||||
|
tunedM.Broadcast();
|
||||||
// Stop section handler
|
// Stop section handler
|
||||||
StopSectionHandler();
|
StopSectionHandler();
|
||||||
DELETE_POINTER(pSectionFilterHandlerM);
|
DELETE_POINTER(pSectionFilterHandlerM);
|
||||||
@@ -103,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)
|
||||||
@@ -120,8 +121,12 @@ cString cSatipDevice::GetSatipStatus(void)
|
|||||||
info = cString::sprintf("%sCardIndex: %d HasLock: yes Strength: %d Quality: %d%s\n", *info, device->CardIndex(), device->SignalStrength(), device->SignalQuality(), live ? " Live: yes" : "");
|
info = cString::sprintf("%sCardIndex: %d HasLock: yes Strength: %d Quality: %d%s\n", *info, device->CardIndex(), device->SignalStrength(), device->SignalQuality(), live ? " Live: yes" : "");
|
||||||
else
|
else
|
||||||
info = cString::sprintf("%sCardIndex: %d HasLock: no\n", *info, device->CardIndex());
|
info = cString::sprintf("%sCardIndex: %d HasLock: no\n", *info, device->CardIndex());
|
||||||
if (channel && channel->Number() > 0)
|
if (channel) {
|
||||||
info = cString::sprintf("%sTransponder: %d Channel: %s\n", *info, (channel && channel->Number() > 0) ? channel->Transponder() : 0, (channel && channel->Number() > 0) ? channel->Name() : "---");
|
if (channel->Number() > 0 && device->Receiving())
|
||||||
|
info = cString::sprintf("%sTransponder: %d Channel: %s\n", *info, channel->Transponder(), channel->Name());
|
||||||
|
else
|
||||||
|
info = cString::sprintf("%sTransponder: %d\n", *info, channel->Transponder());
|
||||||
|
}
|
||||||
if (timers)
|
if (timers)
|
||||||
info = cString::sprintf("%sRecording: %d timer%s\n", *info, timers, (timers > 1) ? "s" : "");
|
info = cString::sprintf("%sRecording: %d timer%s\n", *info, timers, (timers > 1) ? "s" : "");
|
||||||
info = cString::sprintf("%s\n", *info);
|
info = cString::sprintf("%s\n", *info);
|
||||||
@@ -133,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",
|
|
||||||
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)
|
||||||
@@ -206,6 +205,8 @@ cString cSatipDevice::DeviceType(void) const
|
|||||||
cString cSatipDevice::DeviceName(void) const
|
cString cSatipDevice::DeviceName(void) const
|
||||||
{
|
{
|
||||||
debug16("%s [device %u]", __PRETTY_FUNCTION__, deviceIndexM);
|
debug16("%s [device %u]", __PRETTY_FUNCTION__, deviceIndexM);
|
||||||
|
if (!Receiving())
|
||||||
|
return cString::sprintf("%s %d", *DeviceType(), deviceIndexM);
|
||||||
return deviceNameM;
|
return deviceNameM;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -215,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);
|
||||||
@@ -333,6 +349,7 @@ bool cSatipDevice::MaySwitchTransponder(const cChannel *channelP) const
|
|||||||
|
|
||||||
bool cSatipDevice::SetChannelDevice(const cChannel *channelP, bool liveViewP)
|
bool cSatipDevice::SetChannelDevice(const cChannel *channelP, bool liveViewP)
|
||||||
{
|
{
|
||||||
|
cMutexLock MutexLock(&mutexS); // Global lock to prevent any simultaneous zapping
|
||||||
debug9("%s (%d, %d) [device %u]", __PRETTY_FUNCTION__, channelP ? channelP->Number() : -1, liveViewP, deviceIndexM);
|
debug9("%s (%d, %d) [device %u]", __PRETTY_FUNCTION__, channelP ? channelP->Number() : -1, liveViewP, deviceIndexM);
|
||||||
if (channelP) {
|
if (channelP) {
|
||||||
cDvbTransponderParameters dtp(channelP->Parameters());
|
cDvbTransponderParameters dtp(channelP->Parameters());
|
||||||
@@ -350,23 +367,33 @@ bool cSatipDevice::SetChannelDevice(const cChannel *channelP, bool liveViewP)
|
|||||||
if (pTunerM && pTunerM->SetSource(server, channelP->Transponder(), *params, deviceIndexM)) {
|
if (pTunerM && pTunerM->SetSource(server, channelP->Transponder(), *params, deviceIndexM)) {
|
||||||
channelM = *channelP;
|
channelM = *channelP;
|
||||||
deviceNameM = cString::sprintf("%s %d %s", *DeviceType(), deviceIndexM, *cSatipDiscover::GetInstance()->GetServerString(server));
|
deviceNameM = cString::sprintf("%s %d %s", *DeviceType(), deviceIndexM, *cSatipDiscover::GetInstance()->GetServerString(server));
|
||||||
|
// Wait for actual channel tuning to prevent simultaneous frontend allocation failures
|
||||||
|
tunedM.TimedWait(mutexS, eTuningTimeoutMs);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (pTunerM) {
|
else if (pTunerM) {
|
||||||
pTunerM->SetSource(NULL, 0, NULL, deviceIndexM);
|
pTunerM->SetSource(NULL, 0, NULL, deviceIndexM);
|
||||||
|
deviceNameM = cString::sprintf("%s %d", *DeviceType(), deviceIndexM);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void cSatipDevice::SetChannelTuned(void)
|
||||||
|
{
|
||||||
|
debug9("%s () [device %u]", __PRETTY_FUNCTION__, deviceIndexM);
|
||||||
|
// Release immediately any pending conditional wait
|
||||||
|
tunedM.Broadcast();
|
||||||
|
}
|
||||||
|
|
||||||
bool cSatipDevice::SetPid(cPidHandle *handleP, int typeP, bool onP)
|
bool cSatipDevice::SetPid(cPidHandle *handleP, int typeP, bool onP)
|
||||||
{
|
{
|
||||||
debug12("%s (%d, %d, %d) [device %u]", __PRETTY_FUNCTION__, handleP ? handleP->pid : -1, typeP, onP, deviceIndexM);
|
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) {
|
||||||
if (onP)
|
if (onP)
|
||||||
return pTunerM->SetPid(handleP->pid, typeP, true);
|
return pTunerM->SetPid(handleP->pid, typeP, true);
|
||||||
else if (!handleP->used)
|
else if (!handleP->used && pSectionFilterHandlerM && !pSectionFilterHandlerM->Exists(handleP->pid))
|
||||||
return pTunerM->SetPid(handleP->pid, typeP, false);
|
return pTunerM->SetPid(handleP->pid, typeP, false);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@@ -398,7 +425,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();
|
||||||
@@ -472,18 +499,29 @@ int cSatipDevice::GetCISlot(void)
|
|||||||
return slot;
|
return slot;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cString cSatipDevice::GetTnrParameterString(void)
|
||||||
|
{
|
||||||
|
if (channelM.Ca())
|
||||||
|
return GetTnrUrlParameters(&channelM);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
bool cSatipDevice::IsIdle(void)
|
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) {
|
||||||
@@ -497,7 +535,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
|
||||||
@@ -511,8 +549,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());
|
||||||
}
|
}
|
||||||
@@ -526,11 +563,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)
|
||||||
|
available = 0;
|
||||||
dataP = cs->Decrypt(dataP, available);
|
dataP = cs->Decrypt(dataP, available);
|
||||||
SkipData(available);
|
SkipData(available);
|
||||||
}
|
checkTsBufferM = dataP != NULL;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
17
device.h
17
device.h
@@ -18,7 +18,7 @@
|
|||||||
class cSatipDevice : public cDevice, public cSatipPidStatistics, public cSatipBufferStatistics, public cSatipDeviceIf {
|
class cSatipDevice : public cDevice, public cSatipPidStatistics, public cSatipBufferStatistics, public cSatipDeviceIf {
|
||||||
// static ones
|
// static ones
|
||||||
public:
|
public:
|
||||||
static unsigned int deviceCount;
|
static cMutex mutexS;
|
||||||
static bool Initialize(unsigned int DeviceCount);
|
static bool Initialize(unsigned int DeviceCount);
|
||||||
static void Shutdown(void);
|
static void Shutdown(void);
|
||||||
static unsigned int Count(void);
|
static unsigned int Count(void);
|
||||||
@@ -28,18 +28,20 @@ public:
|
|||||||
// private parts
|
// private parts
|
||||||
private:
|
private:
|
||||||
enum {
|
enum {
|
||||||
eReadyTimeoutMs = 2000 // in milliseconds
|
eReadyTimeoutMs = 2000, // in milliseconds
|
||||||
|
eTuningTimeoutMs = 1000 // in milliseconds
|
||||||
};
|
};
|
||||||
unsigned int deviceIndexM;
|
unsigned int deviceIndexM;
|
||||||
bool isPacketDeliveredM;
|
int bytesDeliveredM;
|
||||||
bool isOpenDvrM;
|
bool isOpenDvrM;
|
||||||
|
bool checkTsBufferM;
|
||||||
cString deviceNameM;
|
cString deviceNameM;
|
||||||
cChannel channelM;
|
cChannel channelM;
|
||||||
cRingBufferLinear *tsBufferM;
|
cRingBufferLinear *tsBufferM;
|
||||||
cSatipTuner *pTunerM;
|
cSatipTuner *pTunerM;
|
||||||
cSatipSectionFilterHandler *pSectionFilterHandlerM;
|
cSatipSectionFilterHandler *pSectionFilterHandlerM;
|
||||||
cTimeMs createdM;
|
cTimeMs createdM;
|
||||||
cMutex mutexM;
|
cCondVar tunedM;
|
||||||
|
|
||||||
// constructor & destructor
|
// constructor & destructor
|
||||||
public:
|
public:
|
||||||
@@ -63,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;
|
||||||
|
|
||||||
@@ -82,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:
|
||||||
@@ -98,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:
|
||||||
@@ -107,9 +110,11 @@ public:
|
|||||||
// for internal device interface
|
// for internal device interface
|
||||||
public:
|
public:
|
||||||
virtual void WriteData(u_char *bufferP, int lengthP);
|
virtual void WriteData(u_char *bufferP, int lengthP);
|
||||||
|
virtual void SetChannelTuned(void);
|
||||||
virtual int GetId(void);
|
virtual int GetId(void);
|
||||||
virtual int GetPmtPid(void);
|
virtual int GetPmtPid(void);
|
||||||
virtual int GetCISlot(void);
|
virtual int GetCISlot(void);
|
||||||
|
virtual cString GetTnrParameterString(void);
|
||||||
virtual bool IsIdle(void);
|
virtual bool IsIdle(void);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -13,9 +13,11 @@ public:
|
|||||||
cSatipDeviceIf() {}
|
cSatipDeviceIf() {}
|
||||||
virtual ~cSatipDeviceIf() {}
|
virtual ~cSatipDeviceIf() {}
|
||||||
virtual void WriteData(u_char *bufferP, int lengthP) = 0;
|
virtual void WriteData(u_char *bufferP, int lengthP) = 0;
|
||||||
|
virtual void SetChannelTuned(void) = 0;
|
||||||
virtual int GetId(void) = 0;
|
virtual int GetId(void) = 0;
|
||||||
virtual int GetPmtPid(void) = 0;
|
virtual int GetPmtPid(void) = 0;
|
||||||
virtual int GetCISlot(void) = 0;
|
virtual int GetCISlot(void) = 0;
|
||||||
|
virtual cString GetTnrParameterString(void) = 0;
|
||||||
virtual bool IsIdle(void) = 0;
|
virtual bool IsIdle(void) = 0;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
84
discover.c
84
discover.c
@@ -32,7 +32,7 @@ bool cSatipDiscover::Initialize(cSatipDiscoverServers *serversP)
|
|||||||
if (instanceS) {
|
if (instanceS) {
|
||||||
if (serversP) {
|
if (serversP) {
|
||||||
for (cSatipDiscoverServer *s = serversP->First(); s; s = serversP->Next(s))
|
for (cSatipDiscoverServer *s = serversP->First(); s; s = serversP->Next(s))
|
||||||
instanceS->AddServer(s->IpAddress(), s->Model(), s->Description());
|
instanceS->AddServer(s->SrcAddress(), s->IpAddress(), s->IpPort(), s->Model(), s->Filters(), s->Description(), s->Quirk());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
instanceS->Activate();
|
instanceS->Activate();
|
||||||
@@ -47,6 +47,18 @@ void cSatipDiscover::Destroy(void)
|
|||||||
instanceS->Deactivate();
|
instanceS->Deactivate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t cSatipDiscover::HeaderCallback(char *ptrP, size_t sizeP, size_t nmembP, void *dataP)
|
||||||
|
{
|
||||||
|
cSatipDiscover *obj = reinterpret_cast<cSatipDiscover *>(dataP);
|
||||||
|
size_t len = sizeP * nmembP;
|
||||||
|
debug16("%s len=%zu", __PRETTY_FUNCTION__, len);
|
||||||
|
|
||||||
|
if (obj && (len > 0))
|
||||||
|
obj->headerBufferM.Add(ptrP, len);
|
||||||
|
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
size_t cSatipDiscover::DataCallback(char *ptrP, size_t sizeP, size_t nmembP, void *dataP)
|
size_t cSatipDiscover::DataCallback(char *ptrP, size_t sizeP, size_t nmembP, void *dataP)
|
||||||
{
|
{
|
||||||
cSatipDiscover *obj = reinterpret_cast<cSatipDiscover *>(dataP);
|
cSatipDiscover *obj = reinterpret_cast<cSatipDiscover *>(dataP);
|
||||||
@@ -91,6 +103,7 @@ int cSatipDiscover::DebugCallback(CURL *handleP, curl_infotype typeP, char *data
|
|||||||
cSatipDiscover::cSatipDiscover()
|
cSatipDiscover::cSatipDiscover()
|
||||||
: cThread("SATIP discover"),
|
: cThread("SATIP discover"),
|
||||||
mutexM(),
|
mutexM(),
|
||||||
|
headerBufferM(),
|
||||||
dataBufferM(),
|
dataBufferM(),
|
||||||
msearchM(*this),
|
msearchM(*this),
|
||||||
probeUrlListM(),
|
probeUrlListM(),
|
||||||
@@ -176,7 +189,9 @@ void cSatipDiscover::Fetch(const char *urlP)
|
|||||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_DEBUGFUNCTION, cSatipDiscover::DebugCallback);
|
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_DEBUGFUNCTION, cSatipDiscover::DebugCallback);
|
||||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_DEBUGDATA, this);
|
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_DEBUGDATA, this);
|
||||||
|
|
||||||
// Set callback
|
// Set header and data callbacks
|
||||||
|
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_HEADERFUNCTION, cSatipDiscover::HeaderCallback);
|
||||||
|
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEHEADER, this);
|
||||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEFUNCTION, cSatipDiscover::DataCallback);
|
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEFUNCTION, cSatipDiscover::DataCallback);
|
||||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEDATA, this);
|
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEDATA, this);
|
||||||
|
|
||||||
@@ -199,7 +214,8 @@ void cSatipDiscover::Fetch(const char *urlP)
|
|||||||
SATIP_CURL_EASY_GETINFO(handleM, CURLINFO_RESPONSE_CODE, &rc);
|
SATIP_CURL_EASY_GETINFO(handleM, CURLINFO_RESPONSE_CODE, &rc);
|
||||||
SATIP_CURL_EASY_GETINFO(handleM, CURLINFO_PRIMARY_IP, &addr);
|
SATIP_CURL_EASY_GETINFO(handleM, CURLINFO_PRIMARY_IP, &addr);
|
||||||
if (rc == 200) {
|
if (rc == 200) {
|
||||||
ParseDeviceInfo(addr);
|
ParseDeviceInfo(addr, ParseRtspPort());
|
||||||
|
headerBufferM.Reset();
|
||||||
dataBufferM.Reset();
|
dataBufferM.Reset();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -207,9 +223,32 @@ void cSatipDiscover::Fetch(const char *urlP)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void cSatipDiscover::ParseDeviceInfo(const char *addrP)
|
int cSatipDiscover::ParseRtspPort(void)
|
||||||
{
|
{
|
||||||
debug1("%s (%s)", __PRETTY_FUNCTION__, addrP);
|
debug1("%s", __PRETTY_FUNCTION__);
|
||||||
|
char *s, *p = headerBufferM.Data();
|
||||||
|
char *r = strtok_r(p, "\r\n", &s);
|
||||||
|
int port = SATIP_DEFAULT_RTSP_PORT;
|
||||||
|
|
||||||
|
while (r) {
|
||||||
|
debug16("%s (%zu): %s", __PRETTY_FUNCTION__, headerBufferM.Size(), r);
|
||||||
|
r = skipspace(r);
|
||||||
|
if (strstr(r, "X-SATIP-RTSP-Port")) {
|
||||||
|
int tmp = -1;
|
||||||
|
if (sscanf(r, "X-SATIP-RTSP-Port:%11d", &tmp) == 1) {
|
||||||
|
port = tmp;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
r = strtok_r(NULL, "\r\n", &s);
|
||||||
|
}
|
||||||
|
|
||||||
|
return port;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cSatipDiscover::ParseDeviceInfo(const char *addrP, const int portP)
|
||||||
|
{
|
||||||
|
debug1("%s (%s, %d)", __PRETTY_FUNCTION__, addrP, portP);
|
||||||
const char *desc = NULL, *model = NULL;
|
const char *desc = NULL, *model = NULL;
|
||||||
#ifdef USE_TINYXML
|
#ifdef USE_TINYXML
|
||||||
TiXmlDocument doc;
|
TiXmlDocument doc;
|
||||||
@@ -232,12 +271,12 @@ void cSatipDiscover::ParseDeviceInfo(const char *addrP)
|
|||||||
model = modelNode.text().as_string("DVBS2-1");
|
model = modelNode.text().as_string("DVBS2-1");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
AddServer(addrP, model, desc);
|
AddServer(NULL, addrP, portP, model, NULL, desc, cSatipServer::eSatipQuirkNone);
|
||||||
}
|
}
|
||||||
|
|
||||||
void cSatipDiscover::AddServer(const char *addrP, const char *modelP, const char * descP)
|
void cSatipDiscover::AddServer(const char *srcAddrP, const char *addrP, const int portP, const char *modelP, const char *filtersP, const char *descP, const int quirkP)
|
||||||
{
|
{
|
||||||
debug1("%s (%s, %s, %s)", __PRETTY_FUNCTION__, addrP, modelP, descP);
|
debug1("%s (%s, %s, %d, %s, %s, %s, %d)", __PRETTY_FUNCTION__, srcAddrP, addrP, portP, modelP, filtersP, descP, quirkP);
|
||||||
cMutexLock MutexLock(&mutexM);
|
cMutexLock MutexLock(&mutexM);
|
||||||
if (SatipConfig.GetUseSingleModelServers() && modelP && !isempty(modelP)) {
|
if (SatipConfig.GetUseSingleModelServers() && modelP && !isempty(modelP)) {
|
||||||
int n = 0;
|
int n = 0;
|
||||||
@@ -246,9 +285,9 @@ void cSatipDiscover::AddServer(const char *addrP, const char *modelP, const char
|
|||||||
while (r) {
|
while (r) {
|
||||||
r = skipspace(r);
|
r = skipspace(r);
|
||||||
cString desc = cString::sprintf("%s #%d", !isempty(descP) ? descP : "MyBrokenHardware", n++);
|
cString desc = cString::sprintf("%s #%d", !isempty(descP) ? descP : "MyBrokenHardware", n++);
|
||||||
cSatipServer *tmp = new cSatipServer(addrP, r, desc);
|
cSatipServer *tmp = new cSatipServer(srcAddrP, addrP, portP, r, filtersP, desc, quirkP);
|
||||||
if (!serversM.Update(tmp)) {
|
if (!serversM.Update(tmp)) {
|
||||||
info("Adding server '%s|%s|%s' CI: %s Quirks: %s", tmp->Address(), tmp->Model(), tmp->Description(), tmp->HasCI() ? "yes" : "no", tmp->HasQuirk() ? tmp->Quirks() : "none");
|
info("Adding server '%s|%s|%s' Bind: %s Filters: %s CI: %s Quirks: %s", tmp->Address(), tmp->Model(), tmp->Description(), !isempty(tmp->SrcAddress()) ? tmp->SrcAddress() : "default", !isempty(tmp->Filters()) ? tmp->Filters() : "none", tmp->HasCI() ? "yes" : "no", tmp->HasQuirk() ? tmp->Quirks() : "none");
|
||||||
serversM.Add(tmp);
|
serversM.Add(tmp);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -258,9 +297,9 @@ void cSatipDiscover::AddServer(const char *addrP, const char *modelP, const char
|
|||||||
FREE_POINTER(p);
|
FREE_POINTER(p);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
cSatipServer *tmp = new cSatipServer(addrP, modelP, descP);
|
cSatipServer *tmp = new cSatipServer(srcAddrP, addrP, portP, modelP, filtersP, descP, quirkP);
|
||||||
if (!serversM.Update(tmp)) {
|
if (!serversM.Update(tmp)) {
|
||||||
info("Adding server '%s|%s|%s' CI: %s Quirks: %s", tmp->Address(), tmp->Model(), tmp->Description(), tmp->HasCI() ? "yes" : "no", tmp->HasQuirk() ? tmp->Quirks() : "none");
|
info("Adding server '%s|%s|%s' Bind: %s Filters: %s CI: %s Quirks: %s", tmp->Address(), tmp->Model(), tmp->Description(), !isempty(tmp->SrcAddress()) ? tmp->SrcAddress() : "default", !isempty(tmp->Filters()) ? tmp->Filters() : "none", tmp->HasCI() ? "yes" : "no", tmp->HasQuirk() ? tmp->Quirks() : "none");
|
||||||
serversM.Add(tmp);
|
serversM.Add(tmp);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -317,6 +356,13 @@ cString cSatipDiscover::GetServerList(void)
|
|||||||
return serversM.List();
|
return serversM.List();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void cSatipDiscover::ActivateServer(cSatipServer *serverP, bool onOffP)
|
||||||
|
{
|
||||||
|
debug16("%s (, %d)", __PRETTY_FUNCTION__, onOffP);
|
||||||
|
cMutexLock MutexLock(&mutexM);
|
||||||
|
serversM.Activate(serverP, onOffP);
|
||||||
|
}
|
||||||
|
|
||||||
void cSatipDiscover::AttachServer(cSatipServer *serverP, int deviceIdP, int transponderP)
|
void cSatipDiscover::AttachServer(cSatipServer *serverP, int deviceIdP, int transponderP)
|
||||||
{
|
{
|
||||||
debug16("%s (, %d, %d)", __PRETTY_FUNCTION__, deviceIdP, transponderP);
|
debug16("%s (, %d, %d)", __PRETTY_FUNCTION__, deviceIdP, transponderP);
|
||||||
@@ -345,6 +391,13 @@ bool cSatipDiscover::HasServerCI(cSatipServer *serverP)
|
|||||||
return serversM.HasCI(serverP);
|
return serversM.HasCI(serverP);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cString cSatipDiscover::GetSourceAddress(cSatipServer *serverP)
|
||||||
|
{
|
||||||
|
debug16("%s", __PRETTY_FUNCTION__);
|
||||||
|
cMutexLock MutexLock(&mutexM);
|
||||||
|
return serversM.GetSrcAddress(serverP);
|
||||||
|
}
|
||||||
|
|
||||||
cString cSatipDiscover::GetServerAddress(cSatipServer *serverP)
|
cString cSatipDiscover::GetServerAddress(cSatipServer *serverP)
|
||||||
{
|
{
|
||||||
debug16("%s", __PRETTY_FUNCTION__);
|
debug16("%s", __PRETTY_FUNCTION__);
|
||||||
@@ -352,6 +405,13 @@ cString cSatipDiscover::GetServerAddress(cSatipServer *serverP)
|
|||||||
return serversM.GetAddress(serverP);
|
return serversM.GetAddress(serverP);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int cSatipDiscover::GetServerPort(cSatipServer *serverP)
|
||||||
|
{
|
||||||
|
debug16("%s", __PRETTY_FUNCTION__);
|
||||||
|
cMutexLock MutexLock(&mutexM);
|
||||||
|
return serversM.GetPort(serverP);
|
||||||
|
}
|
||||||
|
|
||||||
int cSatipDiscover::NumProvidedSystems(void)
|
int cSatipDiscover::NumProvidedSystems(void)
|
||||||
{
|
{
|
||||||
debug16("%s", __PRETTY_FUNCTION__);
|
debug16("%s", __PRETTY_FUNCTION__);
|
||||||
|
22
discover.h
22
discover.h
@@ -21,16 +21,24 @@
|
|||||||
|
|
||||||
class cSatipDiscoverServer : public cListObject {
|
class cSatipDiscoverServer : public cListObject {
|
||||||
private:
|
private:
|
||||||
|
int ipPortM;
|
||||||
|
int quirkM;
|
||||||
|
cString srcAddressM;
|
||||||
cString ipAddressM;
|
cString ipAddressM;
|
||||||
cString descriptionM;
|
cString descriptionM;
|
||||||
cString modelM;
|
cString modelM;
|
||||||
|
cString filtersM;
|
||||||
public:
|
public:
|
||||||
cSatipDiscoverServer(const char *ipAddressP, const char *modelP, const char *descriptionP)
|
cSatipDiscoverServer(const char *srcAddressP, const char *ipAddressP, const int ipPortP, const char *modelP, const char *filtersP, const char *descriptionP, const int quirkP)
|
||||||
{
|
{
|
||||||
ipAddressM = ipAddressP; modelM = modelP; descriptionM = descriptionP;
|
srcAddressM = srcAddressP; ipAddressM = ipAddressP; ipPortM = ipPortP; modelM = modelP; filtersM = filtersP; descriptionM = descriptionP; quirkM = quirkP;
|
||||||
}
|
}
|
||||||
|
int IpPort(void) { return ipPortM; }
|
||||||
|
int Quirk(void) { return quirkM; }
|
||||||
|
const char *SrcAddress(void) { return *srcAddressM; }
|
||||||
const char *IpAddress(void) { return *ipAddressM; }
|
const char *IpAddress(void) { return *ipAddressM; }
|
||||||
const char *Model(void) { return *modelM; }
|
const char *Model(void) { return *modelM; }
|
||||||
|
const char *Filters(void) { return *filtersM; }
|
||||||
const char *Description(void) { return *descriptionM; }
|
const char *Description(void) { return *descriptionM; }
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -47,9 +55,11 @@ private:
|
|||||||
eCleanupTimeoutMs = 124000 // in milliseoonds
|
eCleanupTimeoutMs = 124000 // in milliseoonds
|
||||||
};
|
};
|
||||||
static cSatipDiscover *instanceS;
|
static cSatipDiscover *instanceS;
|
||||||
|
static size_t HeaderCallback(char *ptrP, size_t sizeP, size_t nmembP, void *dataP);
|
||||||
static size_t DataCallback(char *ptrP, size_t sizeP, size_t nmembP, void *dataP);
|
static size_t DataCallback(char *ptrP, size_t sizeP, size_t nmembP, void *dataP);
|
||||||
static int DebugCallback(CURL *handleP, curl_infotype typeP, char *dataP, size_t sizeP, void *userPtrP);
|
static int DebugCallback(CURL *handleP, curl_infotype typeP, char *dataP, size_t sizeP, void *userPtrP);
|
||||||
cMutex mutexM;
|
cMutex mutexM;
|
||||||
|
cSatipMemoryBuffer headerBufferM;
|
||||||
cSatipMemoryBuffer dataBufferM;
|
cSatipMemoryBuffer dataBufferM;
|
||||||
cSatipMsearch msearchM;
|
cSatipMsearch msearchM;
|
||||||
cStringList probeUrlListM;
|
cStringList probeUrlListM;
|
||||||
@@ -59,8 +69,9 @@ private:
|
|||||||
cSatipServers serversM;
|
cSatipServers serversM;
|
||||||
void Activate(void);
|
void Activate(void);
|
||||||
void Deactivate(void);
|
void Deactivate(void);
|
||||||
void ParseDeviceInfo(const char *addrP);
|
int ParseRtspPort(void);
|
||||||
void AddServer(const char *addrP, const char *modelP, const char *descP);
|
void ParseDeviceInfo(const char *addrP, const int portP);
|
||||||
|
void AddServer(const char *srcAddrP, const char *addrP, const int portP, const char *modelP, const char *filtersP, const char *descP, const int quirkP);
|
||||||
void Fetch(const char *urlP);
|
void Fetch(const char *urlP);
|
||||||
// constructor
|
// constructor
|
||||||
cSatipDiscover();
|
cSatipDiscover();
|
||||||
@@ -83,11 +94,14 @@ public:
|
|||||||
cSatipServer *GetServer(cSatipServer *serverP);
|
cSatipServer *GetServer(cSatipServer *serverP);
|
||||||
cSatipServers *GetServers(void);
|
cSatipServers *GetServers(void);
|
||||||
cString GetServerString(cSatipServer *serverP);
|
cString GetServerString(cSatipServer *serverP);
|
||||||
|
void ActivateServer(cSatipServer *serverP, bool onOffP);
|
||||||
void AttachServer(cSatipServer *serverP, int deviceIdP, int transponderP);
|
void AttachServer(cSatipServer *serverP, int deviceIdP, int transponderP);
|
||||||
void DetachServer(cSatipServer *serverP, int deviceIdP, int transponderP);
|
void DetachServer(cSatipServer *serverP, int deviceIdP, int transponderP);
|
||||||
bool IsServerQuirk(cSatipServer *serverP, int quirkP);
|
bool IsServerQuirk(cSatipServer *serverP, int quirkP);
|
||||||
bool HasServerCI(cSatipServer *serverP);
|
bool HasServerCI(cSatipServer *serverP);
|
||||||
cString GetServerAddress(cSatipServer *serverP);
|
cString GetServerAddress(cSatipServer *serverP);
|
||||||
|
cString GetSourceAddress(cSatipServer *serverP);
|
||||||
|
int GetServerPort(cSatipServer *serverP);
|
||||||
cString GetServerList(void);
|
cString GetServerList(void);
|
||||||
int NumProvidedSystems(void);
|
int NumProvidedSystems(void);
|
||||||
|
|
||||||
|
@@ -29,7 +29,7 @@ cSatipMsearch::cSatipMsearch(cSatipDiscoverIf &discoverP)
|
|||||||
memset(bufferM, 0, bufferLenM);
|
memset(bufferM, 0, bufferLenM);
|
||||||
else
|
else
|
||||||
error("Cannot create Msearch buffer!");
|
error("Cannot create Msearch buffer!");
|
||||||
if (!Open(eDiscoveryPort))
|
if (!Open(eDiscoveryPort, true))
|
||||||
error("Cannot open Msearch port!");
|
error("Cannot open Msearch port!");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -100,6 +100,11 @@ void cSatipMsearch::Process(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void cSatipMsearch::Process(unsigned char *dataP, int lengthP)
|
||||||
|
{
|
||||||
|
debug16("%s", __PRETTY_FUNCTION__);
|
||||||
|
}
|
||||||
|
|
||||||
cString cSatipMsearch::ToString(void) const
|
cString cSatipMsearch::ToString(void) const
|
||||||
{
|
{
|
||||||
return "MSearch";
|
return "MSearch";
|
||||||
|
@@ -34,6 +34,7 @@ public:
|
|||||||
public:
|
public:
|
||||||
virtual int GetFd(void);
|
virtual int GetFd(void);
|
||||||
virtual void Process(void);
|
virtual void Process(void);
|
||||||
|
virtual void Process(unsigned char *dataP, int lengthP);
|
||||||
virtual cString ToString(void) const;
|
virtual cString ToString(void) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
345
param.c
345
param.c
@@ -163,34 +163,345 @@ cString GetTransponderUrlParameters(const cChannel *channelP)
|
|||||||
dtp.SetModulation(QPSK);
|
dtp.SetModulation(QPSK);
|
||||||
dtp.SetRollOff(ROLLOFF_35);
|
dtp.SetRollOff(ROLLOFF_35);
|
||||||
}
|
}
|
||||||
|
if ((channelP->Rid() % 100) > 0)
|
||||||
|
q += snprintf(q, STBUFLEFT, "&fe=%d", channelP->Rid() % 100);
|
||||||
|
ST(" S *") q += snprintf(q, STBUFLEFT, "src=%d&", ((src > 0) && (src <= 255)) ? src : 1);
|
||||||
|
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, "&src=%d", ((src > 0) && (src <= 255)) ? src : 1);
|
|
||||||
ST(" S *") q += snprintf(q, STBUFLEFT, "&sr=%d", channelP->Srate());
|
|
||||||
ST("C 1") q += snprintf(q, STBUFLEFT, "&sr=%d", channelP->Srate());
|
|
||||||
ST(" S *") q += snprintf(q, STBUFLEFT, "&pol=%c", tolower(dtp.Polarization()));
|
ST(" S *") q += snprintf(q, STBUFLEFT, "&pol=%c", tolower(dtp.Polarization()));
|
||||||
ST("C T2") q += snprintf(q, STBUFLEFT, "&plp=%d", dtp.StreamId());
|
ST(" S *") q += PrintUrlString(q, STBUFLEFT, dtp.RollOff(), SatipRollOffValues);
|
||||||
ST(" T2") q += snprintf(q, STBUFLEFT, "&t2id=%d", dtp.T2SystemId());
|
|
||||||
ST("C 2") q += snprintf(q, STBUFLEFT, "&c2tft=%d", C2TuningFrequencyType);
|
ST("C 2") q += snprintf(q, STBUFLEFT, "&c2tft=%d", C2TuningFrequencyType);
|
||||||
ST("C 2") q += snprintf(q, STBUFLEFT, "&ds=%d", DataSlice);
|
|
||||||
ST("C 1") q += PrintUrlString(q, STBUFLEFT, dtp.Inversion(), SatipInversionValues);
|
|
||||||
ST(" T2") q += PrintUrlString(q, STBUFLEFT, dtp.SisoMiso(), SatipSisoMisoValues);
|
|
||||||
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(" T*") q += PrintUrlString(q, STBUFLEFT, dtp.Guard(), SatipGuardValues);
|
|
||||||
ST("CST*") q += PrintUrlString(q, STBUFLEFT, dtp.CoderateH(), SatipCodeRateValues);
|
|
||||||
ST(" S *") q += PrintUrlString(q, STBUFLEFT, dtp.Pilot(), SatipPilotValues);
|
|
||||||
ST(" S *") q += PrintUrlString(q, STBUFLEFT, dtp.Modulation(), SatipModulationValues);
|
|
||||||
ST(" T*") q += PrintUrlString(q, STBUFLEFT, dtp.Modulation(), SatipModulationValues);
|
|
||||||
ST("C 1") q += PrintUrlString(q, STBUFLEFT, dtp.Modulation(), SatipModulationValues);
|
|
||||||
ST(" S *") q += PrintUrlString(q, STBUFLEFT, dtp.RollOff(), SatipRollOffValues);
|
|
||||||
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(" T*") q += PrintUrlString(q, STBUFLEFT, dtp.Transmission(), SatipTransmissionValues);
|
||||||
if ((channelP->Rid() % 100) > 0)
|
ST(" S *") q += PrintUrlString(q, STBUFLEFT, dtp.Modulation(), SatipModulationValues);
|
||||||
snprintf(q, STBUFLEFT, "&fe=%d", channelP->Rid() % 100);
|
ST(" T*") q += PrintUrlString(q, STBUFLEFT, dtp.Modulation(), SatipModulationValues);
|
||||||
|
ST("C 1") q += PrintUrlString(q, STBUFLEFT, dtp.Modulation(), SatipModulationValues);
|
||||||
|
ST(" S *") q += PrintUrlString(q, STBUFLEFT, dtp.Pilot(), SatipPilotValues);
|
||||||
|
ST(" S *") q += snprintf(q, STBUFLEFT, "&sr=%d", channelP->Srate());
|
||||||
|
ST("C 1") q += snprintf(q, STBUFLEFT, "&sr=%d", channelP->Srate());
|
||||||
|
ST(" T*") q += PrintUrlString(q, STBUFLEFT, dtp.Guard(), SatipGuardValues);
|
||||||
|
ST("CST*") q += PrintUrlString(q, STBUFLEFT, dtp.CoderateH(), SatipCodeRateValues);
|
||||||
|
ST("C 2") q += snprintf(q, STBUFLEFT, "&ds=%d", DataSlice);
|
||||||
|
ST("C T2") q += snprintf(q, STBUFLEFT, "&plp=%d", dtp.StreamId());
|
||||||
|
ST(" T2") q += snprintf(q, STBUFLEFT, "&t2id=%d", dtp.T2SystemId());
|
||||||
|
ST(" T2") q += PrintUrlString(q, STBUFLEFT, dtp.SisoMiso(), SatipSisoMisoValues);
|
||||||
|
ST("C 1") q += PrintUrlString(q, STBUFLEFT, dtp.Inversion(), SatipInversionValues);
|
||||||
#undef ST
|
#undef ST
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cString GetTnrUrlParameters(const cChannel *channelP)
|
||||||
|
{
|
||||||
|
if (channelP) {
|
||||||
|
cDvbTransponderParameters dtp(channelP->Parameters());
|
||||||
|
eTrackType track = cDevice::PrimaryDevice()->GetCurrentAudioTrack();
|
||||||
|
|
||||||
|
// TunerType: Byte;
|
||||||
|
// 0 = cable, 1 = satellite, 2 = terrestrial, 3 = atsc, 4 = iptv, 5 = stream (URL, DVBViewer GE)
|
||||||
|
int TunerType = 0;
|
||||||
|
if (channelP->IsCable())
|
||||||
|
TunerType = 0;
|
||||||
|
else if (channelP->IsSat())
|
||||||
|
TunerType = 1;
|
||||||
|
else if (channelP->IsTerr())
|
||||||
|
TunerType = 2;
|
||||||
|
else if (channelP->IsAtsc())
|
||||||
|
TunerType = 3;
|
||||||
|
|
||||||
|
// Frequency: DWord;
|
||||||
|
// DVB-S: MHz if < 1000000, kHz if >= 1000000
|
||||||
|
// DVB-T/C, ATSC: kHz
|
||||||
|
// IPTV: IP address Byte3.Byte2.Byte1.Byte0
|
||||||
|
int Frequency = channelP->Frequency() / 1000;
|
||||||
|
|
||||||
|
// Symbolrate: DWord;
|
||||||
|
// DVB S/C: in kSym/s
|
||||||
|
// DVB-T, ATSC: 0
|
||||||
|
// IPTV: Port
|
||||||
|
int Symbolrate = (channelP->IsSat() || channelP->IsCable()) ? channelP->Srate() : 0;
|
||||||
|
|
||||||
|
// LNB_LOF: Word;
|
||||||
|
// DVB-S: Local oscillator frequency of the LNB
|
||||||
|
// DVB-T/C, ATSC: 0
|
||||||
|
// IPTV: Byte0 and Byte1 of Source IP
|
||||||
|
int LNB_LOF = channelP->IsSat() ? Setup.LnbSLOF : 0;
|
||||||
|
|
||||||
|
// Tone: Byte;
|
||||||
|
// 0 = off, 1 = 22 khz
|
||||||
|
int Tone = (channelP->Frequency() < Setup.LnbSLOF) ? 0 : 1;
|
||||||
|
|
||||||
|
// Polarity: Byte;
|
||||||
|
// DVB-S polarity: 0 = horizontal, 1 = vertical, 2 = circular left, 3 = circular right
|
||||||
|
// DVB-C modulation: 0 = Auto, 1 = 16QAM, 2 = 32QAM, 3 = 64QAM, 4 = 128QAM, 5 = 256 QAM
|
||||||
|
// DVB-T bandwidth: 0 = 6 MHz, 1 = 7 MHz, 2 = 8 MHz
|
||||||
|
// IPTV: Byte3 of SourceIP
|
||||||
|
int Polarity = 0;
|
||||||
|
if (channelP->IsSat()) {
|
||||||
|
switch (tolower(dtp.Polarization())) {
|
||||||
|
case 'h':
|
||||||
|
Polarity = 0;
|
||||||
|
break;
|
||||||
|
case 'v':
|
||||||
|
Polarity = 1;
|
||||||
|
break;
|
||||||
|
case 'l':
|
||||||
|
Polarity = 2;
|
||||||
|
break;
|
||||||
|
case 'r':
|
||||||
|
Polarity = 3;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (channelP->IsCable()) {
|
||||||
|
switch (dtp.Modulation()) {
|
||||||
|
case 999:
|
||||||
|
Polarity = 0;
|
||||||
|
break;
|
||||||
|
case 16:
|
||||||
|
Polarity = 1;
|
||||||
|
break;
|
||||||
|
case 32:
|
||||||
|
Polarity = 2;
|
||||||
|
break;
|
||||||
|
case 64:
|
||||||
|
Polarity = 3;
|
||||||
|
break;
|
||||||
|
case 128:
|
||||||
|
Polarity = 4;
|
||||||
|
break;
|
||||||
|
case 256:
|
||||||
|
Polarity = 5;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (channelP->IsTerr()) {
|
||||||
|
switch (dtp.Bandwidth()) {
|
||||||
|
case 6:
|
||||||
|
Polarity = 0;
|
||||||
|
break;
|
||||||
|
case 7:
|
||||||
|
Polarity = 1;
|
||||||
|
break;
|
||||||
|
case 8:
|
||||||
|
Polarity = 2;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// DiSEqC: Byte;
|
||||||
|
// 0 = None
|
||||||
|
// 1 = Pos A (mostly translated to PosA/OptA)
|
||||||
|
// 2 = Pos B (mostly translated to PosB/OptA)
|
||||||
|
// 3 = PosA/OptA
|
||||||
|
// 4 = PosB/OptA
|
||||||
|
// 5 = PosA/OptB
|
||||||
|
// 6 = PosB/OptB
|
||||||
|
// 7 = Preset Position (DiSEqC 1.2, see DiSEqCExt)
|
||||||
|
// 8 = Angular Position (DiSEqC 1.2, see DiSEqCExt)
|
||||||
|
// 9 = DiSEqC Command Sequence (see DiSEqCExt)
|
||||||
|
int DiSEqC = 0;
|
||||||
|
|
||||||
|
// FEC: Byte;
|
||||||
|
// 0 = Auto
|
||||||
|
// 1 = 1/2
|
||||||
|
// 2 = 2/3
|
||||||
|
// 3 = 3/4
|
||||||
|
// 4 = 5/6
|
||||||
|
// 5 = 7/8
|
||||||
|
// 6 = 8/9
|
||||||
|
// 7 = 3/5
|
||||||
|
// 8 = 4/5
|
||||||
|
// 9 = 9/10
|
||||||
|
// IPTV: Byte2 of SourceIP
|
||||||
|
// DVB C/T, ATSC: 0
|
||||||
|
int FEC = 0;
|
||||||
|
if (channelP->IsSat()) {
|
||||||
|
switch (dtp.CoderateH()) {
|
||||||
|
case 999:
|
||||||
|
FEC = 0;
|
||||||
|
break;
|
||||||
|
case 12:
|
||||||
|
FEC = 1;
|
||||||
|
break;
|
||||||
|
case 23:
|
||||||
|
FEC = 2;
|
||||||
|
break;
|
||||||
|
case 34:
|
||||||
|
FEC = 3;
|
||||||
|
break;
|
||||||
|
case 56:
|
||||||
|
FEC = 4;
|
||||||
|
break;
|
||||||
|
case 78:
|
||||||
|
FEC = 5;
|
||||||
|
break;
|
||||||
|
case 89:
|
||||||
|
FEC = 6;
|
||||||
|
break;
|
||||||
|
case 35:
|
||||||
|
FEC = 7;
|
||||||
|
break;
|
||||||
|
case 45:
|
||||||
|
FEC = 8;
|
||||||
|
break;
|
||||||
|
case 910:
|
||||||
|
FEC = 9;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Audio_PID: Word;
|
||||||
|
int Audio_PID = channelP->Apid(0);
|
||||||
|
if (IS_AUDIO_TRACK(track))
|
||||||
|
Audio_PID = channelP->Apid(int(track - ttAudioFirst));
|
||||||
|
else if (IS_DOLBY_TRACK(track))
|
||||||
|
Audio_PID = channelP->Dpid(int(track - ttDolbyFirst));
|
||||||
|
|
||||||
|
// Video_PID: Word;
|
||||||
|
int Video_PID = channelP->Vpid();
|
||||||
|
|
||||||
|
// PMT_PID: Word;
|
||||||
|
int PMT_PID = channelP->Ppid();
|
||||||
|
|
||||||
|
// Service_ID: Word;
|
||||||
|
int Service_ID = channelP->Sid();
|
||||||
|
|
||||||
|
// SatModulation: Byte;
|
||||||
|
// Bit 0..1: satellite modulation. 0 = Auto, 1 = QPSK, 2 = 8PSK, 3 = 16QAM or APSK for DVB-S2
|
||||||
|
// Bit 2: modulation system. 0 = DVB-S/T/C, 1 = DVB-S2/T2/C2
|
||||||
|
// Bit 3..4: DVB-S2: roll-off. 0 = 0.35, 1 = 0.25, 2 = 0.20, 3 = reserved
|
||||||
|
// Bit 5..6: spectral inversion, 0 = undefined, 1 = auto, 2 = normal, 3 = inverted
|
||||||
|
// Bit 7: DVB-S2: pilot symbols, 0 = off, 1 = on
|
||||||
|
// DVB-T2: DVB-T2 Lite, 0 = off, 1 = on
|
||||||
|
int SatModulation = 0;
|
||||||
|
if (channelP->IsSat() && dtp.System()) {
|
||||||
|
switch (dtp.Modulation()) {
|
||||||
|
case 999:
|
||||||
|
SatModulation |= (0 & 0x3) << 0;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
SatModulation |= (1 & 0x3) << 0;
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
SatModulation |= (2 & 0x3) << 0;
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
SatModulation |= (3 & 0x3) << 0;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SatModulation |= (dtp.System() & 0x1) << 2;
|
||||||
|
if (channelP->IsSat() && dtp.System()) {
|
||||||
|
switch (dtp.RollOff()) {
|
||||||
|
case 35:
|
||||||
|
SatModulation |= (0 & 0x3) << 3;
|
||||||
|
break;
|
||||||
|
case 25:
|
||||||
|
SatModulation |= (1 & 0x3) << 3;
|
||||||
|
break;
|
||||||
|
case 20:
|
||||||
|
SatModulation |= (2 & 0x3) << 3;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
switch (dtp.Inversion()) {
|
||||||
|
case 999:
|
||||||
|
SatModulation |= (1 & 0x3) << 5;
|
||||||
|
break;
|
||||||
|
case 0:
|
||||||
|
SatModulation |= (2 & 0x3) << 5;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
SatModulation |= (3 & 0x3) << 5;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (channelP->IsSat() && dtp.System()) {
|
||||||
|
switch (dtp.Pilot()) {
|
||||||
|
case 0:
|
||||||
|
SatModulation |= (0 & 0x1) << 7;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
SatModulation |= (1 & 0x1) << 7;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// DiSEqCExt: Word;
|
||||||
|
// DiSEqC Extension, meaning depends on DiSEqC
|
||||||
|
// DiSEqC = 0..6: 0
|
||||||
|
// DiSEqC = 7: Preset Position (DiSEqC 1.2)
|
||||||
|
// DiSEqC = 8: Orbital Position (DiSEqC 1.2, USALS, for calculating motor angle)
|
||||||
|
// Same format as OrbitalPos above
|
||||||
|
// DiSEQC = 9: Orbital Position referencing DiSEqC sequence defined in DiSEqC.xml/ini
|
||||||
|
// Same format as OrbitalPos above
|
||||||
|
int DiSEqCExt = 0;
|
||||||
|
|
||||||
|
// Flags: Byte;
|
||||||
|
// Bit 0: 1 = encrypted channel
|
||||||
|
// Bit 1: reserved, set to 0
|
||||||
|
// Bit 2: 1 = channel broadcasts RDS data
|
||||||
|
// Bit 3: 1 = channel is a video service (even if the Video PID is temporarily = 0)
|
||||||
|
// Bit 4: 1 = channel is an audio service (even if the Audio PID is temporarily = 0)
|
||||||
|
// Bit 5: 1 = audio has a different samplerate than 48 KHz
|
||||||
|
// Bit 6: 1 = bandstacking, internally polarisation is always set to H
|
||||||
|
// Bit 7: 1 = channel entry is an additional audio track of the preceding
|
||||||
|
// channel with bit 7 = 0
|
||||||
|
int Flags = (channelP->Ca() > 0xFF) ? 1 : 0;
|
||||||
|
|
||||||
|
// ChannelGroup: Byte;
|
||||||
|
// 0 = Group A, 1 = Group B, 2 = Group C etc.
|
||||||
|
int ChannelGroup = 0;
|
||||||
|
|
||||||
|
// TransportStream_ID: Word;
|
||||||
|
int TransportStream_ID = channelP->Tid();
|
||||||
|
|
||||||
|
// OriginalNetwork_ID: Word;
|
||||||
|
int OriginalNetwork_ID = channelP->Nid();
|
||||||
|
|
||||||
|
// Substream: Word;
|
||||||
|
// DVB-S/C/T, ATSC, IPTV: 0
|
||||||
|
// DVB-T2: 0 = PLP_ID not set, 1..256: PLP_ID + 1, 257... reserved
|
||||||
|
int Substream = (channelP->IsTerr() && dtp.System()) ? dtp.StreamId() - 1 : 0;
|
||||||
|
|
||||||
|
// OrbitalPos: Word;
|
||||||
|
// DVB-S: orbital position x 10, 0 = undefined, 1..1800 east, 1801..3599 west (1°W = 3599)
|
||||||
|
// DVB-C: 4000..4999
|
||||||
|
// DVB-T: 5000..5999
|
||||||
|
// ATSC: 6000..6999
|
||||||
|
// IPTV: 7000..7999
|
||||||
|
// Stream: 8000..8999
|
||||||
|
int OrbitalPos = 0;
|
||||||
|
if (channelP->IsSat()) {
|
||||||
|
OrbitalPos = cSource::Position(channelP->Source());
|
||||||
|
if (OrbitalPos != 3600)
|
||||||
|
OrbitalPos += 1800;
|
||||||
|
}
|
||||||
|
|
||||||
|
return cString::sprintf("%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d",
|
||||||
|
TunerType, Frequency, Symbolrate, LNB_LOF, Tone, Polarity, DiSEqC, FEC, Audio_PID, Video_PID, PMT_PID, Service_ID,
|
||||||
|
SatModulation, DiSEqCExt, Flags, ChannelGroup, TransportStream_ID, OriginalNetwork_ID, Substream, OrbitalPos);
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
1
param.h
1
param.h
@@ -11,5 +11,6 @@
|
|||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
|
||||||
cString GetTransponderUrlParameters(const cChannel *channelP);
|
cString GetTransponderUrlParameters(const cChannel *channelP);
|
||||||
|
cString GetTnrUrlParameters(const cChannel *channelP);
|
||||||
|
|
||||||
#endif // __SATIP_PARAM_H
|
#endif // __SATIP_PARAM_H
|
||||||
|
28
po/ca_ES.po
28
po/ca_ES.po
@@ -1,14 +1,14 @@
|
|||||||
# VDR plugin language source file.
|
# VDR plugin language source file.
|
||||||
# Copyright (C) 2007-2015 Rolf Ahrenberg
|
# Copyright (C) 2007-2018 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-2015
|
# Gabriel Bonich, 2014-2017
|
||||||
#
|
#
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: vdr-satip 2.2.3\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: 2015-04-26 04:26+0300\n"
|
"POT-Creation-Date: 2018-04-15 04:15+0300+0300\n"
|
||||||
"PO-Revision-Date: 2015-04-26 04:26+0300\n"
|
"PO-Revision-Date: 2018-04-15 04:15+0300+0300\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"
|
||||||
@@ -85,6 +85,15 @@ msgstr "Normal"
|
|||||||
msgid "high"
|
msgid "high"
|
||||||
msgstr "Alt"
|
msgstr "Alt"
|
||||||
|
|
||||||
|
msgid "Unicast"
|
||||||
|
msgstr "Unicast"
|
||||||
|
|
||||||
|
msgid "Multicast"
|
||||||
|
msgstr "Multicast"
|
||||||
|
|
||||||
|
msgid "RTP-over-TCP"
|
||||||
|
msgstr "RTP-per sobre-TCP"
|
||||||
|
|
||||||
msgid "Button$Devices"
|
msgid "Button$Devices"
|
||||||
msgstr "Dispositius"
|
msgstr "Dispositius"
|
||||||
|
|
||||||
@@ -178,6 +187,15 @@ msgstr "Filtra"
|
|||||||
msgid "Define an ill-behaving filter to be blacklisted."
|
msgid "Define an ill-behaving filter to be blacklisted."
|
||||||
msgstr "Definir un filtre mal comportar a la llista negra."
|
msgstr "Definir un filtre mal comportar a la llista negra."
|
||||||
|
|
||||||
|
msgid "Transport mode"
|
||||||
|
msgstr "Tipus de Transmissió"
|
||||||
|
|
||||||
|
msgid ""
|
||||||
|
"Define which transport mode shall be used.\n"
|
||||||
|
"\n"
|
||||||
|
"Unicast, Multicast, RTP-over-TCP"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Active SAT>IP servers:"
|
msgid "Active SAT>IP servers:"
|
||||||
msgstr "Activa SAT>IP servers:"
|
msgstr "Activa SAT>IP servers:"
|
||||||
|
|
||||||
|
39
po/de_DE.po
39
po/de_DE.po
@@ -1,14 +1,14 @@
|
|||||||
# VDR plugin language source file.
|
# VDR plugin language source file.
|
||||||
# Copyright (C) 2007-2015 Rolf Ahrenberg
|
# Copyright (C) 2007-2018 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-2015
|
# Frank Neumann, 2014-2017
|
||||||
#
|
#
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: vdr-satip 2.2.3\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: 2015-04-26 04:26+0300\n"
|
"POT-Creation-Date: 2018-04-15 04:15+0300+0300\n"
|
||||||
"PO-Revision-Date: 2015-04-26 04:26+0300\n"
|
"PO-Revision-Date: 2018-04-15 04:15+0300+0300\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"
|
||||||
@@ -85,11 +85,20 @@ msgstr "normal"
|
|||||||
msgid "high"
|
msgid "high"
|
||||||
msgstr "hoch"
|
msgstr "hoch"
|
||||||
|
|
||||||
|
msgid "Unicast"
|
||||||
|
msgstr "Unicast"
|
||||||
|
|
||||||
|
msgid "Multicast"
|
||||||
|
msgstr "Multicast"
|
||||||
|
|
||||||
|
msgid "RTP-over-TCP"
|
||||||
|
msgstr "RTP-over-TCP"
|
||||||
|
|
||||||
msgid "Button$Devices"
|
msgid "Button$Devices"
|
||||||
msgstr "Geräte"
|
msgstr "Geräte"
|
||||||
|
|
||||||
msgid "Operating mode"
|
msgid "Operating mode"
|
||||||
msgstr "Betriebsmodus"
|
msgstr "Betriebsart"
|
||||||
|
|
||||||
msgid ""
|
msgid ""
|
||||||
"Define the used operating mode for all SAT>IP devices:\n"
|
"Define the used operating mode for all SAT>IP devices:\n"
|
||||||
@@ -99,7 +108,7 @@ msgid ""
|
|||||||
"normal - devices are working within normal parameters\n"
|
"normal - devices are working within normal parameters\n"
|
||||||
"high - devices are working at the highest priority"
|
"high - devices are working at the highest priority"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Bestimme den Betriebsmodus 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 abgeschaltet\n"
|
||||||
"niedrig - Geräte arbeiten mit geringster Priorität\n"
|
"niedrig - Geräte arbeiten mit geringster Priorität\n"
|
||||||
@@ -170,13 +179,25 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"Bestimme die Anzahl der Abschnittsfilter die deaktiviert werden sollen.\n"
|
"Bestimme die Anzahl der Abschnittsfilter die deaktiviert werden sollen.\n"
|
||||||
"\n"
|
"\n"
|
||||||
"Bestimmte Abschnittsfilter können unerwünschtes Verhalten mit VDR, z.B. falsche Zeit-Synchronisation, verursachen. Durch das Ausblenden einzelner Filter können nützliche Daten dieser Abschnitte für den VDR erhalten werden."
|
"Bestimmte Abschnittsfilter können unerwünschtes Verhalten mit VDR, z.B. falsche Zeit-Synchronisation, verursachen. Durch das Ausblenden einzelner Filter können nützliche Daten dieser Abschnitte für den VDR erhalten bleiben."
|
||||||
|
|
||||||
msgid "Filter"
|
msgid "Filter"
|
||||||
msgstr "Filter"
|
msgstr "Filter"
|
||||||
|
|
||||||
msgid "Define an ill-behaving filter to be blacklisted."
|
msgid "Define an ill-behaving filter to be blacklisted."
|
||||||
msgstr "Bestimme einen fehlerhaften Filter der ausgeblendet werden soll."
|
msgstr "Bestimme fehlerhafte Filter die ausgeblendet werden sollen."
|
||||||
|
|
||||||
|
msgid "Transport mode"
|
||||||
|
msgstr "Übertragungsart"
|
||||||
|
|
||||||
|
msgid ""
|
||||||
|
"Define which transport mode shall be used.\n"
|
||||||
|
"\n"
|
||||||
|
"Unicast, Multicast, RTP-over-TCP"
|
||||||
|
msgstr ""
|
||||||
|
"Lege die gewünschte Übertragungsart fest.\n"
|
||||||
|
"\n"
|
||||||
|
"Unicast, Multicast, RTP-over-TCP"
|
||||||
|
|
||||||
msgid "Active SAT>IP servers:"
|
msgid "Active SAT>IP servers:"
|
||||||
msgstr "Aktive SAT>IP Server:"
|
msgstr "Aktive SAT>IP Server:"
|
||||||
|
28
po/es_ES.po
28
po/es_ES.po
@@ -1,14 +1,14 @@
|
|||||||
# VDR plugin language source file.
|
# VDR plugin language source file.
|
||||||
# Copyright (C) 2007-2015 Rolf Ahrenberg
|
# Copyright (C) 2007-2018 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-2015
|
# Gabriel Bonich, 2014-2017
|
||||||
#
|
#
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: vdr-satip 2.2.3\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: 2015-04-26 04:26+0300\n"
|
"POT-Creation-Date: 2018-04-15 04:15+0300+0300\n"
|
||||||
"PO-Revision-Date: 2015-04-26 04:26+0300\n"
|
"PO-Revision-Date: 2018-04-15 04:15+0300+0300\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"
|
||||||
@@ -85,6 +85,15 @@ msgstr "Normal"
|
|||||||
msgid "high"
|
msgid "high"
|
||||||
msgstr "Alto"
|
msgstr "Alto"
|
||||||
|
|
||||||
|
msgid "Unicast"
|
||||||
|
msgstr "Unicast"
|
||||||
|
|
||||||
|
msgid "Multicast"
|
||||||
|
msgstr "Multicast"
|
||||||
|
|
||||||
|
msgid "RTP-over-TCP"
|
||||||
|
msgstr "RTP-antes que-TCP"
|
||||||
|
|
||||||
msgid "Button$Devices"
|
msgid "Button$Devices"
|
||||||
msgstr "Dispositivos"
|
msgstr "Dispositivos"
|
||||||
|
|
||||||
@@ -178,6 +187,15 @@ msgstr "Filtra"
|
|||||||
msgid "Define an ill-behaving filter to be blacklisted."
|
msgid "Define an ill-behaving filter to be blacklisted."
|
||||||
msgstr "Define un filtro para poner en la lista negra."
|
msgstr "Define un filtro para poner en la lista negra."
|
||||||
|
|
||||||
|
msgid "Transport mode"
|
||||||
|
msgstr "Tipo de Transmisión"
|
||||||
|
|
||||||
|
msgid ""
|
||||||
|
"Define which transport mode shall be used.\n"
|
||||||
|
"\n"
|
||||||
|
"Unicast, Multicast, RTP-over-TCP"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Active SAT>IP servers:"
|
msgid "Active SAT>IP servers:"
|
||||||
msgstr "Activa SAT>IP servers:"
|
msgstr "Activa SAT>IP servers:"
|
||||||
|
|
||||||
|
31
po/fi_FI.po
31
po/fi_FI.po
@@ -1,14 +1,14 @@
|
|||||||
# VDR plugin language source file.
|
# VDR plugin language source file.
|
||||||
# Copyright (C) 2007-2015 Rolf Ahrenberg
|
# Copyright (C) 2007-2018 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
|
# Rolf Ahrenberg, 2015-2017
|
||||||
#
|
#
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: vdr-satip 2.2.3\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: 2015-04-26 04:26+0300\n"
|
"POT-Creation-Date: 2018-04-15 04:15+0300+0300\n"
|
||||||
"PO-Revision-Date: 2015-04-26 04:26+0300\n"
|
"PO-Revision-Date: 2018-04-15 04:15+0300+0300\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"
|
||||||
@@ -85,6 +85,15 @@ msgstr "normaali"
|
|||||||
msgid "high"
|
msgid "high"
|
||||||
msgstr "korkea"
|
msgstr "korkea"
|
||||||
|
|
||||||
|
msgid "Unicast"
|
||||||
|
msgstr "Unicast"
|
||||||
|
|
||||||
|
msgid "Multicast"
|
||||||
|
msgstr "Multicast"
|
||||||
|
|
||||||
|
msgid "RTP-over-TCP"
|
||||||
|
msgstr "RTP-over-TCP"
|
||||||
|
|
||||||
msgid "Button$Devices"
|
msgid "Button$Devices"
|
||||||
msgstr "Laitteet"
|
msgstr "Laitteet"
|
||||||
|
|
||||||
@@ -177,6 +186,18 @@ msgstr "Suodatin"
|
|||||||
msgid "Define an ill-behaving filter to be blacklisted."
|
msgid "Define an ill-behaving filter to be blacklisted."
|
||||||
msgstr "Määrittele käytöstä poistettava suodatin, joka lisätään mustalle listalle."
|
msgstr "Määrittele käytöstä poistettava suodatin, joka lisätään mustalle listalle."
|
||||||
|
|
||||||
|
msgid "Transport mode"
|
||||||
|
msgstr "Siirtoyhteystapa"
|
||||||
|
|
||||||
|
msgid ""
|
||||||
|
"Define which transport mode shall be used.\n"
|
||||||
|
"\n"
|
||||||
|
"Unicast, Multicast, RTP-over-TCP"
|
||||||
|
msgstr ""
|
||||||
|
"Määrittele käytettävä siirtoyhteystapa.\n"
|
||||||
|
"\n"
|
||||||
|
"Unicast, Multicast, RTP-over-TCP"
|
||||||
|
|
||||||
msgid "Active SAT>IP servers:"
|
msgid "Active SAT>IP servers:"
|
||||||
msgstr "Aktiiviset SAT>IP-palvelimet:"
|
msgstr "Aktiiviset SAT>IP-palvelimet:"
|
||||||
|
|
||||||
|
206
po/pl_PL.po
Normal file
206
po/pl_PL.po
Normal file
@@ -0,0 +1,206 @@
|
|||||||
|
# VDR plugin language source file.
|
||||||
|
# Copyright (C) 2007-2018 Rolf Ahrenberg
|
||||||
|
# This file is distributed under the same license as the vdr-satip package.
|
||||||
|
# Tomasz Maciej Nowak, 2017
|
||||||
|
#
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: vdr-satip 2.4.0\n"
|
||||||
|
"Report-Msgid-Bugs-To: <see README>\n"
|
||||||
|
"POT-Creation-Date: 2018-04-15 04:15+0300+0300\n"
|
||||||
|
"PO-Revision-Date: 2018-04-15 04:15+0300+0300\n"
|
||||||
|
"Last-Translator: Tomasz Maciej Nowak <tomek_n@o2.pl>\n"
|
||||||
|
"Language-Team: Polish <vdr@linuxtv.org>\n"
|
||||||
|
"Language: pl_PL\n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
"X-Generator: Poedit 1.8.11\n"
|
||||||
|
|
||||||
|
msgid "PAT (0x00)"
|
||||||
|
msgstr "PAT (0x00)"
|
||||||
|
|
||||||
|
msgid "NIT (0x40)"
|
||||||
|
msgstr "NIT (0x40)"
|
||||||
|
|
||||||
|
msgid "SDT (0x42)"
|
||||||
|
msgstr "SDT (0x42)"
|
||||||
|
|
||||||
|
msgid "EIT (0x4E/0x4F/0x5X/0x6X)"
|
||||||
|
msgstr "EIT (0x4E/0x4F/0x5X/0x6X)"
|
||||||
|
|
||||||
|
msgid "TDT (0x70)"
|
||||||
|
msgstr "TDT (0x70)"
|
||||||
|
|
||||||
|
msgid "SAT>IP information not available!"
|
||||||
|
msgstr "Informacja o SAT>IP niedostępna!"
|
||||||
|
|
||||||
|
msgid "SAT>IP Devices"
|
||||||
|
msgstr "Urządzenia SAT>IP"
|
||||||
|
|
||||||
|
msgid "SAT>IP Server"
|
||||||
|
msgstr "Serwer SAT>IP"
|
||||||
|
|
||||||
|
msgid "Address"
|
||||||
|
msgstr "Adres"
|
||||||
|
|
||||||
|
msgid "Model"
|
||||||
|
msgstr "Model"
|
||||||
|
|
||||||
|
msgid "Description"
|
||||||
|
msgstr "Opis"
|
||||||
|
|
||||||
|
msgid "CI extension"
|
||||||
|
msgstr "Rozszerzenie CI"
|
||||||
|
|
||||||
|
msgid "Creation date"
|
||||||
|
msgstr "Data produkcji"
|
||||||
|
|
||||||
|
msgid "SAT>IP Device Status"
|
||||||
|
msgstr "Status urządzenia SAT>IP"
|
||||||
|
|
||||||
|
msgid "SAT>IP Information"
|
||||||
|
msgstr "SAT>IP - informacje"
|
||||||
|
|
||||||
|
msgid "General"
|
||||||
|
msgstr "Główne"
|
||||||
|
|
||||||
|
msgid "Pids"
|
||||||
|
msgstr "Pidy"
|
||||||
|
|
||||||
|
msgid "Filters"
|
||||||
|
msgstr "Filtry"
|
||||||
|
|
||||||
|
msgid "Bits/bytes"
|
||||||
|
msgstr "Bity/bajty"
|
||||||
|
|
||||||
|
msgid "off"
|
||||||
|
msgstr "wyłączone"
|
||||||
|
|
||||||
|
msgid "low"
|
||||||
|
msgstr "niski"
|
||||||
|
|
||||||
|
msgid "normal"
|
||||||
|
msgstr "normalny"
|
||||||
|
|
||||||
|
msgid "high"
|
||||||
|
msgstr "wysoki"
|
||||||
|
|
||||||
|
msgid "Unicast"
|
||||||
|
msgstr "Unicast"
|
||||||
|
|
||||||
|
msgid "Multicast"
|
||||||
|
msgstr "Multicast"
|
||||||
|
|
||||||
|
msgid "RTP-over-TCP"
|
||||||
|
msgstr "RTP-over-TCP"
|
||||||
|
|
||||||
|
msgid "Button$Devices"
|
||||||
|
msgstr "Urządzenia"
|
||||||
|
|
||||||
|
msgid "Operating mode"
|
||||||
|
msgstr "Tryb pracy"
|
||||||
|
|
||||||
|
msgid ""
|
||||||
|
"Define the used operating mode for all SAT>IP devices:\n"
|
||||||
|
"\n"
|
||||||
|
"off - devices are disabled\n"
|
||||||
|
"low - devices are working at the lowest priority\n"
|
||||||
|
"normal - devices are working within normal parameters\n"
|
||||||
|
"high - devices are working at the highest priority"
|
||||||
|
msgstr ""
|
||||||
|
"Określa tryb pracy wszystkich urządzeń SAT>IP:\n"
|
||||||
|
"\n"
|
||||||
|
"wyłączone - urządzenia są wyłączone\n"
|
||||||
|
"niski - urządzenia pracują z najniższym priorytetem\n"
|
||||||
|
"normalny - urządzenia pracują z normalnymi parametrami\n"
|
||||||
|
"wysoki - urządzenia pracują z najwyższym priorytetem"
|
||||||
|
|
||||||
|
msgid "Enable CI extension"
|
||||||
|
msgstr "Włącz rozszerzenie CI"
|
||||||
|
|
||||||
|
msgid ""
|
||||||
|
"Define whether a CI extension shall be used.\n"
|
||||||
|
"\n"
|
||||||
|
"This setting enables integrated CI/CAM handling found in some SAT>IP hardware (e.g. Digital Devices OctopusNet)."
|
||||||
|
msgstr ""
|
||||||
|
"Określa czy korzystać z rozszerzenia CI.\n"
|
||||||
|
"\n"
|
||||||
|
"To ustawienie włącza obsługę dostępnego czytnika CI/CAM w niektórych urządzeniach SAT>IP (np. Digital Devices OctopusNet)."
|
||||||
|
|
||||||
|
msgid "CI/CAM"
|
||||||
|
msgstr "CI/CAM"
|
||||||
|
|
||||||
|
msgid ""
|
||||||
|
"Define a desired CAM type for the CI slot.\n"
|
||||||
|
"\n"
|
||||||
|
"The '---' option lets SAT>IP hardware do the auto-selection."
|
||||||
|
msgstr ""
|
||||||
|
"Określa typ modułu CAM w czytniku CI.\n"
|
||||||
|
"\n"
|
||||||
|
"Opcja '---' pozwala urządzeniu SAT>IP automatycznie wybrać typ."
|
||||||
|
|
||||||
|
msgid "Enable EPG scanning"
|
||||||
|
msgstr "Włącz skanowanie EPG"
|
||||||
|
|
||||||
|
msgid ""
|
||||||
|
"Define whether the EPG background scanning shall be used.\n"
|
||||||
|
"\n"
|
||||||
|
"This setting disables the automatic EIT scanning functionality for all SAT>IP devices."
|
||||||
|
msgstr ""
|
||||||
|
"Określa czy przeprowadzać skanowanie EPG w tle.\n"
|
||||||
|
"\n"
|
||||||
|
"To ustawienie wyłącza funkcję automatycznego skanowania EIT dla wszystkich urządzeń SAT>IP."
|
||||||
|
|
||||||
|
msgid "Disabled sources"
|
||||||
|
msgstr "Wyłączone źródła"
|
||||||
|
|
||||||
|
msgid "none"
|
||||||
|
msgstr "brak"
|
||||||
|
|
||||||
|
msgid ""
|
||||||
|
"Define number of sources to be disabled.\n"
|
||||||
|
"\n"
|
||||||
|
"SAT>IP servers might not have all satellite positions available and such sources can be blacklisted here."
|
||||||
|
msgstr ""
|
||||||
|
"Określa liczbę wyłączonych źródeł.\n"
|
||||||
|
"\n"
|
||||||
|
"Serwery SAT>IP mogą nie mieć dostępu do niektórych pozycji satelitarnych, więc tutaj można je wyłączyć."
|
||||||
|
|
||||||
|
msgid "Define a source to be blacklisted."
|
||||||
|
msgstr "Określ źródła do wyłączenia."
|
||||||
|
|
||||||
|
msgid "Disabled filters"
|
||||||
|
msgstr "Wyłączone filtry"
|
||||||
|
|
||||||
|
msgid ""
|
||||||
|
"Define number of section filters to be disabled.\n"
|
||||||
|
"\n"
|
||||||
|
"Certain section filters might cause some unwanted behaviour to VDR such as time being falsely synchronized. By blacklisting the filters here, useful section data can be left intact for VDR to process."
|
||||||
|
msgstr ""
|
||||||
|
"Określa liczbę wyłączonych filtrów sekcji.\n"
|
||||||
|
"\n"
|
||||||
|
"Niektóre filtry sekcji mogą powodować niezamierzone efekty w VDR, takie jak zły czas synchronizacji. Poprzez wyłączenie niektórych filtrów, użyteczne dane sekcji będą dostępne do przetworzenia dla VDR."
|
||||||
|
|
||||||
|
msgid "Filter"
|
||||||
|
msgstr "Filtr"
|
||||||
|
|
||||||
|
msgid "Define an ill-behaving filter to be blacklisted."
|
||||||
|
msgstr "Określa filtry powodujące zakłócenia, które mają być wyłączone."
|
||||||
|
|
||||||
|
msgid "Transport mode"
|
||||||
|
msgstr "Tryb"
|
||||||
|
|
||||||
|
msgid ""
|
||||||
|
"Define which transport mode shall be used.\n"
|
||||||
|
"\n"
|
||||||
|
"Unicast, Multicast, RTP-over-TCP"
|
||||||
|
msgstr ""
|
||||||
|
"Określa tryb transmisji.\n"
|
||||||
|
"Unicast, Multicast, RTP-over-TCP."
|
||||||
|
|
||||||
|
msgid "Active SAT>IP servers:"
|
||||||
|
msgstr "Aktywne serwery SAT>IP:"
|
||||||
|
|
||||||
|
msgid "Help"
|
||||||
|
msgstr "Pomoc"
|
2
poller.c
2
poller.c
@@ -79,7 +79,7 @@ void cSatipPoller::Action(void)
|
|||||||
// Do the thread loop
|
// Do the thread loop
|
||||||
while (Running()) {
|
while (Running()) {
|
||||||
int nfds = epoll_wait(fdM, events, eMaxFileDescriptors, -1);
|
int nfds = epoll_wait(fdM, events, eMaxFileDescriptors, -1);
|
||||||
ERROR_IF_FUNC((nfds == -1), "epoll_wait() failed", break, ;);
|
ERROR_IF_FUNC((nfds == -1 && errno != EINTR), "epoll_wait() failed", break, ;);
|
||||||
for (int i = 0; i < nfds; ++i) {
|
for (int i = 0; i < nfds; ++i) {
|
||||||
cSatipPollerIf* poll = reinterpret_cast<cSatipPollerIf *>(events[i].data.ptr);
|
cSatipPollerIf* poll = reinterpret_cast<cSatipPollerIf *>(events[i].data.ptr);
|
||||||
if (poll) {
|
if (poll) {
|
||||||
|
@@ -14,6 +14,7 @@ public:
|
|||||||
virtual ~cSatipPollerIf() {}
|
virtual ~cSatipPollerIf() {}
|
||||||
virtual int GetFd(void) = 0;
|
virtual int GetFd(void) = 0;
|
||||||
virtual void Process(void) = 0;
|
virtual void Process(void) = 0;
|
||||||
|
virtual void Process(unsigned char *dataP, int lengthP) = 0;
|
||||||
virtual cString ToString(void) const = 0;
|
virtual cString ToString(void) const = 0;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
10
rtcp.c
10
rtcp.c
@@ -92,6 +92,16 @@ void cSatipRtcp::Process(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void cSatipRtcp::Process(unsigned char *dataP, int lengthP)
|
||||||
|
{
|
||||||
|
debug16("%s [device %d]", __PRETTY_FUNCTION__, tunerM.GetId());
|
||||||
|
if (dataP && lengthP > 0) {
|
||||||
|
int offset = GetApplicationOffset(&lengthP);
|
||||||
|
if (offset >= 0)
|
||||||
|
tunerM.ProcessApplicationData(dataP + offset, lengthP);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
cString cSatipRtcp::ToString(void) const
|
cString cSatipRtcp::ToString(void) const
|
||||||
{
|
{
|
||||||
return cString::sprintf("RTCP [device %d]", tunerM.GetId());
|
return cString::sprintf("RTCP [device %d]", tunerM.GetId());
|
||||||
|
1
rtcp.h
1
rtcp.h
@@ -30,6 +30,7 @@ public:
|
|||||||
public:
|
public:
|
||||||
virtual int GetFd(void);
|
virtual int GetFd(void);
|
||||||
virtual void Process(void);
|
virtual void Process(void);
|
||||||
|
virtual void Process(unsigned char *dataP, int lengthP);
|
||||||
virtual cString ToString(void) const;
|
virtual cString ToString(void) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
23
rtp.c
23
rtp.c
@@ -14,7 +14,8 @@
|
|||||||
#include "rtp.h"
|
#include "rtp.h"
|
||||||
|
|
||||||
cSatipRtp::cSatipRtp(cSatipTunerIf &tunerP)
|
cSatipRtp::cSatipRtp(cSatipTunerIf &tunerP)
|
||||||
: tunerM(tunerP),
|
: cSatipSocket(SatipConfig.GetRtpRcvBufSize()),
|
||||||
|
tunerM(tunerP),
|
||||||
bufferLenM(eRtpPacketReadCount * eMaxUdpPacketSizeB),
|
bufferLenM(eRtpPacketReadCount * eMaxUdpPacketSizeB),
|
||||||
bufferM(MALLOC(unsigned char, bufferLenM)),
|
bufferM(MALLOC(unsigned char, bufferLenM)),
|
||||||
lastErrorReportM(0),
|
lastErrorReportM(0),
|
||||||
@@ -45,7 +46,7 @@ void cSatipRtp::Close(void)
|
|||||||
|
|
||||||
sequenceNumberM = -1;
|
sequenceNumberM = -1;
|
||||||
if (packetErrorsM) {
|
if (packetErrorsM) {
|
||||||
info("Detected %d RTP packet errors [device %d]", packetErrorsM, tunerM.GetId());
|
info("Detected %d RTP packet error%s [device %d]", packetErrorsM, packetErrorsM == 1 ? "": "s", tunerM.GetId());
|
||||||
packetErrorsM = 0;
|
packetErrorsM = 0;
|
||||||
lastErrorReportM = time(NULL);
|
lastErrorReportM = time(NULL);
|
||||||
}
|
}
|
||||||
@@ -80,7 +81,7 @@ int cSatipRtp::GetHeaderLength(unsigned char *bufferP, unsigned int lengthP)
|
|||||||
else if ((sequenceNumberM >= 0) && (((sequenceNumberM + 1) % 0xFFFF) != seq)) {
|
else if ((sequenceNumberM >= 0) && (((sequenceNumberM + 1) % 0xFFFF) != seq)) {
|
||||||
packetErrorsM++;
|
packetErrorsM++;
|
||||||
if (time(NULL) - lastErrorReportM > eReportIntervalS) {
|
if (time(NULL) - lastErrorReportM > eReportIntervalS) {
|
||||||
info("Detected %d RTP packet errors [device %d]", packetErrorsM, tunerM.GetId());
|
info("Detected %d RTP packet error%s [device %d]", packetErrorsM, packetErrorsM == 1 ? "": "s", tunerM.GetId());
|
||||||
packetErrorsM = 0;
|
packetErrorsM = 0;
|
||||||
lastErrorReportM = time(NULL);
|
lastErrorReportM = time(NULL);
|
||||||
}
|
}
|
||||||
@@ -142,6 +143,22 @@ void cSatipRtp::Process(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void cSatipRtp::Process(unsigned char *dataP, int lengthP)
|
||||||
|
{
|
||||||
|
debug16("%s [device %d]", __PRETTY_FUNCTION__, tunerM.GetId());
|
||||||
|
if (dataP && lengthP > 0) {
|
||||||
|
uint64_t elapsed;
|
||||||
|
cTimeMs processing(0);
|
||||||
|
int headerlen = GetHeaderLength(dataP, lengthP);
|
||||||
|
if ((headerlen >= 0) && (headerlen < lengthP))
|
||||||
|
tunerM.ProcessVideoData(dataP + headerlen, lengthP - headerlen);
|
||||||
|
|
||||||
|
elapsed = processing.Elapsed();
|
||||||
|
if (elapsed > 1)
|
||||||
|
debug6("%s %d read(s) took %" PRIu64 " ms [device %d]", __PRETTY_FUNCTION__, lengthP, elapsed, tunerM.GetId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
cString cSatipRtp::ToString(void) const
|
cString cSatipRtp::ToString(void) const
|
||||||
{
|
{
|
||||||
return cString::sprintf("RTP [device %d]", tunerM.GetId());
|
return cString::sprintf("RTP [device %d]", tunerM.GetId());
|
||||||
|
1
rtp.h
1
rtp.h
@@ -36,6 +36,7 @@ public:
|
|||||||
public:
|
public:
|
||||||
virtual int GetFd(void);
|
virtual int GetFd(void);
|
||||||
virtual void Process(void);
|
virtual void Process(void);
|
||||||
|
virtual void Process(unsigned char *dataP, int lengthP);
|
||||||
virtual cString ToString(void) const;
|
virtual cString ToString(void) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
116
rtsp.c
116
rtsp.c
@@ -17,12 +17,14 @@ cSatipRtsp::cSatipRtsp(cSatipTunerIf &tunerP)
|
|||||||
: tunerM(tunerP),
|
: tunerM(tunerP),
|
||||||
headerBufferM(),
|
headerBufferM(),
|
||||||
dataBufferM(),
|
dataBufferM(),
|
||||||
modeM(cmUnicast),
|
|
||||||
handleM(NULL),
|
handleM(NULL),
|
||||||
headerListM(NULL),
|
headerListM(NULL),
|
||||||
errorNoMoreM(""),
|
errorNoMoreM(""),
|
||||||
errorOutOfRangeM(""),
|
errorOutOfRangeM(""),
|
||||||
errorCheckSyntaxM("")
|
errorCheckSyntaxM(""),
|
||||||
|
modeM(cSatipConfig::eTransportModeUnicast),
|
||||||
|
interleavedRtpIdM(0),
|
||||||
|
interleavedRtcpIdM(1)
|
||||||
{
|
{
|
||||||
debug1("%s [device %d]", __PRETTY_FUNCTION__, tunerM.GetId());
|
debug1("%s [device %d]", __PRETTY_FUNCTION__, tunerM.GetId());
|
||||||
Create();
|
Create();
|
||||||
@@ -58,6 +60,30 @@ size_t cSatipRtsp::DataCallback(char *ptrP, size_t sizeP, size_t nmembP, void *d
|
|||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t cSatipRtsp::InterleaveCallback(char *ptrP, size_t sizeP, size_t nmembP, void *dataP)
|
||||||
|
{
|
||||||
|
cSatipRtsp *obj = reinterpret_cast<cSatipRtsp *>(dataP);
|
||||||
|
size_t len = sizeP * nmembP;
|
||||||
|
debug16("%s len=%zu", __PRETTY_FUNCTION__, len);
|
||||||
|
|
||||||
|
if (obj && ptrP && len > 0) {
|
||||||
|
char tag = ptrP[0] & 0xFF;
|
||||||
|
if (tag == '$') {
|
||||||
|
int count = ((ptrP[2] & 0xFF) << 8) | (ptrP[3] & 0xFF);
|
||||||
|
if (count > 0) {
|
||||||
|
unsigned int channel = ptrP[1] & 0xFF;
|
||||||
|
u_char *data = (u_char *)&ptrP[4];
|
||||||
|
if (channel == obj->interleavedRtpIdM)
|
||||||
|
obj->tunerM.ProcessRtpData(data, count);
|
||||||
|
else if (channel == obj->interleavedRtcpIdM)
|
||||||
|
obj->tunerM.ProcessRtcpData(data, count);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
int cSatipRtsp::DebugCallback(CURL *handleP, curl_infotype typeP, char *dataP, size_t sizeP, void *userPtrP)
|
int cSatipRtsp::DebugCallback(CURL *handleP, curl_infotype typeP, char *dataP, size_t sizeP, void *userPtrP)
|
||||||
{
|
{
|
||||||
cSatipRtsp *obj = reinterpret_cast<cSatipRtsp *>(userPtrP);
|
cSatipRtsp *obj = reinterpret_cast<cSatipRtsp *>(userPtrP);
|
||||||
@@ -87,6 +113,21 @@ int cSatipRtsp::DebugCallback(CURL *handleP, curl_infotype typeP, char *dataP, s
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cString cSatipRtsp::GetActiveMode(void)
|
||||||
|
{
|
||||||
|
switch (modeM) {
|
||||||
|
case cSatipConfig::eTransportModeUnicast:
|
||||||
|
return "Unicast";
|
||||||
|
case cSatipConfig::eTransportModeMulticast:
|
||||||
|
return "Multicast";
|
||||||
|
case cSatipConfig::eTransportModeRtpOverTcp:
|
||||||
|
return "RTP-over-TCP";
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
cString cSatipRtsp::RtspUnescapeString(const char *strP)
|
cString cSatipRtsp::RtspUnescapeString(const char *strP)
|
||||||
{
|
{
|
||||||
debug1("%s (%s) [device %d]", __PRETTY_FUNCTION__, strP, tunerM.GetId());
|
debug1("%s (%s) [device %d]", __PRETTY_FUNCTION__, strP, tunerM.GetId());
|
||||||
@@ -149,6 +190,22 @@ void cSatipRtsp::Reset(void)
|
|||||||
Create();
|
Create();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool cSatipRtsp::SetInterface(const char *bindAddrP)
|
||||||
|
{
|
||||||
|
debug1("%s (%s) [device %d]", __PRETTY_FUNCTION__, bindAddrP, tunerM.GetId());
|
||||||
|
bool result = true;
|
||||||
|
CURLcode res = CURLE_OK;
|
||||||
|
|
||||||
|
if (handleM && !isempty(bindAddrP)) {
|
||||||
|
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_INTERFACE, *cString::sprintf("host!%s", bindAddrP));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_INTERFACE, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
bool cSatipRtsp::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());
|
||||||
@@ -171,9 +228,9 @@ bool cSatipRtsp::Options(const char *uriP)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool cSatipRtsp::Setup(const char *uriP, int rtpPortP, int rtcpPortP)
|
bool cSatipRtsp::Setup(const char *uriP, int rtpPortP, int rtcpPortP, bool useTcpP)
|
||||||
{
|
{
|
||||||
debug1("%s (%s, %d, %d) [device %d]", __PRETTY_FUNCTION__, uriP, rtpPortP, rtcpPortP, tunerM.GetId());
|
debug1("%s (%s, %d, %d, %d) [device %d]", __PRETTY_FUNCTION__, uriP, rtpPortP, rtcpPortP, useTcpP, tunerM.GetId());
|
||||||
bool result = false;
|
bool result = false;
|
||||||
|
|
||||||
if (handleM && !isempty(uriP)) {
|
if (handleM && !isempty(uriP)) {
|
||||||
@@ -182,14 +239,17 @@ bool cSatipRtsp::Setup(const char *uriP, int rtpPortP, int rtcpPortP)
|
|||||||
cTimeMs processing(0);
|
cTimeMs processing(0);
|
||||||
CURLcode res = CURLE_OK;
|
CURLcode res = CURLE_OK;
|
||||||
|
|
||||||
switch (modeM) {
|
switch (SatipConfig.GetTransportMode()) {
|
||||||
case cmMulticast:
|
case cSatipConfig::eTransportModeMulticast:
|
||||||
// RTP/AVP;multicast;destination=<IP multicast address>;port=<RTP port>-<RTCP port>;ttl=<ttl>
|
// RTP/AVP;multicast;destination=<multicast group address>;port=<RTP port>-<RTCP port>;ttl=<ttl>[;source=<multicast source address>]
|
||||||
transport = cString::sprintf("RTP/AVP;multicast;port=%d-%d", rtpPortP, rtcpPortP);
|
transport = cString::sprintf("RTP/AVP;multicast");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
case cmUnicast:
|
|
||||||
// RTP/AVP;unicast;client_port=<client RTP port>-<client RTCP port>
|
// RTP/AVP;unicast;client_port=<client RTP port>-<client RTCP port>
|
||||||
|
// RTP/AVP/TCP;unicast;client_port=<client RTP port>-<client RTCP port>
|
||||||
|
if (useTcpP)
|
||||||
|
transport = cString::sprintf("RTP/AVP/TCP;unicast;interleaved=%u-%u", interleavedRtpIdM, interleavedRtcpIdM);
|
||||||
|
else
|
||||||
transport = cString::sprintf("RTP/AVP;unicast;client_port=%d-%d", rtpPortP, rtcpPortP);
|
transport = cString::sprintf("RTP/AVP;unicast;client_port=%d-%d", rtpPortP, rtcpPortP);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -203,6 +263,9 @@ bool cSatipRtsp::Setup(const char *uriP, int rtpPortP, int rtcpPortP)
|
|||||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEHEADER, this);
|
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEHEADER, this);
|
||||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEFUNCTION, cSatipRtsp::DataCallback);
|
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEFUNCTION, cSatipRtsp::DataCallback);
|
||||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEDATA, this);
|
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEDATA, this);
|
||||||
|
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_INTERLEAVEFUNCTION, NULL);
|
||||||
|
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_INTERLEAVEDATA, NULL);
|
||||||
|
|
||||||
SATIP_CURL_EASY_PERFORM(handleM);
|
SATIP_CURL_EASY_PERFORM(handleM);
|
||||||
// Session id is now known - disable header parsing
|
// Session id is now known - disable header parsing
|
||||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_HEADERFUNCTION, NULL);
|
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_HEADERFUNCTION, NULL);
|
||||||
@@ -310,6 +373,8 @@ bool cSatipRtsp::Teardown(const char *uriP)
|
|||||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_RTSP_REQUEST, (long)CURL_RTSPREQ_TEARDOWN);
|
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_RTSP_REQUEST, (long)CURL_RTSPREQ_TEARDOWN);
|
||||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEFUNCTION, cSatipRtsp::DataCallback);
|
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEFUNCTION, cSatipRtsp::DataCallback);
|
||||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEDATA, this);
|
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEDATA, this);
|
||||||
|
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_INTERLEAVEFUNCTION, NULL);
|
||||||
|
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_INTERLEAVEDATA, NULL);
|
||||||
SATIP_CURL_EASY_PERFORM(handleM);
|
SATIP_CURL_EASY_PERFORM(handleM);
|
||||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEFUNCTION, NULL);
|
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEFUNCTION, NULL);
|
||||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEDATA, NULL);
|
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEDATA, NULL);
|
||||||
@@ -351,6 +416,35 @@ void cSatipRtsp::ParseHeader(void)
|
|||||||
tunerM.SetSessionTimeout(skipspace(session), -1);
|
tunerM.SetSessionTimeout(skipspace(session), -1);
|
||||||
FREE_POINTER(session);
|
FREE_POINTER(session);
|
||||||
}
|
}
|
||||||
|
else if (strstr(r, "Transport:")) {
|
||||||
|
CURLcode res = CURLE_OK;
|
||||||
|
int rtp = -1, rtcp = -1, ttl = -1;
|
||||||
|
char *tmp = NULL, *destination = NULL, *source = NULL;
|
||||||
|
interleavedRtpIdM = 0;
|
||||||
|
interleavedRtcpIdM = 1;
|
||||||
|
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_INTERLEAVEFUNCTION, NULL);
|
||||||
|
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_INTERLEAVEDATA, NULL);
|
||||||
|
if (sscanf(r, "Transport:%m[^;];unicast;client_port=%11d-%11d", &tmp, &rtp, &rtcp) == 3) {
|
||||||
|
modeM = cSatipConfig::eTransportModeUnicast;
|
||||||
|
tunerM.SetupTransport(rtp, rtcp, NULL, NULL);
|
||||||
|
}
|
||||||
|
else if (sscanf(r, "Transport:%m[^;];multicast;destination=%m[^;];port=%11d-%11d;ttl=%11d;source=%m[^;]", &tmp, &destination, &rtp, &rtcp, &ttl, &source) == 6 ||
|
||||||
|
sscanf(r, "Transport:%m[^;];multicast;destination=%m[^;];port=%11d-%11d;ttl=%11d", &tmp, &destination, &rtp, &rtcp, &ttl) == 5) {
|
||||||
|
modeM = cSatipConfig::eTransportModeMulticast;
|
||||||
|
tunerM.SetupTransport(rtp, rtcp, destination, source);
|
||||||
|
}
|
||||||
|
else if (sscanf(r, "Transport:%m[^;];interleaved=%11d-%11d", &tmp, &rtp, &rtcp) == 3) {
|
||||||
|
interleavedRtpIdM = rtp;
|
||||||
|
interleavedRtcpIdM = rtcp;
|
||||||
|
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_INTERLEAVEFUNCTION, cSatipRtsp::InterleaveCallback);
|
||||||
|
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_INTERLEAVEDATA, this);
|
||||||
|
modeM = cSatipConfig::eTransportModeRtpOverTcp;
|
||||||
|
tunerM.SetupTransport(-1, -1, NULL, NULL);
|
||||||
|
}
|
||||||
|
FREE_POINTER(tmp);
|
||||||
|
FREE_POINTER(destination);
|
||||||
|
FREE_POINTER(source);
|
||||||
|
}
|
||||||
r = strtok_r(NULL, "\r\n", &s);
|
r = strtok_r(NULL, "\r\n", &s);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -418,10 +512,12 @@ bool cSatipRtsp::ValidateLatestResponse(long *rcP)
|
|||||||
// SETUP PLAY TEARDOWN
|
// SETUP PLAY TEARDOWN
|
||||||
// The message body of the response may contain the "Out-of-Range:" parameter followed
|
// The message body of the response may contain the "Out-of-Range:" parameter followed
|
||||||
// by a space-separated list of the attribute names that are not understood:
|
// by a space-separated list of the attribute names that are not understood:
|
||||||
// "src" "fe" "freq" "pol" "msys" "mtype" "plts" "ro" "sr" "fec" "pids" "addpids" "delpids" "mcast
|
// "src" "fe" "freq" "pol" "msys" "mtype" "plts" "ro" "sr" "fec" "pids" "addpids" "delpids" "mcast"
|
||||||
if (!isempty(*errorOutOfRangeM)) {
|
if (!isempty(*errorOutOfRangeM)) {
|
||||||
SATIP_CURL_EASY_GETINFO(handleM, CURLINFO_EFFECTIVE_URL, &url);
|
SATIP_CURL_EASY_GETINFO(handleM, CURLINFO_EFFECTIVE_URL, &url);
|
||||||
error("Out of range: %s (error code %ld: %s) [device %d]", *errorOutOfRangeM, rc, url, tunerM.GetId());
|
error("Out of range: %s (error code %ld: %s) [device %d]", *errorOutOfRangeM, rc, url, tunerM.GetId());
|
||||||
|
// Reseting the connection wouldn't help anything due to invalid channel configuration, so let it be successful
|
||||||
|
result = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 503:
|
case 503:
|
||||||
|
10
rtsp.h
10
rtsp.h
@@ -22,22 +22,24 @@ class cSatipRtsp {
|
|||||||
private:
|
private:
|
||||||
static size_t HeaderCallback(char *ptrP, size_t sizeP, size_t nmembP, void *dataP);
|
static size_t HeaderCallback(char *ptrP, size_t sizeP, size_t nmembP, void *dataP);
|
||||||
static size_t DataCallback(char *ptrP, size_t sizeP, size_t nmembP, void *dataP);
|
static size_t DataCallback(char *ptrP, size_t sizeP, size_t nmembP, void *dataP);
|
||||||
|
static size_t InterleaveCallback(char *ptrP, size_t sizeP, size_t nmembP, void *dataP);
|
||||||
static int DebugCallback(CURL *handleP, curl_infotype typeP, char *dataP, size_t sizeP, void *userPtrP);
|
static int DebugCallback(CURL *handleP, curl_infotype typeP, char *dataP, size_t sizeP, void *userPtrP);
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
eConnectTimeoutMs = 1500, // in milliseconds
|
eConnectTimeoutMs = 1500, // in milliseconds
|
||||||
};
|
};
|
||||||
enum eCommunicationMode { cmUnicast, cmMulticast };
|
|
||||||
|
|
||||||
cSatipTunerIf &tunerM;
|
cSatipTunerIf &tunerM;
|
||||||
cSatipMemoryBuffer headerBufferM;
|
cSatipMemoryBuffer headerBufferM;
|
||||||
cSatipMemoryBuffer dataBufferM;
|
cSatipMemoryBuffer dataBufferM;
|
||||||
eCommunicationMode modeM;
|
|
||||||
CURL *handleM;
|
CURL *handleM;
|
||||||
struct curl_slist *headerListM;
|
struct curl_slist *headerListM;
|
||||||
cString errorNoMoreM;
|
cString errorNoMoreM;
|
||||||
cString errorOutOfRangeM;
|
cString errorOutOfRangeM;
|
||||||
cString errorCheckSyntaxM;
|
cString errorCheckSyntaxM;
|
||||||
|
int modeM;
|
||||||
|
unsigned int interleavedRtpIdM;
|
||||||
|
unsigned int interleavedRtcpIdM;
|
||||||
|
|
||||||
void Create(void);
|
void Create(void);
|
||||||
void Destroy(void);
|
void Destroy(void);
|
||||||
@@ -53,10 +55,12 @@ public:
|
|||||||
explicit cSatipRtsp(cSatipTunerIf &tunerP);
|
explicit cSatipRtsp(cSatipTunerIf &tunerP);
|
||||||
virtual ~cSatipRtsp();
|
virtual ~cSatipRtsp();
|
||||||
|
|
||||||
|
cString GetActiveMode(void);
|
||||||
cString RtspUnescapeString(const char *strP);
|
cString RtspUnescapeString(const char *strP);
|
||||||
void Reset(void);
|
void Reset(void);
|
||||||
|
bool SetInterface(const char *bindAddrP);
|
||||||
bool Options(const char *uriP);
|
bool Options(const char *uriP);
|
||||||
bool Setup(const char *uriP, int rtpPortP, int rtcpPortP);
|
bool Setup(const char *uriP, int rtpPortP, int rtcpPortP, bool useTcpP);
|
||||||
bool SetSession(const char *sessionP);
|
bool SetSession(const char *sessionP);
|
||||||
bool Describe(const char *uriP);
|
bool Describe(const char *uriP);
|
||||||
bool Play(const char *uriP);
|
bool Play(const char *uriP);
|
||||||
|
96
satip.c
96
satip.c
@@ -5,6 +5,7 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <ctype.h>
|
||||||
#include <getopt.h>
|
#include <getopt.h>
|
||||||
#include <vdr/plugin.h>
|
#include <vdr/plugin.h>
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
@@ -19,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.3" GITVERSION;
|
const char VERSION[] = "2.4.0" 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 {
|
||||||
@@ -35,6 +36,7 @@ private:
|
|||||||
unsigned int deviceCountM;
|
unsigned int deviceCountM;
|
||||||
cSatipDiscoverServers *serversM;
|
cSatipDiscoverServers *serversM;
|
||||||
void ParseServer(const char *paramP);
|
void ParseServer(const char *paramP);
|
||||||
|
void ParsePortRange(const char *paramP);
|
||||||
int ParseCicams(const char *valueP, int *cicamsP);
|
int ParseCicams(const char *valueP, int *cicamsP);
|
||||||
int ParseSources(const char *valueP, int *sourcesP);
|
int ParseSources(const char *valueP, int *sourcesP);
|
||||||
int ParseFilters(const char *valueP, int *filtersP);
|
int ParseFilters(const char *valueP, int *filtersP);
|
||||||
@@ -83,11 +85,14 @@ 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>|<model2>|<desc2>\n"
|
" -s <ipaddr>|<model>|<desc>, --server=<ipaddr1>|<model1>|<desc1>;<ipaddr2>:<port>|<model2>:<filter>|<desc2>:<quirk>\n"
|
||||||
" define hard-coded SAT>IP server(s)\n"
|
" define hard-coded SAT>IP server(s)\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 all the server quirks\n";
|
" -n, --noquirks disable autodetection of the server quirks\n"
|
||||||
|
" -p, --portrange=<start>-<end> set a range of ports used for the RT[C]P server\n"
|
||||||
|
" a minimum of 2 ports per device is required.\n"
|
||||||
|
" -r, --rcvbuf override the size of the RTP receive buffer in bytes\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
bool cPluginSatip::ProcessArgs(int argc, char *argv[])
|
bool cPluginSatip::ProcessArgs(int argc, char *argv[])
|
||||||
@@ -98,6 +103,8 @@ bool cPluginSatip::ProcessArgs(int argc, char *argv[])
|
|||||||
{ "devices", required_argument, NULL, 'd' },
|
{ "devices", required_argument, NULL, 'd' },
|
||||||
{ "trace", required_argument, NULL, 't' },
|
{ "trace", required_argument, NULL, 't' },
|
||||||
{ "server", required_argument, NULL, 's' },
|
{ "server", required_argument, NULL, 's' },
|
||||||
|
{ "portrange",required_argument, NULL, 'p' },
|
||||||
|
{ "rcvbuf", required_argument, NULL, 'r' },
|
||||||
{ "detach", no_argument, NULL, 'D' },
|
{ "detach", no_argument, NULL, 'D' },
|
||||||
{ "single", no_argument, NULL, 'S' },
|
{ "single", no_argument, NULL, 'S' },
|
||||||
{ "noquirks", no_argument, NULL, 'n' },
|
{ "noquirks", no_argument, NULL, 'n' },
|
||||||
@@ -105,8 +112,9 @@ bool cPluginSatip::ProcessArgs(int argc, char *argv[])
|
|||||||
};
|
};
|
||||||
|
|
||||||
cString server;
|
cString server;
|
||||||
|
cString portrange;
|
||||||
int c;
|
int c;
|
||||||
while ((c = getopt_long(argc, argv, "d:t:s:DSn", long_options, NULL)) != -1) {
|
while ((c = getopt_long(argc, argv, "d:t:s:p:r:DSn", long_options, NULL)) != -1) {
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case 'd':
|
case 'd':
|
||||||
deviceCountM = strtol(optarg, NULL, 0);
|
deviceCountM = strtol(optarg, NULL, 0);
|
||||||
@@ -126,10 +134,18 @@ bool cPluginSatip::ProcessArgs(int argc, char *argv[])
|
|||||||
case 'n':
|
case 'n':
|
||||||
SatipConfig.SetDisableServerQuirks(true);
|
SatipConfig.SetDisableServerQuirks(true);
|
||||||
break;
|
break;
|
||||||
|
case 'p':
|
||||||
|
portrange = optarg;
|
||||||
|
break;
|
||||||
|
case 'r':
|
||||||
|
SatipConfig.SetRtpRcvBufSize(strtol(optarg, NULL, 0));
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (!isempty(*portrange))
|
||||||
|
ParsePortRange(portrange);
|
||||||
// this must be done after all parameters are parsed
|
// this must be done after all parameters are parsed
|
||||||
if (!isempty(*server))
|
if (!isempty(*server))
|
||||||
ParseServer(*server);
|
ParseServer(*server);
|
||||||
@@ -222,7 +238,9 @@ void cPluginSatip::ParseServer(const char *paramP)
|
|||||||
while (r) {
|
while (r) {
|
||||||
r = skipspace(r);
|
r = skipspace(r);
|
||||||
debug3("%s server[%d]=%s", __PRETTY_FUNCTION__, n, r);
|
debug3("%s server[%d]=%s", __PRETTY_FUNCTION__, n, r);
|
||||||
cString serverAddr, serverModel, serverDescription;
|
cString sourceAddr, serverAddr, serverModel, serverFilters, serverDescription;
|
||||||
|
int serverQuirk = cSatipServer::eSatipQuirkNone;
|
||||||
|
int serverPort = SATIP_DEFAULT_RTSP_PORT;
|
||||||
int n2 = 0;
|
int n2 = 0;
|
||||||
char *s2, *p2 = r;
|
char *s2, *p2 = r;
|
||||||
char *r2 = strtok_r(p2, "|", &s2);
|
char *r2 = strtok_r(p2, "|", &s2);
|
||||||
@@ -230,13 +248,40 @@ void cPluginSatip::ParseServer(const char *paramP)
|
|||||||
debug3("%s param[%d]=%s", __PRETTY_FUNCTION__, n2, r2);
|
debug3("%s param[%d]=%s", __PRETTY_FUNCTION__, n2, r2);
|
||||||
switch (n2++) {
|
switch (n2++) {
|
||||||
case 0:
|
case 0:
|
||||||
|
{
|
||||||
|
char *r3 = strchr(r2, '@');
|
||||||
|
if (r3) {
|
||||||
|
*r3 = 0;
|
||||||
|
sourceAddr = r2;
|
||||||
|
r2 = r3 + 1;
|
||||||
|
}
|
||||||
serverAddr = r2;
|
serverAddr = r2;
|
||||||
|
r3 = strchr(r2, ':');
|
||||||
|
if (r3) {
|
||||||
|
serverPort = strtol(r3 + 1, NULL, 0);
|
||||||
|
serverAddr = serverAddr.Truncate(r3 - r2);
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
|
{
|
||||||
serverModel = r2;
|
serverModel = r2;
|
||||||
|
char *r3 = strchr(r2, ':');
|
||||||
|
if (r3) {
|
||||||
|
serverFilters = r3 + 1;
|
||||||
|
serverModel = serverModel.Truncate(r3 - r2);
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
|
{
|
||||||
serverDescription = r2;
|
serverDescription = r2;
|
||||||
|
char *r3 = strchr(r2, ':');
|
||||||
|
if (r3) {
|
||||||
|
serverQuirk = strtol(r3 + 1, NULL, 0);
|
||||||
|
serverDescription = serverDescription.Truncate(r3 - r2);
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@@ -244,10 +289,10 @@ void cPluginSatip::ParseServer(const char *paramP)
|
|||||||
r2 = strtok_r(NULL, "|", &s2);
|
r2 = strtok_r(NULL, "|", &s2);
|
||||||
}
|
}
|
||||||
if (*serverAddr && *serverModel && *serverDescription) {
|
if (*serverAddr && *serverModel && *serverDescription) {
|
||||||
debug1("%s ipaddr=%s model=%s desc=%s", __PRETTY_FUNCTION__, *serverAddr, *serverModel, *serverDescription);
|
debug1("%s srcaddr=%s ipaddr=%s port=%d model=%s (%s) desc=%s (%d)", __PRETTY_FUNCTION__, *sourceAddr, *serverAddr, serverPort, *serverModel, *serverFilters, *serverDescription, serverQuirk);
|
||||||
if (!serversM)
|
if (!serversM)
|
||||||
serversM = new cSatipDiscoverServers();
|
serversM = new cSatipDiscoverServers();
|
||||||
serversM->Add(new cSatipDiscoverServer(*serverAddr, *serverModel, *serverDescription));
|
serversM->Add(new cSatipDiscoverServer(*sourceAddr, *serverAddr, serverPort, *serverModel, *serverFilters, *serverDescription, serverQuirk));
|
||||||
}
|
}
|
||||||
++n;
|
++n;
|
||||||
r = strtok_r(NULL, ";", &s);
|
r = strtok_r(NULL, ";", &s);
|
||||||
@@ -255,6 +300,37 @@ void cPluginSatip::ParseServer(const char *paramP)
|
|||||||
FREE_POINTER(p);
|
FREE_POINTER(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void cPluginSatip::ParsePortRange(const char *paramP)
|
||||||
|
{
|
||||||
|
char *s, *p = skipspace(paramP);
|
||||||
|
char *r = strtok_r(p, "-", &s);
|
||||||
|
unsigned int rangeStart = 0;
|
||||||
|
unsigned int rangeStop = 0;
|
||||||
|
if (r) {
|
||||||
|
rangeStart = strtol(r, NULL, 0);
|
||||||
|
r = strtok_r(NULL, "-", &s);
|
||||||
|
}
|
||||||
|
if (r)
|
||||||
|
rangeStop = strtol(r, NULL, 0);
|
||||||
|
else {
|
||||||
|
error("Port range argument not valid '%s'", paramP);
|
||||||
|
rangeStart = 0;
|
||||||
|
rangeStop = 0;
|
||||||
|
}
|
||||||
|
if (rangeStart % 2) {
|
||||||
|
error("The given range start port must be even!");
|
||||||
|
rangeStart = 0;
|
||||||
|
rangeStop = 0;
|
||||||
|
}
|
||||||
|
else if (rangeStop - rangeStart + 1 < deviceCountM * 2) {
|
||||||
|
error("The given port range is to small: %d < %d!", rangeStop - rangeStart + 1, deviceCountM * 2);
|
||||||
|
rangeStart = 0;
|
||||||
|
rangeStop = 0;
|
||||||
|
}
|
||||||
|
SatipConfig.SetPortRangeStart(rangeStart);
|
||||||
|
SatipConfig.SetPortRangeStop(rangeStop);
|
||||||
|
}
|
||||||
|
|
||||||
int cPluginSatip::ParseCicams(const char *valueP, int *cicamsP)
|
int cPluginSatip::ParseCicams(const char *valueP, int *cicamsP)
|
||||||
{
|
{
|
||||||
debug1("%s (%s,)", __PRETTY_FUNCTION__, valueP);
|
debug1("%s (%s,)", __PRETTY_FUNCTION__, valueP);
|
||||||
@@ -342,6 +418,8 @@ bool cPluginSatip::SetupParse(const char *nameP, const char *valueP)
|
|||||||
for (unsigned int i = 0; i < DisabledFiltersCount; ++i)
|
for (unsigned int i = 0; i < DisabledFiltersCount; ++i)
|
||||||
SatipConfig.SetDisabledFilters(i, DisabledFilters[i]);
|
SatipConfig.SetDisabledFilters(i, DisabledFilters[i]);
|
||||||
}
|
}
|
||||||
|
else if (!strcasecmp(nameP, "TransportMode"))
|
||||||
|
SatipConfig.SetTransportMode(atoi(valueP));
|
||||||
else
|
else
|
||||||
return false;
|
return false;
|
||||||
return true;
|
return true;
|
||||||
|
104
sectionfilter.c
104
sectionfilter.c
@@ -102,8 +102,11 @@ int cSatipSectionFilter::Filter(void)
|
|||||||
if (doneqM && !neq)
|
if (doneqM && !neq)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (ringBufferM && (secLenM > 0))
|
if (ringBufferM && (secLenM > 0)) {
|
||||||
ringBufferM->Put(new cFrame(secBufM, secLenM));
|
cFrame* section = new cFrame(secBufM, secLenM);
|
||||||
|
if (!ringBufferM->Put(section))
|
||||||
|
DELETE_POINTER(section);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -126,7 +129,7 @@ int cSatipSectionFilter::CopyDump(const uint8_t *bufP, uint8_t lenP)
|
|||||||
if (tsFeedpM + lenP > eDmxMaxSectionFeedSize)
|
if (tsFeedpM + lenP > eDmxMaxSectionFeedSize)
|
||||||
lenP = (uint8_t)(eDmxMaxSectionFeedSize - tsFeedpM);
|
lenP = (uint8_t)(eDmxMaxSectionFeedSize - tsFeedpM);
|
||||||
|
|
||||||
if (lenP <= 0)
|
if (lenP == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
memcpy(secBufBaseM + tsFeedpM, bufP, lenP);
|
memcpy(secBufBaseM + tsFeedpM, bufP, lenP);
|
||||||
@@ -141,7 +144,7 @@ int cSatipSectionFilter::CopyDump(const uint8_t *bufP, uint8_t lenP)
|
|||||||
|
|
||||||
for (n = 0; secBufpM + 2 < limit; ++n) {
|
for (n = 0; secBufpM + 2 < limit; ++n) {
|
||||||
uint16_t seclen = GetLength(secBufM);
|
uint16_t seclen = GetLength(secBufM);
|
||||||
if ((seclen <= 0) || (seclen > eDmxMaxSectionSize) || ((seclen + secBufpM) > limit))
|
if ((seclen > eDmxMaxSectionSize) || ((seclen + secBufpM) > limit))
|
||||||
return 0;
|
return 0;
|
||||||
secLenM = seclen;
|
secLenM = seclen;
|
||||||
if (pusiSeenM)
|
if (pusiSeenM)
|
||||||
@@ -209,27 +212,28 @@ void cSatipSectionFilter::Process(const uint8_t* dataP)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool cSatipSectionFilter::Send(void)
|
void cSatipSectionFilter::Send(void)
|
||||||
{
|
{
|
||||||
bool result = false;
|
|
||||||
cFrame *section = ringBufferM->Get();
|
cFrame *section = ringBufferM->Get();
|
||||||
if (section) {
|
if (section) {
|
||||||
uchar *data = section->Data();
|
uchar *data = section->Data();
|
||||||
int count = section->Count();
|
int count = section->Count();
|
||||||
if (data && (count > 0) && (socketM[1] >= 0) && (socketM[0] >= 0)) {
|
if (data && (count > 0) && (socketM[1] >= 0) && (socketM[0] >= 0)) {
|
||||||
ssize_t len = send(socketM[1], data, count, MSG_EOR);
|
if (send(socketM[1], data, count, MSG_EOR) > 0) {
|
||||||
ERROR_IF(len < 0 && errno != EAGAIN, "send()");
|
|
||||||
if (len > 0) {
|
|
||||||
ringBufferM->Drop(section);
|
|
||||||
result = !!ringBufferM->Available();
|
|
||||||
// Update statistics
|
// Update statistics
|
||||||
AddSectionStatistic(len, 1);
|
AddSectionStatistic(count, 1);
|
||||||
}
|
}
|
||||||
|
else if (errno != EAGAIN)
|
||||||
|
error("failed to send section data (%i bytes) [device=%d]", count, deviceIndexM);
|
||||||
}
|
}
|
||||||
|
ringBufferM->Drop(section);
|
||||||
}
|
}
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int cSatipSectionFilter::Available(void) const
|
||||||
|
{
|
||||||
|
return ringBufferM->Available();
|
||||||
|
}
|
||||||
|
|
||||||
cSatipSectionFilterHandler::cSatipSectionFilterHandler(int deviceIndexP, unsigned int bufferLenP)
|
cSatipSectionFilterHandler::cSatipSectionFilterHandler(int deviceIndexP, unsigned int bufferLenP)
|
||||||
: cThread(cString::sprintf("SATIP#%d section handler", deviceIndexP)),
|
: cThread(cString::sprintf("SATIP#%d section handler", deviceIndexP)),
|
||||||
@@ -267,30 +271,48 @@ cSatipSectionFilterHandler::~cSatipSectionFilterHandler()
|
|||||||
Delete(i);
|
Delete(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void cSatipSectionFilterHandler::SendAll(void)
|
||||||
|
{
|
||||||
|
cMutexLock MutexLock(&mutexM);
|
||||||
|
bool pendingData;
|
||||||
|
do {
|
||||||
|
pendingData = false;
|
||||||
|
|
||||||
|
// zero polling structures
|
||||||
|
memset(pollFdsM, 0, sizeof(pollFdsM));
|
||||||
|
|
||||||
|
// assemble all handlers to poll (use -1 to ignore handlers)
|
||||||
|
for (unsigned int i = 0; i < eMaxSecFilterCount; ++i) {
|
||||||
|
if (filtersM[i] && filtersM[i]->Available() != 0) {
|
||||||
|
pollFdsM[i].fd = filtersM[i]->GetFd();
|
||||||
|
pollFdsM[i].events = POLLOUT;
|
||||||
|
pendingData = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
pollFdsM[i].fd = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// exit if there isn't any pending data or we time out
|
||||||
|
if (!pendingData || poll(pollFdsM, eMaxSecFilterCount, eSecFilterSendTimeoutMs) <= 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// send data (if available)
|
||||||
|
for (unsigned int i = 0; i < eMaxSecFilterCount && pendingData; ++i) {
|
||||||
|
if (pollFdsM[i].revents & POLLOUT)
|
||||||
|
filtersM[i]->Send();
|
||||||
|
}
|
||||||
|
} while (pendingData);
|
||||||
|
}
|
||||||
|
|
||||||
void cSatipSectionFilterHandler::Action(void)
|
void cSatipSectionFilterHandler::Action(void)
|
||||||
{
|
{
|
||||||
debug1("%s Entering [device %d]", __PRETTY_FUNCTION__, deviceIndexM);
|
debug1("%s Entering [device %d]", __PRETTY_FUNCTION__, deviceIndexM);
|
||||||
bool processed = false;
|
|
||||||
// Do the thread loop
|
// Do the thread loop
|
||||||
while (Running()) {
|
while (Running()) {
|
||||||
// Send demuxed section packets through all filters
|
uchar *p = NULL;
|
||||||
bool retry = false;
|
|
||||||
mutexM.Lock();
|
|
||||||
for (unsigned int i = 0; i < eMaxSecFilterCount; ++i) {
|
|
||||||
if (filtersM[i] && filtersM[i]->Send())
|
|
||||||
retry = true;
|
|
||||||
}
|
|
||||||
mutexM.Unlock();
|
|
||||||
if (retry)
|
|
||||||
continue;
|
|
||||||
// Read one TS packet
|
|
||||||
if (ringBufferM) {
|
|
||||||
int len = 0;
|
int len = 0;
|
||||||
if (processed) {
|
// Process all pending TS packets
|
||||||
ringBufferM->Del(TS_SIZE);
|
while ((p = ringBufferM->Get(len)) != NULL) {
|
||||||
processed = false;
|
|
||||||
}
|
|
||||||
uchar *p = ringBufferM->Get(len);
|
|
||||||
if (p && (len >= TS_SIZE)) {
|
if (p && (len >= TS_SIZE)) {
|
||||||
if (*p != TS_SYNC_BYTE) {
|
if (*p != TS_SYNC_BYTE) {
|
||||||
for (int i = 1; i < len; ++i) {
|
for (int i = 1; i < len; ++i) {
|
||||||
@@ -310,11 +332,12 @@ void cSatipSectionFilterHandler::Action(void)
|
|||||||
filtersM[i]->Process(p);
|
filtersM[i]->Process(p);
|
||||||
}
|
}
|
||||||
mutexM.Unlock();
|
mutexM.Unlock();
|
||||||
processed = true;
|
ringBufferM->Del(TS_SIZE);
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cCondWait::SleepMs(10); // to avoid busy loop and reduce cpu load
|
|
||||||
|
// Send demuxed section packets through all filters
|
||||||
|
SendAll();
|
||||||
}
|
}
|
||||||
debug1("%s Exiting [device %d]", __PRETTY_FUNCTION__, deviceIndexM);
|
debug1("%s Exiting [device %d]", __PRETTY_FUNCTION__, deviceIndexM);
|
||||||
}
|
}
|
||||||
@@ -338,6 +361,19 @@ cString cSatipSectionFilterHandler::GetInformation(void)
|
|||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool cSatipSectionFilterHandler::Exists(u_short pidP)
|
||||||
|
{
|
||||||
|
debug16("%s (%d) [device %d]", __PRETTY_FUNCTION__, pidP, deviceIndexM);
|
||||||
|
cMutexLock MutexLock(&mutexM);
|
||||||
|
for (unsigned int i = 0; i < eMaxSecFilterCount; ++i) {
|
||||||
|
if (filtersM[i] && (pidP == filtersM[i]->GetPid())) {
|
||||||
|
debug12("%s (%d) Found [device %d]", __PRETTY_FUNCTION__, pidP, deviceIndexM);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool cSatipSectionFilterHandler::Delete(unsigned int indexP)
|
bool cSatipSectionFilterHandler::Delete(unsigned int indexP)
|
||||||
{
|
{
|
||||||
debug16("%s (%d) [device %d]", __PRETTY_FUNCTION__, indexP, deviceIndexM);
|
debug16("%s (%d) [device %d]", __PRETTY_FUNCTION__, indexP, deviceIndexM);
|
||||||
|
@@ -8,6 +8,7 @@
|
|||||||
#ifndef __SATIP_SECTIONFILTER_H
|
#ifndef __SATIP_SECTIONFILTER_H
|
||||||
#define __SATIP_SECTIONFILTER_H
|
#define __SATIP_SECTIONFILTER_H
|
||||||
|
|
||||||
|
#include <poll.h>
|
||||||
#include <vdr/device.h>
|
#include <vdr/device.h>
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
@@ -55,23 +56,27 @@ public:
|
|||||||
cSatipSectionFilter(int deviceIndexP, uint16_t pidP, uint8_t tidP, uint8_t maskP);
|
cSatipSectionFilter(int deviceIndexP, uint16_t pidP, uint8_t tidP, uint8_t maskP);
|
||||||
virtual ~cSatipSectionFilter();
|
virtual ~cSatipSectionFilter();
|
||||||
void Process(const uint8_t* dataP);
|
void Process(const uint8_t* dataP);
|
||||||
bool Send(void);
|
void Send(void);
|
||||||
int GetFd(void) { return socketM[0]; }
|
int GetFd(void) { return socketM[0]; }
|
||||||
uint16_t GetPid(void) const { return pidM; }
|
uint16_t GetPid(void) const { return pidM; }
|
||||||
|
int Available(void) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
class cSatipSectionFilterHandler : public cThread {
|
class cSatipSectionFilterHandler : public cThread {
|
||||||
private:
|
private:
|
||||||
enum {
|
enum {
|
||||||
eMaxSecFilterCount = 32
|
eMaxSecFilterCount = 32,
|
||||||
|
eSecFilterSendTimeoutMs = 10
|
||||||
};
|
};
|
||||||
cRingBufferLinear *ringBufferM;
|
cRingBufferLinear *ringBufferM;
|
||||||
cMutex mutexM;
|
cMutex mutexM;
|
||||||
int deviceIndexM;
|
int deviceIndexM;
|
||||||
cSatipSectionFilter *filtersM[eMaxSecFilterCount];
|
cSatipSectionFilter *filtersM[eMaxSecFilterCount];
|
||||||
|
struct pollfd pollFdsM[eMaxSecFilterCount];
|
||||||
|
|
||||||
bool Delete(unsigned int indexP);
|
bool Delete(unsigned int indexP);
|
||||||
bool IsBlackListed(u_short pidP, u_char tidP, u_char maskP) const;
|
bool IsBlackListed(u_short pidP, u_char tidP, u_char maskP) const;
|
||||||
|
void SendAll(void);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void Action(void);
|
virtual void Action(void);
|
||||||
@@ -80,6 +85,7 @@ public:
|
|||||||
cSatipSectionFilterHandler(int deviceIndexP, unsigned int bufferLenP);
|
cSatipSectionFilterHandler(int deviceIndexP, unsigned int bufferLenP);
|
||||||
virtual ~cSatipSectionFilterHandler();
|
virtual ~cSatipSectionFilterHandler();
|
||||||
cString GetInformation(void);
|
cString GetInformation(void);
|
||||||
|
bool Exists(u_short pidP);
|
||||||
int Open(u_short pidP, u_char tidP, u_char maskP);
|
int Open(u_short pidP, u_char tidP, u_char maskP);
|
||||||
void Close(int handleP);
|
void Close(int handleP);
|
||||||
int GetPid(int handleP);
|
int GetPid(int handleP);
|
||||||
|
153
server.c
153
server.c
@@ -80,16 +80,39 @@ bool cSatipFrontends::Detach(int deviceIdP, int transponderP)
|
|||||||
|
|
||||||
// --- cSatipServer -----------------------------------------------------------
|
// --- cSatipServer -----------------------------------------------------------
|
||||||
|
|
||||||
cSatipServer::cSatipServer(const char *addressP, const char *modelP, const char *descriptionP)
|
cSatipServer::cSatipServer(const char *srcAddressP, const char *addressP, const int portP, const char *modelP, const char *filtersP, const char *descriptionP, const int quirkP)
|
||||||
: addressM((addressP && *addressP) ? addressP : "0.0.0.0"),
|
: srcAddressM((srcAddressP && *srcAddressP) ? srcAddressP : ""),
|
||||||
|
addressM((addressP && *addressP) ? addressP : "0.0.0.0"),
|
||||||
modelM((modelP && *modelP) ? modelP : "DVBS-1"),
|
modelM((modelP && *modelP) ? modelP : "DVBS-1"),
|
||||||
|
filtersM((filtersP && *filtersP) ? filtersP : ""),
|
||||||
descriptionM(!isempty(descriptionP) ? descriptionP : "MyBrokenHardware"),
|
descriptionM(!isempty(descriptionP) ? descriptionP : "MyBrokenHardware"),
|
||||||
quirksM(""),
|
quirksM(""),
|
||||||
quirkM(eSatipQuirkNone),
|
portM(portP),
|
||||||
|
quirkM(quirkP),
|
||||||
hasCiM(false),
|
hasCiM(false),
|
||||||
|
activeM(true),
|
||||||
createdM(time(NULL)),
|
createdM(time(NULL)),
|
||||||
lastSeenM(0)
|
lastSeenM(0)
|
||||||
{
|
{
|
||||||
|
memset(sourceFiltersM, 0, sizeof(sourceFiltersM));
|
||||||
|
if (!isempty(*filtersM)) {
|
||||||
|
char *s, *p = strdup(*filtersM);
|
||||||
|
char *r = strtok_r(p, ",", &s);
|
||||||
|
unsigned int i = 0;
|
||||||
|
while (r) {
|
||||||
|
int t = cSource::FromString(skipspace(r));
|
||||||
|
if (t && i < ELEMENTS(sourceFiltersM))
|
||||||
|
sourceFiltersM[i++] = t;
|
||||||
|
r = strtok_r(NULL, ",", &s);
|
||||||
|
}
|
||||||
|
if (i) {
|
||||||
|
filtersM = "";
|
||||||
|
for (unsigned int j = 0; j < i; ++j)
|
||||||
|
filtersM = cString::sprintf("%s%s%s", *filtersM, isempty(*filtersM) ? "" : ",", *cSource::ToString(sourceFiltersM[j]));
|
||||||
|
debug3("%s filters=%s", __PRETTY_FUNCTION__, *filtersM);
|
||||||
|
}
|
||||||
|
FREE_POINTER(p);
|
||||||
|
}
|
||||||
if (!SatipConfig.GetDisableServerQuirks()) {
|
if (!SatipConfig.GetDisableServerQuirks()) {
|
||||||
// These devices contain a session id bug:
|
// These devices contain a session id bug:
|
||||||
// Inverto Airscreen Server IDL 400 ?
|
// Inverto Airscreen Server IDL 400 ?
|
||||||
@@ -97,28 +120,62 @@ cSatipServer::cSatipServer(const char *addressP, const char *modelP, const char
|
|||||||
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, "Triax SatIP Converter") // Triax TSS 400
|
strstr(*descriptionM, "Triax SatIP Converter") // Triax TSS 400
|
||||||
) {
|
)
|
||||||
quirkM |= eSatipQuirkSessionId;
|
quirkM |= eSatipQuirkSessionId;
|
||||||
quirksM = cString::sprintf("%s%sSessionId", *quirksM, isempty(*quirksM) ? "" : ",");
|
// These devices contain support for RTP over TCP:
|
||||||
}
|
if (strstr(*descriptionM, "minisatip") || // minisatip server
|
||||||
|
strstr(*descriptionM, "DVBViewer") // DVBViewer Media Server
|
||||||
|
)
|
||||||
|
quirkM |= eSatipQuirkRtpOverTcp;
|
||||||
// These devices contain a play (add/delpids) parameter bug:
|
// These devices contain a play (add/delpids) parameter bug:
|
||||||
if (strstr(*descriptionM, "fritzdvbc") // Fritz!WLAN Repeater DVB-C
|
if (strstr(*descriptionM, "FRITZ!Box 6490 Cable") || // FRITZ!Box 6490 Cable
|
||||||
) {
|
strstr(*descriptionM, "FRITZ!WLAN Repeater DVB-C") || // FRITZ!WLAN Repeater DVB-C
|
||||||
|
strstr(*descriptionM, "fritzdvbc") // FRITZ!WLAN Repeater DVB-C (old firmware)
|
||||||
|
)
|
||||||
quirkM |= eSatipQuirkPlayPids;
|
quirkM |= eSatipQuirkPlayPids;
|
||||||
quirksM = cString::sprintf("%s%sPlayPids", *quirksM, isempty(*quirksM) ? "" : ",");
|
|
||||||
}
|
|
||||||
// These devices contain a frontend locking bug:
|
// These devices contain a frontend locking bug:
|
||||||
if (strstr(*descriptionM, "fritzdvbc") || // Fritz!WLAN Repeater DVB-C
|
if (strstr(*descriptionM, "FRITZ!Box 6490 Cable") || // FRITZ!Box 6490 Cable
|
||||||
|
strstr(*descriptionM, "FRITZ!WLAN Repeater DVB-C") || // FRITZ!WLAN Repeater DVB-C
|
||||||
|
strstr(*descriptionM, "fritzdvbc") || // FRITZ!WLAN Repeater DVB-C (old firmware)
|
||||||
strstr(*descriptionM, "Schwaiger Sat>IP Server") // Schwaiger MS41IP
|
strstr(*descriptionM, "Schwaiger Sat>IP Server") // Schwaiger MS41IP
|
||||||
) {
|
)
|
||||||
quirkM |= eSatipQuirkForceLock;
|
quirkM |= eSatipQuirkForceLock;
|
||||||
quirksM = cString::sprintf("%s%sForceLock", *quirksM, isempty(*quirksM) ? "" : ",");
|
|
||||||
}
|
|
||||||
debug3("%s description=%s quirks=%s", __PRETTY_FUNCTION__, *descriptionM, *quirksM);
|
|
||||||
}
|
|
||||||
// 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;
|
||||||
|
// These devices support the TNR protocol extension
|
||||||
|
if (strstr(*descriptionM, "DVBViewer") // DVBViewer Media Server
|
||||||
|
)
|
||||||
|
quirkM |= eSatipQuirkCiTnr;
|
||||||
|
// These devices don't support auto-detection of pilot tones
|
||||||
|
if (strstr(*descriptionM, "GSSBOX") || // Grundig Sat Systems GSS.box DSI 400
|
||||||
|
strstr(*descriptionM, "DIGIBIT") || // Telestar Digibit R1
|
||||||
|
strstr(*descriptionM, "Triax SatIP Converter") || // Triax TSS 400
|
||||||
|
strstr(*descriptionM, "KATHREIN SatIP Server") // Kathrein ExIP 414/E
|
||||||
|
)
|
||||||
|
quirkM |= eSatipQuirkForcePilot;
|
||||||
|
}
|
||||||
|
if ((quirkM & eSatipQuirkMask) & eSatipQuirkSessionId)
|
||||||
|
quirksM = cString::sprintf("%s%sSessionId", *quirksM, isempty(*quirksM) ? "" : ",");
|
||||||
|
if ((quirkM & eSatipQuirkMask) & eSatipQuirkPlayPids)
|
||||||
|
quirksM = cString::sprintf("%s%sPlayPids", *quirksM, isempty(*quirksM) ? "" : ",");
|
||||||
|
if ((quirkM & eSatipQuirkMask) & eSatipQuirkForceLock)
|
||||||
|
quirksM = cString::sprintf("%s%sForceLock", *quirksM, isempty(*quirksM) ? "" : ",");
|
||||||
|
if ((quirkM & eSatipQuirkMask) & eSatipQuirkRtpOverTcp)
|
||||||
|
quirksM = cString::sprintf("%s%sRtpOverTcp", *quirksM, isempty(*quirksM) ? "" : ",");
|
||||||
|
if ((quirkM & eSatipQuirkMask) & eSatipQuirkCiXpmt)
|
||||||
|
quirksM = cString::sprintf("%s%sCiXpmt", *quirksM, isempty(*quirksM) ? "" : ",");
|
||||||
|
if ((quirkM & eSatipQuirkMask) & eSatipQuirkCiTnr)
|
||||||
|
quirksM = cString::sprintf("%s%sCiTnr", *quirksM, isempty(*quirksM) ? "" : ",");
|
||||||
|
if ((quirkM & eSatipQuirkMask) & eSatipQuirkForcePilot)
|
||||||
|
quirksM = cString::sprintf("%s%sForcePilot", *quirksM, isempty(*quirksM) ? "" : ",");
|
||||||
|
debug3("%s description=%s quirks=%s", __PRETTY_FUNCTION__, *descriptionM, *quirksM);
|
||||||
|
// These devices support external CI
|
||||||
|
if (strstr(*descriptionM, "OctopusNet") || // Digital Devices OctopusNet
|
||||||
|
strstr(*descriptionM, "minisatip") || // minisatip server
|
||||||
|
strstr(*descriptionM, "DVBViewer") // DVBViewer Media Server
|
||||||
) {
|
) {
|
||||||
hasCiM = true;
|
hasCiM = true;
|
||||||
}
|
}
|
||||||
@@ -153,7 +210,7 @@ cSatipServer::cSatipServer(const char *addressP, const char *modelP, const char
|
|||||||
}
|
}
|
||||||
r = strtok_r(NULL, ",", &s);
|
r = strtok_r(NULL, ",", &s);
|
||||||
}
|
}
|
||||||
free(p);
|
FREE_POINTER(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
cSatipServer::~cSatipServer()
|
cSatipServer::~cSatipServer()
|
||||||
@@ -172,9 +229,23 @@ int cSatipServer::Compare(const cListObject &listObjectP) const
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool cSatipServer::IsValidSource(int sourceP)
|
||||||
|
{
|
||||||
|
if (sourceFiltersM[0]) {
|
||||||
|
for (unsigned int i = 0; i < ELEMENTS(sourceFiltersM); ++i) {
|
||||||
|
if (sourceP == sourceFiltersM[i]) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool cSatipServer::Assign(int deviceIdP, int sourceP, int systemP, int transponderP)
|
bool cSatipServer::Assign(int deviceIdP, int sourceP, int systemP, int transponderP)
|
||||||
{
|
{
|
||||||
bool result = false;
|
bool result = false;
|
||||||
|
if (IsValidSource(sourceP)) {
|
||||||
if (cSource::IsType(sourceP, 'S'))
|
if (cSource::IsType(sourceP, 'S'))
|
||||||
result = frontendsM[eSatipFrontendDVBS2].Assign(deviceIdP, transponderP);
|
result = frontendsM[eSatipFrontendDVBS2].Assign(deviceIdP, transponderP);
|
||||||
else if (cSource::IsType(sourceP, 'T')) {
|
else if (cSource::IsType(sourceP, 'T')) {
|
||||||
@@ -189,23 +260,27 @@ 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);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool cSatipServer::Matches(int sourceP)
|
bool cSatipServer::Matches(int sourceP)
|
||||||
{
|
{
|
||||||
|
if (IsValidSource(sourceP)) {
|
||||||
if (cSource::IsType(sourceP, 'S'))
|
if (cSource::IsType(sourceP, 'S'))
|
||||||
return GetModulesDVBS2();
|
return GetModulesDVBS2();
|
||||||
else if (cSource::IsType(sourceP, 'T'))
|
else if (cSource::IsType(sourceP, 'T'))
|
||||||
return GetModulesDVBT() || GetModulesDVBT2();
|
return GetModulesDVBT() || GetModulesDVBT2();
|
||||||
else if (cSource::IsType(sourceP, 'C'))
|
else if (cSource::IsType(sourceP, 'C'))
|
||||||
return GetModulesDVBC() || GetModulesDVBC2();
|
return GetModulesDVBC() || GetModulesDVBC2();
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool cSatipServer::Matches(int deviceIdP, int sourceP, int systemP, int transponderP)
|
bool cSatipServer::Matches(int deviceIdP, int sourceP, int systemP, int transponderP)
|
||||||
{
|
{
|
||||||
bool result = false;
|
bool result = false;
|
||||||
|
if (IsValidSource(sourceP)) {
|
||||||
if (cSource::IsType(sourceP, 'S'))
|
if (cSource::IsType(sourceP, 'S'))
|
||||||
result = frontendsM[eSatipFrontendDVBS2].Matches(deviceIdP, transponderP);
|
result = frontendsM[eSatipFrontendDVBS2].Matches(deviceIdP, transponderP);
|
||||||
else if (cSource::IsType(sourceP, 'T')) {
|
else if (cSource::IsType(sourceP, 'T')) {
|
||||||
@@ -220,6 +295,7 @@ 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);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -287,11 +363,11 @@ cSatipServer *cSatipServers::Find(int sourceP)
|
|||||||
cSatipServer *cSatipServers::Assign(int deviceIdP, int sourceP, int transponderP, int systemP)
|
cSatipServer *cSatipServers::Assign(int deviceIdP, int sourceP, int transponderP, int systemP)
|
||||||
{
|
{
|
||||||
for (cSatipServer *s = First(); s; s = Next(s)) {
|
for (cSatipServer *s = First(); s; s = Next(s)) {
|
||||||
if (s->Matches(deviceIdP, sourceP, systemP, transponderP))
|
if (s->IsActive() && s->Matches(deviceIdP, sourceP, systemP, transponderP))
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
for (cSatipServer *s = First(); s; s = Next(s)) {
|
for (cSatipServer *s = First(); s; s = Next(s)) {
|
||||||
if (s->Assign(deviceIdP, sourceP, systemP, transponderP))
|
if (s->IsActive() && s->Assign(deviceIdP, sourceP, systemP, transponderP))
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -308,6 +384,16 @@ cSatipServer *cSatipServers::Update(cSatipServer *serverP)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void cSatipServers::Activate(cSatipServer *serverP, bool onOffP)
|
||||||
|
{
|
||||||
|
for (cSatipServer *s = First(); s; s = Next(s)) {
|
||||||
|
if (s == serverP) {
|
||||||
|
s->Activate(onOffP);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void cSatipServers::Attach(cSatipServer *serverP, int deviceIdP, int transponderP)
|
void cSatipServers::Attach(cSatipServer *serverP, int deviceIdP, int transponderP)
|
||||||
{
|
{
|
||||||
for (cSatipServer *s = First(); s; s = Next(s)) {
|
for (cSatipServer *s = First(); s; s = Next(s)) {
|
||||||
@@ -362,6 +448,18 @@ void cSatipServers::Cleanup(uint64_t intervalMsP)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cString cSatipServers::GetSrcAddress(cSatipServer *serverP)
|
||||||
|
{
|
||||||
|
cString address = "";
|
||||||
|
for (cSatipServer *s = First(); s; s = Next(s)) {
|
||||||
|
if (s == serverP) {
|
||||||
|
address = s->SrcAddress();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return address;
|
||||||
|
}
|
||||||
|
|
||||||
cString cSatipServers::GetAddress(cSatipServer *serverP)
|
cString cSatipServers::GetAddress(cSatipServer *serverP)
|
||||||
{
|
{
|
||||||
cString address = "";
|
cString address = "";
|
||||||
@@ -374,6 +472,18 @@ cString cSatipServers::GetAddress(cSatipServer *serverP)
|
|||||||
return address;
|
return address;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int cSatipServers::GetPort(cSatipServer *serverP)
|
||||||
|
{
|
||||||
|
int port = SATIP_DEFAULT_RTSP_PORT;
|
||||||
|
for (cSatipServer *s = First(); s; s = Next(s)) {
|
||||||
|
if (s == serverP) {
|
||||||
|
port = s->Port();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return port;
|
||||||
|
}
|
||||||
|
|
||||||
cString cSatipServers::GetString(cSatipServer *serverP)
|
cString cSatipServers::GetString(cSatipServer *serverP)
|
||||||
{
|
{
|
||||||
cString list = "";
|
cString list = "";
|
||||||
@@ -390,7 +500,10 @@ cString cSatipServers::List(void)
|
|||||||
{
|
{
|
||||||
cString list = "";
|
cString list = "";
|
||||||
for (cSatipServer *s = First(); s; s = Next(s))
|
for (cSatipServer *s = First(); s; s = Next(s))
|
||||||
list = cString::sprintf("%s%s|%s|%s\n", *list, s->Address(), s->Model(), s->Description());
|
if (isempty(s->SrcAddress()))
|
||||||
|
list = cString::sprintf("%s%c %s|%s|%s\n", *list, s->IsActive() ? '+' : '-', s->Address(), s->Model(), s->Description());
|
||||||
|
else
|
||||||
|
list = cString::sprintf("%s%c %s@%s|%s|%s\n", *list, s->IsActive() ? '+' : '-', s->SrcAddress(), s->Address(), s->Model(), s->Description());
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
25
server.h
25
server.h
@@ -54,15 +54,24 @@ private:
|
|||||||
eSatipFrontendDVBC2,
|
eSatipFrontendDVBC2,
|
||||||
eSatipFrontendCount
|
eSatipFrontendCount
|
||||||
};
|
};
|
||||||
|
enum {
|
||||||
|
eSatipMaxSourceFilters = 16
|
||||||
|
};
|
||||||
|
cString srcAddressM;
|
||||||
cString addressM;
|
cString addressM;
|
||||||
cString modelM;
|
cString modelM;
|
||||||
|
cString filtersM;
|
||||||
cString descriptionM;
|
cString descriptionM;
|
||||||
cString quirksM;
|
cString quirksM;
|
||||||
cSatipFrontends frontendsM[eSatipFrontendCount];
|
cSatipFrontends frontendsM[eSatipFrontendCount];
|
||||||
|
int sourceFiltersM[eSatipMaxSourceFilters];
|
||||||
|
int portM;
|
||||||
int quirkM;
|
int quirkM;
|
||||||
bool hasCiM;
|
bool hasCiM;
|
||||||
|
bool activeM;
|
||||||
time_t createdM;
|
time_t createdM;
|
||||||
cTimeMs lastSeenM;
|
cTimeMs lastSeenM;
|
||||||
|
bool IsValidSource(int sourceP);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
enum eSatipQuirk {
|
enum eSatipQuirk {
|
||||||
@@ -70,9 +79,13 @@ public:
|
|||||||
eSatipQuirkSessionId = 0x01,
|
eSatipQuirkSessionId = 0x01,
|
||||||
eSatipQuirkPlayPids = 0x02,
|
eSatipQuirkPlayPids = 0x02,
|
||||||
eSatipQuirkForceLock = 0x04,
|
eSatipQuirkForceLock = 0x04,
|
||||||
eSatipQuirkMask = 0x0F
|
eSatipQuirkRtpOverTcp = 0x08,
|
||||||
|
eSatipQuirkCiXpmt = 0x10,
|
||||||
|
eSatipQuirkCiTnr = 0x20,
|
||||||
|
eSatipQuirkForcePilot = 0x40,
|
||||||
|
eSatipQuirkMask = 0xFF
|
||||||
};
|
};
|
||||||
cSatipServer(const char *addressP, const char *modelP, const char *descriptionP);
|
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();
|
||||||
virtual int Compare(const cListObject &listObjectP) const;
|
virtual int Compare(const cListObject &listObjectP) const;
|
||||||
bool Assign(int deviceIdP, int sourceP, int systemP, int transponderP);
|
bool Assign(int deviceIdP, int sourceP, int systemP, int transponderP);
|
||||||
@@ -85,13 +98,18 @@ public:
|
|||||||
int GetModulesDVBT2(void);
|
int GetModulesDVBT2(void);
|
||||||
int GetModulesDVBC(void);
|
int GetModulesDVBC(void);
|
||||||
int GetModulesDVBC2(void);
|
int GetModulesDVBC2(void);
|
||||||
|
void Activate(bool onOffP) { activeM = onOffP; }
|
||||||
|
const char *SrcAddress(void) { return *srcAddressM; }
|
||||||
const char *Address(void) { return *addressM; }
|
const char *Address(void) { return *addressM; }
|
||||||
const char *Model(void) { return *modelM; }
|
const char *Model(void) { return *modelM; }
|
||||||
|
const char *Filters(void) { return *filtersM; }
|
||||||
const char *Description(void) { return *descriptionM; }
|
const char *Description(void) { return *descriptionM; }
|
||||||
const char *Quirks(void) { return *quirksM; }
|
const char *Quirks(void) { return *quirksM; }
|
||||||
|
int Port(void) { return portM; }
|
||||||
bool Quirk(int quirkP) { return ((quirkP & eSatipQuirkMask) & quirkM); }
|
bool Quirk(int quirkP) { return ((quirkP & eSatipQuirkMask) & quirkM); }
|
||||||
bool HasQuirk(void) { return (quirkM != eSatipQuirkNone); }
|
bool HasQuirk(void) { return (quirkM != eSatipQuirkNone); }
|
||||||
bool HasCI(void) { return hasCiM; }
|
bool HasCI(void) { return hasCiM; }
|
||||||
|
bool IsActive(void) { return activeM; }
|
||||||
void Update(void) { lastSeenM.Set(); }
|
void Update(void) { lastSeenM.Set(); }
|
||||||
uint64_t LastSeen(void) { return lastSeenM.Elapsed(); }
|
uint64_t LastSeen(void) { return lastSeenM.Elapsed(); }
|
||||||
time_t Created(void) { return createdM; }
|
time_t Created(void) { return createdM; }
|
||||||
@@ -105,13 +123,16 @@ public:
|
|||||||
cSatipServer *Find(int sourceP);
|
cSatipServer *Find(int sourceP);
|
||||||
cSatipServer *Assign(int deviceIdP, int sourceP, int transponderP, int systemP);
|
cSatipServer *Assign(int deviceIdP, int sourceP, int transponderP, int systemP);
|
||||||
cSatipServer *Update(cSatipServer *serverP);
|
cSatipServer *Update(cSatipServer *serverP);
|
||||||
|
void Activate(cSatipServer *serverP, bool onOffP);
|
||||||
void Attach(cSatipServer *serverP, int deviceIdP, int transponderP);
|
void Attach(cSatipServer *serverP, int deviceIdP, int transponderP);
|
||||||
void Detach(cSatipServer *serverP, int deviceIdP, int transponderP);
|
void Detach(cSatipServer *serverP, int deviceIdP, int transponderP);
|
||||||
bool IsQuirk(cSatipServer *serverP, int quirkP);
|
bool IsQuirk(cSatipServer *serverP, int quirkP);
|
||||||
bool HasCI(cSatipServer *serverP);
|
bool HasCI(cSatipServer *serverP);
|
||||||
void Cleanup(uint64_t intervalMsP = 0);
|
void Cleanup(uint64_t intervalMsP = 0);
|
||||||
cString GetAddress(cSatipServer *serverP);
|
cString GetAddress(cSatipServer *serverP);
|
||||||
|
cString GetSrcAddress(cSatipServer *serverP);
|
||||||
cString GetString(cSatipServer *serverP);
|
cString GetString(cSatipServer *serverP);
|
||||||
|
int GetPort(cSatipServer *serverP);
|
||||||
cString List(void);
|
cString List(void);
|
||||||
int NumProvidedSystems(void);
|
int NumProvidedSystems(void);
|
||||||
};
|
};
|
||||||
|
30
setup.c
30
setup.c
@@ -86,6 +86,8 @@ eOSState cSatipEditSrcItem::ProcessKey(eKeys Key)
|
|||||||
class cSatipServerInfo : public cOsdMenu
|
class cSatipServerInfo : public cOsdMenu
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
cSatipServer *serverM;
|
||||||
|
int activeM;
|
||||||
cString addressM;
|
cString addressM;
|
||||||
cString modelM;
|
cString modelM;
|
||||||
cString descriptionM;
|
cString descriptionM;
|
||||||
@@ -101,7 +103,9 @@ public:
|
|||||||
|
|
||||||
cSatipServerInfo::cSatipServerInfo(cSatipServer *serverP)
|
cSatipServerInfo::cSatipServerInfo(cSatipServer *serverP)
|
||||||
: cOsdMenu(tr("SAT>IP Server"), 20),
|
: cOsdMenu(tr("SAT>IP Server"), 20),
|
||||||
addressM(serverP ? serverP->Address() : "---"),
|
serverM(serverP),
|
||||||
|
activeM(serverP && serverP->IsActive()),
|
||||||
|
addressM(serverP ? (isempty(serverP->SrcAddress()) ? serverP->Address() : *cString::sprintf("%s@%s", serverP->SrcAddress(), serverP->Address())) : "---"),
|
||||||
modelM(serverP ? serverP->Model() : "---"),
|
modelM(serverP ? serverP->Model() : "---"),
|
||||||
descriptionM(serverP ? serverP->Description() : "---"),
|
descriptionM(serverP ? serverP->Description() : "---"),
|
||||||
ciExtensionM(serverP && serverP->HasCI() ? trVDR("yes") : trVDR("no")),
|
ciExtensionM(serverP && serverP->HasCI() ? trVDR("yes") : trVDR("no")),
|
||||||
@@ -118,6 +122,7 @@ cSatipServerInfo::~cSatipServerInfo()
|
|||||||
|
|
||||||
void cSatipServerInfo::Setup(void)
|
void cSatipServerInfo::Setup(void)
|
||||||
{
|
{
|
||||||
|
Add(new cMenuEditBoolItem(trVDR("Active"), &activeM));
|
||||||
Add(new cOsdItem(cString::sprintf("%s:\t%s", tr("Address"), *addressM), osUnknown, false));
|
Add(new cOsdItem(cString::sprintf("%s:\t%s", tr("Address"), *addressM), osUnknown, false));
|
||||||
Add(new cOsdItem(cString::sprintf("%s:\t%s", tr("Model"), *modelM), osUnknown, false));
|
Add(new cOsdItem(cString::sprintf("%s:\t%s", tr("Model"), *modelM), osUnknown, false));
|
||||||
Add(new cOsdItem(cString::sprintf("%s:\t%s", tr("Description"), *descriptionM), osUnknown, false));
|
Add(new cOsdItem(cString::sprintf("%s:\t%s", tr("Description"), *descriptionM), osUnknown, false));
|
||||||
@@ -127,6 +132,7 @@ void cSatipServerInfo::Setup(void)
|
|||||||
|
|
||||||
eOSState cSatipServerInfo::ProcessKey(eKeys keyP)
|
eOSState cSatipServerInfo::ProcessKey(eKeys keyP)
|
||||||
{
|
{
|
||||||
|
int oldActive = activeM;
|
||||||
eOSState state = cOsdMenu::ProcessKey(keyP);
|
eOSState state = cOsdMenu::ProcessKey(keyP);
|
||||||
|
|
||||||
if (state == osUnknown) {
|
if (state == osUnknown) {
|
||||||
@@ -135,6 +141,12 @@ eOSState cSatipServerInfo::ProcessKey(eKeys keyP)
|
|||||||
default: state = osContinue; break;
|
default: state = osContinue; break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (keyP != kNone && oldActive != activeM) {
|
||||||
|
cSatipDiscover::GetInstance()->ActivateServer(serverM, activeM);
|
||||||
|
Setup();
|
||||||
|
}
|
||||||
|
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -155,7 +167,7 @@ cSatipServerItem::cSatipServerItem(cSatipServer *serverP)
|
|||||||
{
|
{
|
||||||
SetSelectable(true);
|
SetSelectable(true);
|
||||||
// Must begin with a '#' character!
|
// Must begin with a '#' character!
|
||||||
SetText(*cString::sprintf("# %s (%s)\t%s", serverM->Address(), serverM->Model(), serverM->Description()));
|
SetText(*cString::sprintf("%s %s (%s)\t%s", serverM->IsActive() ? "+" : "-", isempty(serverM->SrcAddress()) ? serverM->Address() : *cString::sprintf("%s@%s", serverM->SrcAddress(), serverM->Address()), serverM->Model(), serverM->Description()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void cSatipServerItem::SetMenuItem(cSkinDisplayMenu *displayMenuP, int indexP, bool currentP, bool selectableP)
|
void cSatipServerItem::SetMenuItem(cSkinDisplayMenu *displayMenuP, int indexP, bool currentP, bool selectableP)
|
||||||
@@ -333,6 +345,7 @@ cSatipPluginSetup::cSatipPluginSetup()
|
|||||||
: detachedModeM(SatipConfig.GetDetachedMode()),
|
: detachedModeM(SatipConfig.GetDetachedMode()),
|
||||||
deviceCountM(0),
|
deviceCountM(0),
|
||||||
operatingModeM(SatipConfig.GetOperatingMode()),
|
operatingModeM(SatipConfig.GetOperatingMode()),
|
||||||
|
transportModeM(SatipConfig.GetTransportMode()),
|
||||||
ciExtensionM(SatipConfig.GetCIExtension()),
|
ciExtensionM(SatipConfig.GetCIExtension()),
|
||||||
eitScanM(SatipConfig.GetEITScan()),
|
eitScanM(SatipConfig.GetEITScan()),
|
||||||
numDisabledSourcesM(SatipConfig.GetDisabledSourcesCount()),
|
numDisabledSourcesM(SatipConfig.GetDisabledSourcesCount()),
|
||||||
@@ -343,6 +356,9 @@ cSatipPluginSetup::cSatipPluginSetup()
|
|||||||
operatingModeTextsM[cSatipConfig::eOperatingModeLow] = tr("low");
|
operatingModeTextsM[cSatipConfig::eOperatingModeLow] = tr("low");
|
||||||
operatingModeTextsM[cSatipConfig::eOperatingModeNormal] = tr("normal");
|
operatingModeTextsM[cSatipConfig::eOperatingModeNormal] = tr("normal");
|
||||||
operatingModeTextsM[cSatipConfig::eOperatingModeHigh] = tr("high");
|
operatingModeTextsM[cSatipConfig::eOperatingModeHigh] = tr("high");
|
||||||
|
transportModeTextsM[cSatipConfig::eTransportModeUnicast] = tr("Unicast");
|
||||||
|
transportModeTextsM[cSatipConfig::eTransportModeMulticast] = tr("Multicast");
|
||||||
|
transportModeTextsM[cSatipConfig::eTransportModeRtpOverTcp] = tr("RTP-over-TCP");
|
||||||
for (unsigned int i = 0; i < ELEMENTS(cicamsM); ++i)
|
for (unsigned int i = 0; i < ELEMENTS(cicamsM); ++i)
|
||||||
cicamsM[i] = SatipConfig.GetCICAM(i);
|
cicamsM[i] = SatipConfig.GetCICAM(i);
|
||||||
for (unsigned int i = 0; i < ELEMENTS(ca_systems_table); ++i)
|
for (unsigned int i = 0; i < ELEMENTS(ca_systems_table); ++i)
|
||||||
@@ -400,6 +416,8 @@ void cSatipPluginSetup::Setup(void)
|
|||||||
helpM.Append(tr("Define an ill-behaving filter to be blacklisted."));
|
helpM.Append(tr("Define an ill-behaving filter to be blacklisted."));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Add(new cMenuEditStraItem(tr("Transport mode"), &transportModeM, ELEMENTS(transportModeTextsM), transportModeTextsM));
|
||||||
|
helpM.Append(tr("Define which transport mode shall be used.\n\nUnicast, Multicast, RTP-over-TCP"));
|
||||||
Add(new cOsdItem(tr("Active SAT>IP servers:"), osUnknown, false));
|
Add(new cOsdItem(tr("Active SAT>IP servers:"), osUnknown, false));
|
||||||
helpM.Append("");
|
helpM.Append("");
|
||||||
|
|
||||||
@@ -465,10 +483,12 @@ eOSState cSatipPluginSetup::ProcessKey(eKeys keyP)
|
|||||||
int oldNumDisabledFilters = numDisabledFiltersM;
|
int oldNumDisabledFilters = numDisabledFiltersM;
|
||||||
eOSState state = cMenuSetupPage::ProcessKey(keyP);
|
eOSState state = cMenuSetupPage::ProcessKey(keyP);
|
||||||
|
|
||||||
// Ugly hack with hardcoded '#' character :(
|
// Ugly hack with hardcoded '+/-' characters :(
|
||||||
const char *p = Get(Current())->Text();
|
const char *p = Get(Current())->Text();
|
||||||
if (!hadSubMenu && !HasSubMenu() && (*p == '#') && (keyP == kOk))
|
if (!hadSubMenu && !HasSubMenu() && p && (*p == '+' || *p == '-') && (keyP == kOk))
|
||||||
return DeviceInfo();
|
return DeviceInfo();
|
||||||
|
if (hadSubMenu && !HasSubMenu())
|
||||||
|
Setup();
|
||||||
|
|
||||||
if (state == osUnknown) {
|
if (state == osUnknown) {
|
||||||
switch (keyP) {
|
switch (keyP) {
|
||||||
@@ -547,6 +567,7 @@ void cSatipPluginSetup::Store(void)
|
|||||||
{
|
{
|
||||||
// Store values into setup.conf
|
// Store values into setup.conf
|
||||||
SetupStore("OperatingMode", operatingModeM);
|
SetupStore("OperatingMode", operatingModeM);
|
||||||
|
SetupStore("TransportMode", transportModeM);
|
||||||
SetupStore("EnableCIExtension", ciExtensionM);
|
SetupStore("EnableCIExtension", ciExtensionM);
|
||||||
SetupStore("EnableEITScan", eitScanM);
|
SetupStore("EnableEITScan", eitScanM);
|
||||||
StoreCicams("CICAM", cicamsM);
|
StoreCicams("CICAM", cicamsM);
|
||||||
@@ -554,6 +575,7 @@ void cSatipPluginSetup::Store(void)
|
|||||||
StoreFilters("DisabledFilters", disabledFilterIndexesM);
|
StoreFilters("DisabledFilters", disabledFilterIndexesM);
|
||||||
// Update global config
|
// Update global config
|
||||||
SatipConfig.SetOperatingMode(operatingModeM);
|
SatipConfig.SetOperatingMode(operatingModeM);
|
||||||
|
SatipConfig.SetTransportMode(transportModeM);
|
||||||
SatipConfig.SetCIExtension(ciExtensionM);
|
SatipConfig.SetCIExtension(ciExtensionM);
|
||||||
SatipConfig.SetEITScan(eitScanM);
|
SatipConfig.SetEITScan(eitScanM);
|
||||||
for (int i = 0; i < MAX_CICAM_COUNT; ++i)
|
for (int i = 0; i < MAX_CICAM_COUNT; ++i)
|
||||||
|
2
setup.h
2
setup.h
@@ -18,7 +18,9 @@ private:
|
|||||||
bool detachedModeM;
|
bool detachedModeM;
|
||||||
int deviceCountM;
|
int deviceCountM;
|
||||||
int operatingModeM;
|
int operatingModeM;
|
||||||
|
int transportModeM;
|
||||||
const char *operatingModeTextsM[cSatipConfig::eOperatingModeCount];
|
const char *operatingModeTextsM[cSatipConfig::eOperatingModeCount];
|
||||||
|
const char *transportModeTextsM[cSatipConfig::eTransportModeCount];
|
||||||
int ciExtensionM;
|
int ciExtensionM;
|
||||||
int cicamsM[MAX_CICAM_COUNT];
|
int cicamsM[MAX_CICAM_COUNT];
|
||||||
const char *cicamTextsM[CA_SYSTEMS_TABLE_SIZE];
|
const char *cicamTextsM[CA_SYSTEMS_TABLE_SIZE];
|
||||||
|
182
socket.c
182
socket.c
@@ -19,9 +19,35 @@
|
|||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "socket.h"
|
#include "socket.h"
|
||||||
|
|
||||||
|
#if defined(__GLIBC__)
|
||||||
|
#if defined(__GLIBC_PREREQ)
|
||||||
|
#if !__GLIBC_PREREQ(2,12)
|
||||||
|
#define __SATIP_DISABLE_RECVMMSG__
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
cSatipSocket::cSatipSocket()
|
cSatipSocket::cSatipSocket()
|
||||||
: socketPortM(0),
|
: socketPortM(0),
|
||||||
socketDescM(-1)
|
socketDescM(-1),
|
||||||
|
isMulticastM(false),
|
||||||
|
useSsmM(false),
|
||||||
|
streamAddrM(htonl(INADDR_ANY)),
|
||||||
|
sourceAddrM(htonl(INADDR_ANY)),
|
||||||
|
rcvBufSizeM(0)
|
||||||
|
{
|
||||||
|
debug1("%s", __PRETTY_FUNCTION__);
|
||||||
|
memset(&sockAddrM, 0, sizeof(sockAddrM));
|
||||||
|
}
|
||||||
|
|
||||||
|
cSatipSocket::cSatipSocket(size_t rcvBufSizeP)
|
||||||
|
: socketPortM(0),
|
||||||
|
socketDescM(-1),
|
||||||
|
isMulticastM(false),
|
||||||
|
useSsmM(false),
|
||||||
|
streamAddrM(htonl(INADDR_ANY)),
|
||||||
|
sourceAddrM(htonl(INADDR_ANY)),
|
||||||
|
rcvBufSizeM(rcvBufSizeP)
|
||||||
{
|
{
|
||||||
debug1("%s", __PRETTY_FUNCTION__);
|
debug1("%s", __PRETTY_FUNCTION__);
|
||||||
memset(&sockAddrM, 0, sizeof(sockAddrM));
|
memset(&sockAddrM, 0, sizeof(sockAddrM));
|
||||||
@@ -34,10 +60,17 @@ cSatipSocket::~cSatipSocket()
|
|||||||
Close();
|
Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool cSatipSocket::Open(const int portP)
|
bool cSatipSocket::Open(const int portP, const bool reuseP)
|
||||||
{
|
{
|
||||||
|
// If socket is there already and it is bound to a different port, it must
|
||||||
|
// be closed first
|
||||||
|
if (portP != socketPortM) {
|
||||||
|
debug1("%s (%d, %d) Socket tear-down", __PRETTY_FUNCTION__, portP, reuseP);
|
||||||
|
Close();
|
||||||
|
}
|
||||||
// Bind to the socket if it is not active already
|
// Bind to the socket if it is not active already
|
||||||
if (socketDescM < 0) {
|
if (socketDescM < 0) {
|
||||||
|
int yes;
|
||||||
socklen_t len = sizeof(sockAddrM);
|
socklen_t len = sizeof(sockAddrM);
|
||||||
// Create socket
|
// Create socket
|
||||||
socketDescM = socket(PF_INET, SOCK_DGRAM, 0);
|
socketDescM = socket(PF_INET, SOCK_DGRAM, 0);
|
||||||
@@ -46,9 +79,24 @@ bool cSatipSocket::Open(const int portP)
|
|||||||
ERROR_IF_FUNC(fcntl(socketDescM, F_SETFL, O_NONBLOCK), "fcntl(O_NONBLOCK)",
|
ERROR_IF_FUNC(fcntl(socketDescM, F_SETFL, O_NONBLOCK), "fcntl(O_NONBLOCK)",
|
||||||
Close(), return false);
|
Close(), return false);
|
||||||
// Allow multiple sockets to use the same PORT number
|
// Allow multiple sockets to use the same PORT number
|
||||||
int yes = 1;
|
yes = reuseP;
|
||||||
ERROR_IF_FUNC(setsockopt(socketDescM, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) < 0,
|
ERROR_IF_FUNC(setsockopt(socketDescM, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) < 0,
|
||||||
"setsockopt(SO_REUSEADDR)", Close(), return false);
|
"setsockopt(SO_REUSEADDR)", Close(), return false);
|
||||||
|
yes = reuseP;
|
||||||
|
#ifdef SO_REUSEPORT
|
||||||
|
ERROR_IF_FUNC(setsockopt(socketDescM, SOL_SOCKET, SO_REUSEPORT, &yes, sizeof(yes)) < 0 && errno != ENOPROTOOPT,
|
||||||
|
"setsockopt(SO_REUSEPORT)", Close(), return false);
|
||||||
|
#endif
|
||||||
|
#ifndef __FreeBSD__
|
||||||
|
// Allow packet information to be fetched
|
||||||
|
ERROR_IF_FUNC(setsockopt(socketDescM, SOL_IP, IP_PKTINFO, &yes, sizeof(yes)) < 0,
|
||||||
|
"setsockopt(IP_PKTINFO)", Close(), return false);
|
||||||
|
#endif // __FreeBSD__
|
||||||
|
// Tweak receive buffer size if requested
|
||||||
|
if (rcvBufSizeM > 0) {
|
||||||
|
ERROR_IF_FUNC(setsockopt(socketDescM, SOL_SOCKET, SO_RCVBUF, &rcvBufSizeM, sizeof(rcvBufSizeM)) < 0,
|
||||||
|
"setsockopt(SO_RCVBUF)", Close(), return false);
|
||||||
|
}
|
||||||
// Bind socket
|
// Bind socket
|
||||||
memset(&sockAddrM, 0, sizeof(sockAddrM));
|
memset(&sockAddrM, 0, sizeof(sockAddrM));
|
||||||
sockAddrM.sin_family = AF_INET;
|
sockAddrM.sin_family = AF_INET;
|
||||||
@@ -60,20 +108,38 @@ bool cSatipSocket::Open(const int portP)
|
|||||||
ERROR_IF_FUNC(getsockname(socketDescM, (struct sockaddr*)&sockAddrM, &len) < 0,
|
ERROR_IF_FUNC(getsockname(socketDescM, (struct sockaddr*)&sockAddrM, &len) < 0,
|
||||||
"getsockname()", Close(), return false);
|
"getsockname()", Close(), return false);
|
||||||
socketPortM = ntohs(sockAddrM.sin_port);
|
socketPortM = ntohs(sockAddrM.sin_port);
|
||||||
|
isMulticastM = false;
|
||||||
}
|
}
|
||||||
debug1("%s (%d) socketPort=%d", __PRETTY_FUNCTION__, portP, socketPortM);
|
debug1("%s (%d) socketPort=%d", __PRETTY_FUNCTION__, portP, socketPortM);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool cSatipSocket::OpenMulticast(const int portP, const char *streamAddrP, const char *sourceAddrP)
|
||||||
|
{
|
||||||
|
debug1("%s (%d, %s, %s)", __PRETTY_FUNCTION__, portP, streamAddrP, sourceAddrP);
|
||||||
|
if (Open(portP)) {
|
||||||
|
CheckAddress(streamAddrP, &streamAddrM);
|
||||||
|
if (!isempty(sourceAddrP))
|
||||||
|
useSsmM = CheckAddress(sourceAddrP, &sourceAddrM);
|
||||||
|
return Join();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
void cSatipSocket::Close(void)
|
void cSatipSocket::Close(void)
|
||||||
{
|
{
|
||||||
debug1("%s sockerPort=%d", __PRETTY_FUNCTION__, socketPortM);
|
debug1("%s socketPort=%d", __PRETTY_FUNCTION__, socketPortM);
|
||||||
// Check if socket exists
|
// Check if socket exists
|
||||||
if (socketDescM >= 0) {
|
if (socketDescM >= 0) {
|
||||||
|
Leave();
|
||||||
close(socketDescM);
|
close(socketDescM);
|
||||||
socketDescM = -1;
|
socketDescM = -1;
|
||||||
socketPortM = 0;
|
socketPortM = 0;
|
||||||
memset(&sockAddrM, 0, sizeof(sockAddrM));
|
memset(&sockAddrM, 0, sizeof(sockAddrM));
|
||||||
|
streamAddrM = htonl(INADDR_ANY);
|
||||||
|
sourceAddrM = htonl(INADDR_ANY);
|
||||||
|
isMulticastM = false;
|
||||||
|
useSsmM = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -96,6 +162,96 @@ bool cSatipSocket::Flush(void)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool cSatipSocket::CheckAddress(const char *addrP, in_addr_t *inAddrP)
|
||||||
|
{
|
||||||
|
if (inAddrP) {
|
||||||
|
// First try only the IP address
|
||||||
|
*inAddrP = inet_addr(addrP);
|
||||||
|
if (*inAddrP == htonl(INADDR_NONE)) {
|
||||||
|
debug1("%s (%s, ) Cannot convert to address", __PRETTY_FUNCTION__, addrP);
|
||||||
|
// It may be a host name, get the name
|
||||||
|
struct hostent *host = gethostbyname(addrP);
|
||||||
|
if (!host) {
|
||||||
|
char tmp[64];
|
||||||
|
error("gethostbyname() failed: %s is not valid address: %s", addrP,
|
||||||
|
strerror_r(h_errno, tmp, sizeof(tmp)));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
*inAddrP = inet_addr(*host->h_addr_list);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool cSatipSocket::Join(void)
|
||||||
|
{
|
||||||
|
debug1("%s", __PRETTY_FUNCTION__);
|
||||||
|
// Check if socket exists
|
||||||
|
if (socketDescM >= 0 && !isMulticastM) {
|
||||||
|
// Join a new multicast group
|
||||||
|
if (useSsmM) {
|
||||||
|
// Source-specific multicast (SSM) is used
|
||||||
|
struct group_source_req gsr;
|
||||||
|
struct sockaddr_in *grp;
|
||||||
|
struct sockaddr_in *src;
|
||||||
|
gsr.gsr_interface = 0; // if_nametoindex("any") ?
|
||||||
|
grp = (struct sockaddr_in*)&gsr.gsr_group;
|
||||||
|
grp->sin_family = AF_INET;
|
||||||
|
grp->sin_addr.s_addr = streamAddrM;
|
||||||
|
grp->sin_port = 0;
|
||||||
|
src = (struct sockaddr_in*)&gsr.gsr_source;
|
||||||
|
src->sin_family = AF_INET;
|
||||||
|
src->sin_addr.s_addr = sourceAddrM;
|
||||||
|
src->sin_port = 0;
|
||||||
|
ERROR_IF_RET(setsockopt(socketDescM, SOL_IP, MCAST_JOIN_SOURCE_GROUP, &gsr, sizeof(gsr)) < 0, "setsockopt(MCAST_JOIN_SOURCE_GROUP)", return false);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
struct ip_mreq mreq;
|
||||||
|
mreq.imr_multiaddr.s_addr = streamAddrM;
|
||||||
|
mreq.imr_interface.s_addr = htonl(INADDR_ANY);
|
||||||
|
ERROR_IF_RET(setsockopt(socketDescM, SOL_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0, "setsockopt(IP_ADD_MEMBERSHIP)", return false);
|
||||||
|
}
|
||||||
|
// Update multicasting flag
|
||||||
|
isMulticastM = true;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool cSatipSocket::Leave(void)
|
||||||
|
{
|
||||||
|
debug1("%s", __PRETTY_FUNCTION__);
|
||||||
|
// Check if socket exists
|
||||||
|
if (socketDescM >= 0 && isMulticastM) {
|
||||||
|
// Leave the existing multicast group
|
||||||
|
if (useSsmM) {
|
||||||
|
// Source-specific multicast (SSM) is used
|
||||||
|
struct group_source_req gsr;
|
||||||
|
struct sockaddr_in *grp;
|
||||||
|
struct sockaddr_in *src;
|
||||||
|
gsr.gsr_interface = 0; // if_nametoindex("any") ?
|
||||||
|
grp = (struct sockaddr_in*)&gsr.gsr_group;
|
||||||
|
grp->sin_family = AF_INET;
|
||||||
|
grp->sin_addr.s_addr = streamAddrM;
|
||||||
|
grp->sin_port = 0;
|
||||||
|
src = (struct sockaddr_in*)&gsr.gsr_source;
|
||||||
|
src->sin_family = AF_INET;
|
||||||
|
src->sin_addr.s_addr = sourceAddrM;
|
||||||
|
src->sin_port = 0;
|
||||||
|
ERROR_IF_RET(setsockopt(socketDescM, SOL_IP, MCAST_LEAVE_SOURCE_GROUP, &gsr, sizeof(gsr)) < 0, "setsockopt(MCAST_LEAVE_SOURCE_GROUP)", return false);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
struct ip_mreq mreq;
|
||||||
|
mreq.imr_multiaddr.s_addr = streamAddrM;
|
||||||
|
mreq.imr_interface.s_addr = htonl(INADDR_ANY);
|
||||||
|
ERROR_IF_RET(setsockopt(socketDescM, SOL_IP, IP_DROP_MEMBERSHIP, &mreq, sizeof(mreq)) < 0, "setsockopt(IP_DROP_MEMBERSHIP)", return false);
|
||||||
|
}
|
||||||
|
// Update multicasting flag
|
||||||
|
isMulticastM = false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
int cSatipSocket::Read(unsigned char *bufferAddrP, unsigned int bufferLenP)
|
int cSatipSocket::Read(unsigned char *bufferAddrP, unsigned int bufferLenP)
|
||||||
{
|
{
|
||||||
debug16("%s (, %d)", __PRETTY_FUNCTION__, bufferLenP);
|
debug16("%s (, %d)", __PRETTY_FUNCTION__, bufferLenP);
|
||||||
@@ -126,8 +282,22 @@ int cSatipSocket::Read(unsigned char *bufferAddrP, unsigned int bufferLenP)
|
|||||||
|
|
||||||
if (socketDescM && bufferAddrP && (bufferLenP > 0))
|
if (socketDescM && bufferAddrP && (bufferLenP > 0))
|
||||||
len = (int)recvmsg(socketDescM, &msgh, MSG_DONTWAIT);
|
len = (int)recvmsg(socketDescM, &msgh, MSG_DONTWAIT);
|
||||||
if (len > 0)
|
if (len > 0) {
|
||||||
|
#ifndef __FreeBSD__
|
||||||
|
if (isMulticastM) {
|
||||||
|
// Process auxiliary received data and validate source address
|
||||||
|
for (struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msgh); cmsg != NULL; cmsg = CMSG_NXTHDR(&msgh, cmsg)) {
|
||||||
|
if ((cmsg->cmsg_level == SOL_IP) && (cmsg->cmsg_type == IP_PKTINFO)) {
|
||||||
|
struct in_pktinfo *i = (struct in_pktinfo *)CMSG_DATA(cmsg);
|
||||||
|
if ((i->ipi_addr.s_addr == streamAddrM) || (htonl(INADDR_ANY) == streamAddrM))
|
||||||
return len;
|
return len;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif // __FreeBSD__
|
||||||
|
return len;
|
||||||
|
}
|
||||||
} while (len > 0);
|
} while (len > 0);
|
||||||
ERROR_IF_RET(len < 0 && errno != EAGAIN && errno != EWOULDBLOCK, "recvmsg()", return -1);
|
ERROR_IF_RET(len < 0 && errno != EAGAIN && errno != EWOULDBLOCK, "recvmsg()", return -1);
|
||||||
return 0;
|
return 0;
|
||||||
@@ -146,7 +316,7 @@ int cSatipSocket::ReadMulti(unsigned char *bufferAddrP, unsigned int *elementRec
|
|||||||
error("%s Invalid parameter(s)", __PRETTY_FUNCTION__);
|
error("%s Invalid parameter(s)", __PRETTY_FUNCTION__);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
#if defined(__GLIBC_PREREQ) && __GLIBC_PREREQ(2,12)
|
#ifndef __SATIP_DISABLE_RECVMMSG__
|
||||||
// Initialize iov and msgh structures
|
// Initialize iov and msgh structures
|
||||||
struct mmsghdr mmsgh[elementCountP];
|
struct mmsghdr mmsgh[elementCountP];
|
||||||
struct iovec iov[elementCountP];
|
struct iovec iov[elementCountP];
|
||||||
|
14
socket.h
14
socket.h
@@ -15,14 +15,26 @@ private:
|
|||||||
int socketPortM;
|
int socketPortM;
|
||||||
int socketDescM;
|
int socketDescM;
|
||||||
struct sockaddr_in sockAddrM;
|
struct sockaddr_in sockAddrM;
|
||||||
|
bool isMulticastM;
|
||||||
|
bool useSsmM;
|
||||||
|
in_addr_t streamAddrM;
|
||||||
|
in_addr_t sourceAddrM;
|
||||||
|
size_t rcvBufSizeM;
|
||||||
|
|
||||||
|
bool CheckAddress(const char *addrP, in_addr_t *inAddrP);
|
||||||
|
bool Join(void);
|
||||||
|
bool Leave(void);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
cSatipSocket();
|
cSatipSocket();
|
||||||
|
explicit cSatipSocket(size_t rcvBufSizeP);
|
||||||
virtual ~cSatipSocket();
|
virtual ~cSatipSocket();
|
||||||
bool Open(const int portP = 0);
|
bool Open(const int portP = 0, const bool reuseP = false);
|
||||||
|
bool OpenMulticast(const int portP, const char *streamAddrP, const char *sourceAddrP);
|
||||||
virtual void Close(void);
|
virtual void Close(void);
|
||||||
int Fd(void) { return socketDescM; }
|
int Fd(void) { return socketDescM; }
|
||||||
int Port(void) { return socketPortM; }
|
int Port(void) { return socketPortM; }
|
||||||
|
bool IsMulticast(void) { return isMulticastM; }
|
||||||
bool IsOpen(void) { return (socketDescM >= 0); }
|
bool IsOpen(void) { return (socketDescM >= 0); }
|
||||||
bool Flush(void);
|
bool Flush(void);
|
||||||
int Read(unsigned char *bufferAddrP, unsigned int bufferLenP);
|
int Read(unsigned char *bufferAddrP, unsigned int bufferLenP);
|
||||||
|
108
tuner.c
108
tuner.c
@@ -25,6 +25,8 @@ cSatipTuner::cSatipTuner(cSatipDeviceIf &deviceP, unsigned int packetLenP)
|
|||||||
rtcpM(*this),
|
rtcpM(*this),
|
||||||
streamAddrM(""),
|
streamAddrM(""),
|
||||||
streamParamM(""),
|
streamParamM(""),
|
||||||
|
tnrParamM(""),
|
||||||
|
streamPortM(SATIP_DEFAULT_RTSP_PORT),
|
||||||
currentServerM(NULL, deviceP.GetId(), 0),
|
currentServerM(NULL, deviceP.GetId(), 0),
|
||||||
nextServerM(NULL, deviceP.GetId(), 0),
|
nextServerM(NULL, deviceP.GetId(), 0),
|
||||||
mutexM(),
|
mutexM(),
|
||||||
@@ -38,6 +40,7 @@ cSatipTuner::cSatipTuner(cSatipDeviceIf &deviceP, unsigned int packetLenP)
|
|||||||
externalStateM(),
|
externalStateM(),
|
||||||
timeoutM(eMinKeepAliveIntervalMs),
|
timeoutM(eMinKeepAliveIntervalMs),
|
||||||
hasLockM(false),
|
hasLockM(false),
|
||||||
|
signalStrengthDBmM(0.0),
|
||||||
signalStrengthM(-1),
|
signalStrengthM(-1),
|
||||||
signalQualityM(-1),
|
signalQualityM(-1),
|
||||||
frontendIdM(-1),
|
frontendIdM(-1),
|
||||||
@@ -50,12 +53,16 @@ cSatipTuner::cSatipTuner(cSatipDeviceIf &deviceP, unsigned int packetLenP)
|
|||||||
debug1("%s (, %d) [device %d]", __PRETTY_FUNCTION__, packetLenP, deviceIdM);
|
debug1("%s (, %d) [device %d]", __PRETTY_FUNCTION__, packetLenP, deviceIdM);
|
||||||
|
|
||||||
// Open sockets
|
// Open sockets
|
||||||
int i = 100;
|
int i = SatipConfig.GetPortRangeStart() ? SatipConfig.GetPortRangeStop() - SatipConfig.GetPortRangeStart() - 1 : 100;
|
||||||
|
int port = SatipConfig.GetPortRangeStart();
|
||||||
while (i-- > 0) {
|
while (i-- > 0) {
|
||||||
if (rtpM.Open(0) && rtcpM.Open(rtpM.Port() + 1))
|
// RTP must use an even port number
|
||||||
|
if (rtpM.Open(port) && (rtpM.Port() % 2 == 0) && rtcpM.Open(rtpM.Port() + 1))
|
||||||
break;
|
break;
|
||||||
rtpM.Close();
|
rtpM.Close();
|
||||||
rtcpM.Close();
|
rtcpM.Close();
|
||||||
|
if (SatipConfig.GetPortRangeStart())
|
||||||
|
port += 2;
|
||||||
}
|
}
|
||||||
if ((rtpM.Port() <= 0) || (rtcpM.Port() <= 0)) {
|
if ((rtpM.Port() <= 0) || (rtcpM.Port() <= 0)) {
|
||||||
error("Cannot open required RTP/RTCP ports [device %d]", deviceIdM);
|
error("Cannot open required RTP/RTCP ports [device %d]", deviceIdM);
|
||||||
@@ -120,6 +127,7 @@ void cSatipTuner::Action(void)
|
|||||||
break;
|
break;
|
||||||
case tsTuned:
|
case tsTuned:
|
||||||
debug4("%s: tsTuned [device %d]", __PRETTY_FUNCTION__, deviceIdM);
|
debug4("%s: tsTuned [device %d]", __PRETTY_FUNCTION__, deviceIdM);
|
||||||
|
deviceM->SetChannelTuned();
|
||||||
reConnectM.Set(eConnectTimeoutMs);
|
reConnectM.Set(eConnectTimeoutMs);
|
||||||
idleCheck.Set(eIdleCheckTimeoutMs);
|
idleCheck.Set(eIdleCheckTimeoutMs);
|
||||||
lastIdleStatus = false;
|
lastIdleStatus = false;
|
||||||
@@ -128,6 +136,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;
|
||||||
}
|
}
|
||||||
@@ -205,7 +214,8 @@ bool cSatipTuner::Connect(void)
|
|||||||
debug1("%s [device %d]", __PRETTY_FUNCTION__, deviceIdM);
|
debug1("%s [device %d]", __PRETTY_FUNCTION__, deviceIdM);
|
||||||
|
|
||||||
if (!isempty(*streamAddrM)) {
|
if (!isempty(*streamAddrM)) {
|
||||||
cString connectionUri = cString::sprintf("rtsp://%s/", *streamAddrM);
|
cString connectionUri = GetBaseUrl(*streamAddrM, streamPortM);
|
||||||
|
tnrParamM = "";
|
||||||
// Just retune
|
// Just retune
|
||||||
if (streamIdM >= 0) {
|
if (streamIdM >= 0) {
|
||||||
cString uri = cString::sprintf("%sstream=%d?%s", *connectionUri, streamIdM, *streamParamM);
|
cString uri = cString::sprintf("%sstream=%d?%s", *connectionUri, streamIdM, *streamParamM);
|
||||||
@@ -215,12 +225,15 @@ bool cSatipTuner::Connect(void)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (rtspM.Options(*connectionUri)) {
|
else if (rtspM.SetInterface(nextServerM.IsValid() ? *nextServerM.GetSrcAddress() : NULL) && rtspM.Options(*connectionUri)) {
|
||||||
cString uri = cString::sprintf("%s?%s", *connectionUri, *streamParamM);
|
cString uri = cString::sprintf("%s?%s", *connectionUri, *streamParamM);
|
||||||
|
bool useTcp = SatipConfig.IsTransportModeRtpOverTcp() && nextServerM.IsValid() && nextServerM.IsQuirk(cSatipServer::eSatipQuirkRtpOverTcp);
|
||||||
// Flush any old content
|
// Flush any old content
|
||||||
//rtpM.Flush();
|
//rtpM.Flush();
|
||||||
//rtcpM.Flush();
|
//rtcpM.Flush();
|
||||||
if (rtspM.Setup(*uri, rtpM.Port(), rtcpM.Port())) {
|
if (useTcp)
|
||||||
|
debug1("%s Requesting TCP [device %d]", __PRETTY_FUNCTION__, deviceIdM);
|
||||||
|
if (rtspM.Setup(*uri, rtpM.Port(), rtcpM.Port(), useTcp)) {
|
||||||
keepAliveM.Set(timeoutM);
|
keepAliveM.Set(timeoutM);
|
||||||
if (nextServerM.IsValid()) {
|
if (nextServerM.IsValid()) {
|
||||||
currentServerM = nextServerM;
|
currentServerM = nextServerM;
|
||||||
@@ -244,7 +257,7 @@ bool cSatipTuner::Disconnect(void)
|
|||||||
debug1("%s [device %d]", __PRETTY_FUNCTION__, deviceIdM);
|
debug1("%s [device %d]", __PRETTY_FUNCTION__, deviceIdM);
|
||||||
|
|
||||||
if (!isempty(*streamAddrM) && (streamIdM >= 0)) {
|
if (!isempty(*streamAddrM) && (streamIdM >= 0)) {
|
||||||
cString uri = cString::sprintf("rtsp://%s/stream=%d", *streamAddrM, streamIdM);
|
cString uri = cString::sprintf("%sstream=%d", *GetBaseUrl(*streamAddrM, streamPortM), 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();
|
||||||
@@ -253,6 +266,7 @@ 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;
|
||||||
@@ -289,6 +303,11 @@ void cSatipTuner::ProcessVideoData(u_char *bufferP, int lengthP)
|
|||||||
reConnectM.Set(eConnectTimeoutMs);
|
reConnectM.Set(eConnectTimeoutMs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void cSatipTuner::ProcessRtpData(u_char *bufferP, int lengthP)
|
||||||
|
{
|
||||||
|
rtpM.Process(bufferP, lengthP);
|
||||||
|
}
|
||||||
|
|
||||||
void cSatipTuner::ProcessApplicationData(u_char *bufferP, int lengthP)
|
void cSatipTuner::ProcessApplicationData(u_char *bufferP, int lengthP)
|
||||||
{
|
{
|
||||||
debug16("%s (%d) [device %d]", __PRETTY_FUNCTION__, lengthP, deviceIdM);
|
debug16("%s (%d) [device %d]", __PRETTY_FUNCTION__, lengthP, deviceIdM);
|
||||||
@@ -317,8 +336,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:
|
||||||
@@ -342,6 +362,11 @@ void cSatipTuner::ProcessApplicationData(u_char *bufferP, int lengthP)
|
|||||||
reConnectM.Set(eConnectTimeoutMs);
|
reConnectM.Set(eConnectTimeoutMs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void cSatipTuner::ProcessRtcpData(u_char *bufferP, int lengthP)
|
||||||
|
{
|
||||||
|
rtcpM.Process(bufferP, lengthP);
|
||||||
|
}
|
||||||
|
|
||||||
void cSatipTuner::SetStreamId(int streamIdP)
|
void cSatipTuner::SetStreamId(int streamIdP)
|
||||||
{
|
{
|
||||||
cMutexLock MutexLock(&mutexM);
|
cMutexLock MutexLock(&mutexM);
|
||||||
@@ -359,6 +384,47 @@ void cSatipTuner::SetSessionTimeout(const char *sessionP, int timeoutP)
|
|||||||
timeoutM = (timeoutP > eMinKeepAliveIntervalMs) ? timeoutP : eMinKeepAliveIntervalMs;
|
timeoutM = (timeoutP > eMinKeepAliveIntervalMs) ? timeoutP : eMinKeepAliveIntervalMs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void cSatipTuner::SetupTransport(int rtpPortP, int rtcpPortP, const char *streamAddrP, const char *sourceAddrP)
|
||||||
|
{
|
||||||
|
cMutexLock MutexLock(&mutexM);
|
||||||
|
debug1("%s (%d, %d, %s, %s) [device %d]", __PRETTY_FUNCTION__, rtpPortP, rtcpPortP, streamAddrP, sourceAddrP, deviceIdM);
|
||||||
|
bool multicast = !isempty(streamAddrP);
|
||||||
|
// Adapt RTP to any transport media change
|
||||||
|
if (multicast != rtpM.IsMulticast() || rtpPortP != rtpM.Port()) {
|
||||||
|
cSatipPoller::GetInstance()->Unregister(rtpM);
|
||||||
|
if (rtpPortP >= 0) {
|
||||||
|
rtpM.Close();
|
||||||
|
if (multicast)
|
||||||
|
rtpM.OpenMulticast(rtpPortP, streamAddrP, sourceAddrP);
|
||||||
|
else
|
||||||
|
rtpM.Open(rtpPortP);
|
||||||
|
cSatipPoller::GetInstance()->Register(rtpM);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Adapt RTCP to any transport media change
|
||||||
|
if (multicast != rtcpM.IsMulticast() || rtcpPortP != rtcpM.Port()) {
|
||||||
|
cSatipPoller::GetInstance()->Unregister(rtcpM);
|
||||||
|
if (rtcpPortP >= 0) {
|
||||||
|
rtcpM.Close();
|
||||||
|
if (multicast)
|
||||||
|
rtcpM.OpenMulticast(rtcpPortP, streamAddrP, sourceAddrP);
|
||||||
|
else
|
||||||
|
rtcpM.Open(rtcpPortP);
|
||||||
|
cSatipPoller::GetInstance()->Register(rtcpM);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cString cSatipTuner::GetBaseUrl(const char *addressP, const int portP)
|
||||||
|
{
|
||||||
|
debug16("%s (%s, %d) [device %d]", __PRETTY_FUNCTION__, addressP, portP, deviceIdM);
|
||||||
|
|
||||||
|
if (portP != SATIP_DEFAULT_RTSP_PORT)
|
||||||
|
return cString::sprintf("rtsp://%s:%d/", addressP, portP);
|
||||||
|
|
||||||
|
return cString::sprintf("rtsp://%s/", addressP);
|
||||||
|
}
|
||||||
|
|
||||||
int cSatipTuner::GetId(void)
|
int cSatipTuner::GetId(void)
|
||||||
{
|
{
|
||||||
debug16("%s [device %d]", __PRETTY_FUNCTION__, deviceIdM);
|
debug16("%s [device %d]", __PRETTY_FUNCTION__, deviceIdM);
|
||||||
@@ -375,6 +441,10 @@ bool cSatipTuner::SetSource(cSatipServer *serverP, const int transponderP, const
|
|||||||
// Update stream address and parameter
|
// Update stream address and parameter
|
||||||
streamAddrM = rtspM.RtspUnescapeString(*nextServerM.GetAddress());
|
streamAddrM = rtspM.RtspUnescapeString(*nextServerM.GetAddress());
|
||||||
streamParamM = rtspM.RtspUnescapeString(parameterP);
|
streamParamM = rtspM.RtspUnescapeString(parameterP);
|
||||||
|
streamPortM = nextServerM.GetPort();
|
||||||
|
// Modify parameter if required
|
||||||
|
if (nextServerM.IsQuirk(cSatipServer::eSatipQuirkForcePilot) && strstr(parameterP, "msys=dvbs2") && !strstr(parameterP, "plts="))
|
||||||
|
streamParamM = rtspM.RtspUnescapeString(*cString::sprintf("%s&plts=on", parameterP));
|
||||||
// Reconnect
|
// Reconnect
|
||||||
RequestState(tsSet, smExternal);
|
RequestState(tsSet, smExternal);
|
||||||
}
|
}
|
||||||
@@ -413,7 +483,7 @@ bool cSatipTuner::UpdatePids(bool forceP)
|
|||||||
cMutexLock MutexLock(&mutexM);
|
cMutexLock MutexLock(&mutexM);
|
||||||
if (((forceP && pidsM.Size()) || (pidUpdateCacheM.TimedOut() && (addPidsM.Size() || delPidsM.Size()))) &&
|
if (((forceP && pidsM.Size()) || (pidUpdateCacheM.TimedOut() && (addPidsM.Size() || delPidsM.Size()))) &&
|
||||||
!isempty(*streamAddrM) && (streamIdM > 0)) {
|
!isempty(*streamAddrM) && (streamIdM > 0)) {
|
||||||
cString uri = cString::sprintf("rtsp://%s/stream=%d", *streamAddrM, 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);
|
||||||
if (forceP || usedummy) {
|
if (forceP || usedummy) {
|
||||||
@@ -429,6 +499,7 @@ bool cSatipTuner::UpdatePids(bool forceP)
|
|||||||
uri = cString::sprintf("%s%sdelpids=%s", *uri, addPidsM.Size() ? "&" : "?", *delPidsM.ListPids());
|
uri = cString::sprintf("%s%sdelpids=%s", *uri, addPidsM.Size() ? "&" : "?", *delPidsM.ListPids());
|
||||||
}
|
}
|
||||||
if (useci) {
|
if (useci) {
|
||||||
|
if (currentServerM.IsQuirk(cSatipServer::eSatipQuirkCiXpmt)) {
|
||||||
// CI extension parameters:
|
// CI extension parameters:
|
||||||
// - x_pmt : specifies the PMT of the service you want the CI to decode
|
// - x_pmt : specifies the PMT of the service you want the CI to decode
|
||||||
// - x_ci : specfies which CI slot (1..n) to use
|
// - x_ci : specfies which CI slot (1..n) to use
|
||||||
@@ -444,6 +515,15 @@ bool cSatipTuner::UpdatePids(bool forceP)
|
|||||||
}
|
}
|
||||||
pmtPidM = pid;
|
pmtPidM = pid;
|
||||||
}
|
}
|
||||||
|
else if (currentServerM.IsQuirk(cSatipServer::eSatipQuirkCiTnr)) {
|
||||||
|
// CI extension parameters:
|
||||||
|
// - tnr : specifies a channel config entry
|
||||||
|
cString param = deviceM->GetTnrParameterString();
|
||||||
|
if (!isempty(*param) && strcmp(*tnrParamM, *param) != 0)
|
||||||
|
uri = cString::sprintf("%s&tnr=%s", *uri, *param);
|
||||||
|
tnrParamM = param;
|
||||||
|
}
|
||||||
|
}
|
||||||
pidUpdateCacheM.Set(ePidUpdateIntervalMs);
|
pidUpdateCacheM.Set(ePidUpdateIntervalMs);
|
||||||
if (!rtspM.Play(*uri))
|
if (!rtspM.Play(*uri))
|
||||||
return false;
|
return false;
|
||||||
@@ -463,7 +543,7 @@ bool cSatipTuner::KeepAlive(bool forceP)
|
|||||||
forceP = true;
|
forceP = true;
|
||||||
}
|
}
|
||||||
if (forceP && !isempty(*streamAddrM)) {
|
if (forceP && !isempty(*streamAddrM)) {
|
||||||
cString uri = cString::sprintf("rtsp://%s/", *streamAddrM);
|
cString uri = GetBaseUrl(*streamAddrM, streamPortM);
|
||||||
if (!rtspM.Options(*uri))
|
if (!rtspM.Options(*uri))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -480,7 +560,7 @@ bool cSatipTuner::ReadReceptionStatus(bool forceP)
|
|||||||
forceP = true;
|
forceP = true;
|
||||||
}
|
}
|
||||||
if (forceP && !isempty(*streamAddrM) && (streamIdM > 0)) {
|
if (forceP && !isempty(*streamAddrM) && (streamIdM > 0)) {
|
||||||
cString uri = cString::sprintf("rtsp://%s/stream=%d", *streamAddrM, streamIdM);
|
cString uri = cString::sprintf("%sstream=%d", *GetBaseUrl(*streamAddrM, streamPortM), streamIdM);
|
||||||
if (rtspM.Describe(*uri))
|
if (rtspM.Describe(*uri))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -594,6 +674,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);
|
||||||
@@ -615,5 +701,5 @@ cString cSatipTuner::GetSignalStatus(void)
|
|||||||
cString cSatipTuner::GetInformation(void)
|
cString cSatipTuner::GetInformation(void)
|
||||||
{
|
{
|
||||||
debug16("%s [device %d]", __PRETTY_FUNCTION__, deviceIdM);
|
debug16("%s [device %d]", __PRETTY_FUNCTION__, deviceIdM);
|
||||||
return (currentStateM >= tsTuned) ? cString::sprintf("rtsp://%s/?%s [stream=%d]", *streamAddrM, *streamParamM, streamIdM) : "connection failed";
|
return (currentStateM >= tsTuned) ? cString::sprintf("%s?%s (%s) [stream=%d]", *GetBaseUrl(*streamAddrM, streamPortM), *streamParamM, *rtspM.GetActiveMode(), streamIdM) : "connection failed";
|
||||||
}
|
}
|
||||||
|
15
tuner.h
15
tuner.h
@@ -69,6 +69,8 @@ public:
|
|||||||
void Set(cSatipServer *serverP, const int transponderP) { serverM = serverP; transponderM = transponderP; }
|
void Set(cSatipServer *serverP, const int transponderP) { serverM = serverP; transponderM = transponderP; }
|
||||||
void Reset(void) { serverM = NULL; transponderM = 0; }
|
void Reset(void) { serverM = NULL; transponderM = 0; }
|
||||||
cString GetAddress(void) { return serverM ? cSatipDiscover::GetInstance()->GetServerAddress(serverM) : ""; }
|
cString GetAddress(void) { return serverM ? cSatipDiscover::GetInstance()->GetServerAddress(serverM) : ""; }
|
||||||
|
cString GetSrcAddress(void) { return serverM ? cSatipDiscover::GetInstance()->GetSourceAddress(serverM) : ""; }
|
||||||
|
int GetPort(void) { return serverM ? cSatipDiscover::GetInstance()->GetServerPort(serverM) : SATIP_DEFAULT_RTSP_PORT; }
|
||||||
cString GetInfo(void) { return cString::sprintf("server=%s deviceid=%d transponder=%d", serverM ? "assigned" : "null", deviceIdM, transponderM); }
|
cString GetInfo(void) { return cString::sprintf("server=%s deviceid=%d transponder=%d", serverM ? "assigned" : "null", deviceIdM, transponderM); }
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -77,8 +79,9 @@ class cSatipTuner : public cThread, public cSatipTunerStatistics, public cSatipT
|
|||||||
private:
|
private:
|
||||||
enum {
|
enum {
|
||||||
eDummyPid = 100,
|
eDummyPid = 100,
|
||||||
eDefaultSignalStrength = 15,
|
eDefaultSignalStrengthDBm = -25,
|
||||||
eDefaultSignalQuality = 224,
|
eDefaultSignalStrength = 224,
|
||||||
|
eDefaultSignalQuality = 15,
|
||||||
eSleepTimeoutMs = 250, // in milliseconds
|
eSleepTimeoutMs = 250, // in milliseconds
|
||||||
eStatusUpdateTimeoutMs = 1000, // in milliseconds
|
eStatusUpdateTimeoutMs = 1000, // in milliseconds
|
||||||
ePidUpdateIntervalMs = 250, // in milliseconds
|
ePidUpdateIntervalMs = 250, // in milliseconds
|
||||||
@@ -98,6 +101,8 @@ private:
|
|||||||
cSatipRtcp rtcpM;
|
cSatipRtcp rtcpM;
|
||||||
cString streamAddrM;
|
cString streamAddrM;
|
||||||
cString streamParamM;
|
cString streamParamM;
|
||||||
|
cString tnrParamM;
|
||||||
|
int streamPortM;
|
||||||
cSatipTunerServer currentServerM;
|
cSatipTunerServer currentServerM;
|
||||||
cSatipTunerServer nextServerM;
|
cSatipTunerServer nextServerM;
|
||||||
cMutex mutexM;
|
cMutex mutexM;
|
||||||
@@ -111,6 +116,7 @@ private:
|
|||||||
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;
|
||||||
@@ -130,6 +136,7 @@ private:
|
|||||||
bool RequestState(eTunerState stateP, eStateMode modeP);
|
bool RequestState(eTunerState stateP, eStateMode modeP);
|
||||||
const char *StateModeString(eStateMode modeP);
|
const char *StateModeString(eStateMode modeP);
|
||||||
const char *TunerStateString(eTunerState stateP);
|
const char *TunerStateString(eTunerState stateP);
|
||||||
|
cString GetBaseUrl(const char *addressP, const int portP);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void Action(void);
|
virtual void Action(void);
|
||||||
@@ -144,6 +151,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);
|
||||||
@@ -153,8 +161,11 @@ public:
|
|||||||
public:
|
public:
|
||||||
virtual void ProcessVideoData(u_char *bufferP, int lengthP);
|
virtual void ProcessVideoData(u_char *bufferP, int lengthP);
|
||||||
virtual void ProcessApplicationData(u_char *bufferP, int lengthP);
|
virtual void ProcessApplicationData(u_char *bufferP, int lengthP);
|
||||||
|
virtual void ProcessRtpData(u_char *bufferP, int lengthP);
|
||||||
|
virtual void ProcessRtcpData(u_char *bufferP, int lengthP);
|
||||||
virtual void SetStreamId(int streamIdP);
|
virtual void SetStreamId(int streamIdP);
|
||||||
virtual void SetSessionTimeout(const char *sessionP, int timeoutP);
|
virtual void SetSessionTimeout(const char *sessionP, int timeoutP);
|
||||||
|
virtual void SetupTransport(int rtpPortP, int rtcpPortP, const char *streamAddrP, const char *sourceAddrP);
|
||||||
virtual int GetId(void);
|
virtual int GetId(void);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -14,8 +14,11 @@ public:
|
|||||||
virtual ~cSatipTunerIf() {}
|
virtual ~cSatipTunerIf() {}
|
||||||
virtual void ProcessVideoData(u_char *bufferP, int lengthP) = 0;
|
virtual void ProcessVideoData(u_char *bufferP, int lengthP) = 0;
|
||||||
virtual void ProcessApplicationData(u_char *bufferP, int lengthP) = 0;
|
virtual void ProcessApplicationData(u_char *bufferP, int lengthP) = 0;
|
||||||
|
virtual void ProcessRtpData(u_char *bufferP, int lengthP) = 0;
|
||||||
|
virtual void ProcessRtcpData(u_char *bufferP, int lengthP) = 0;
|
||||||
virtual void SetStreamId(int streamIdP) = 0;
|
virtual void SetStreamId(int streamIdP) = 0;
|
||||||
virtual void SetSessionTimeout(const char *sessionP, int timeoutP) = 0;
|
virtual void SetSessionTimeout(const char *sessionP, int timeoutP) = 0;
|
||||||
|
virtual void SetupTransport(int rtpPortP, int rtcpPortP, const char *streamAddrP, const char *sourceAddrP) = 0;
|
||||||
virtual int GetId(void) = 0;
|
virtual int GetId(void) = 0;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
Reference in New Issue
Block a user