mirror of
https://github.com/rofafor/vdr-plugin-satip.git
synced 2023-10-10 11:37:42 +00:00
Compare commits
119 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
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 | ||
|
|
37a0572a64 | ||
|
|
613c0aed7c | ||
|
|
c3ad29eb27 | ||
|
|
e90b8651e6 | ||
|
|
0f370aa36a | ||
|
|
49e2dd1fc1 | ||
|
|
ba0b808ec4 | ||
|
|
4e2535a7e2 | ||
|
|
6384b8694e | ||
|
|
6c4c8a10b7 | ||
|
|
8b43cdc634 | ||
|
|
fe010ab72c | ||
|
|
7bdc152f76 | ||
|
|
bd6774ba28 | ||
|
|
fbf7977853 | ||
|
|
19a6a4a5ee | ||
|
|
7b683dba8d | ||
|
|
942d3a936e | ||
|
|
748ea15d1d | ||
|
|
1d75da403a | ||
|
|
4d8263e8fd | ||
|
|
7019b719a5 | ||
|
|
39249ca2d5 | ||
|
|
68e0d1474e | ||
|
|
ad5c221e44 | ||
|
|
826e53e8ea | ||
|
|
f4dd02a9aa | ||
|
|
8184a785b7 | ||
|
|
1b4094696a | ||
|
|
4139e87f4a | ||
|
|
7196c9403b | ||
|
|
e1c896c1a6 | ||
|
|
6b63ad145f | ||
|
|
84dfc6701e | ||
|
|
653d9d659b | ||
|
|
26cd34f965 | ||
|
|
df258d127f | ||
|
|
3e4b1c0383 | ||
|
|
73ed299ed9 | ||
|
|
37e151b3e3 | ||
|
|
b1aad3fb80 | ||
|
|
a87dfc43f7 | ||
|
|
26be862d89 | ||
|
|
ab2a47e3e7 | ||
|
|
3d1efe7a80 | ||
|
|
c9898bfbfd | ||
|
|
46bfc805e6 | ||
|
|
30925337cb | ||
|
|
63e47ad24a | ||
|
|
14123e160f | ||
|
|
278d0478cf | ||
|
|
9989c36eee | ||
|
|
d2064f0c04 | ||
|
|
714d3ed902 | ||
|
|
b466d6836e | ||
|
|
184ddf2a53 | ||
|
|
65a2158051 | ||
|
|
e833ca6fdd | ||
|
|
c9abfddf11 | ||
|
|
fb7a7fe3a2 | ||
|
|
3b9269e9de | ||
|
|
09e6c272cd | ||
|
|
266aadb999 | ||
|
|
aed5a7820a | ||
|
|
bcb11b6257 | ||
|
|
21261f8042 | ||
|
|
2f11ad7a98 | ||
|
|
83a0233780 | ||
|
|
6f3715eb8b | ||
|
|
92991cd144 | ||
|
|
304addbc00 | ||
|
|
26ff10ce1e | ||
|
|
e654b3bbd2 | ||
|
|
acea8748a4 | ||
|
|
755f1049bb | ||
|
|
2f6315280f | ||
|
|
695dd53bfc | ||
|
|
5fef77518e | ||
|
|
791767f02b | ||
|
|
0d52649dbd | ||
|
|
0c03c1b8d4 | ||
|
|
db59aa9c29 | ||
|
|
0fd559ce79 | ||
|
|
e10ce57210 | ||
|
|
c7f4b265d5 | ||
|
|
35c0f25c38 |
86
HISTORY
86
HISTORY
@@ -88,3 +88,89 @@ VDR Plugin 'satip' Revision History
|
|||||||
- Added plenty of performance tweaks (Thanks to
|
- Added plenty of performance tweaks (Thanks to
|
||||||
Stefan Schallenberg).
|
Stefan Schallenberg).
|
||||||
- Fixed EIT scan (Thanks to Stefan Schallenberg).
|
- Fixed EIT scan (Thanks to Stefan Schallenberg).
|
||||||
|
|
||||||
|
2015-01-10: Version 1.0.1
|
||||||
|
|
||||||
|
- Updated the command-line help and README.
|
||||||
|
- Fixed the server teardown.
|
||||||
|
- Removed the unnecessary config directory definition.
|
||||||
|
- Added a fallback for older glibc libraries.
|
||||||
|
- Improved pid selection performance.
|
||||||
|
- Added support for Digital Devices CI extension.
|
||||||
|
|
||||||
|
2015-01-18: Version 1.0.2
|
||||||
|
|
||||||
|
- Added configurable CI slots.
|
||||||
|
- Fixed parsing of the setup values.
|
||||||
|
- Added an option to disable sources via sources.conf.
|
||||||
|
- Added a command-line option to disable all the
|
||||||
|
SAT>IP server quirks.
|
||||||
|
- Updated Spanish and Catalan translations (Thanks to
|
||||||
|
Gabriel Bonich).
|
||||||
|
- Updated German translations (Thanks to Frank Neumann).
|
||||||
|
|
||||||
|
|
||||||
|
===================================
|
||||||
|
VDR Plugin 'satip' Revision History
|
||||||
|
===================================
|
||||||
|
|
||||||
|
2015-02-19: Version 2.2.0
|
||||||
|
|
||||||
|
- Updated for vdr-2.2.0.
|
||||||
|
- Fixed memory deallocation errors.
|
||||||
|
- Cleaned up all scan-build warnings.
|
||||||
|
- Refactored the frontend handling.
|
||||||
|
|
||||||
|
2015-04-04: Version 2.2.1
|
||||||
|
|
||||||
|
- Improved RTSP error checking.
|
||||||
|
- Got rid of SATIP_DEBUG.
|
||||||
|
- Robustify the server discovery.
|
||||||
|
- Fixed a memory leak in TinyXML implementation
|
||||||
|
(Thanks to Oliver Endriss).
|
||||||
|
- Updated against SAT>IP protocol specification
|
||||||
|
version 1.2.2.
|
||||||
|
|
||||||
|
2015-04-26: Version 2.2.2
|
||||||
|
|
||||||
|
- Added a more flexible OPER command in the SVDRP
|
||||||
|
interface.
|
||||||
|
- Added new ATTA and DETA SVDRP commands.
|
||||||
|
- Set the default device count to two.
|
||||||
|
|
||||||
|
2015-09-18: Version 2.2.3
|
||||||
|
|
||||||
|
- Added a timeout for releasing idling devices.
|
||||||
|
- Reset the RTSP connection after any failed connect.
|
||||||
|
- Added tweaks for minisatip and Schwaiger MS41IP.
|
||||||
|
- Updated for vdr-2.3.1 (Thanks to Klaus Schmidinger).
|
||||||
|
|
||||||
|
2016-12-18: Version 2.2.4
|
||||||
|
|
||||||
|
- Updated German translation (Thanks to Frank Neumann).
|
||||||
|
- Fixed Panasonic CXW804 support (Thanks to Tobias Grimm).
|
||||||
|
- Fixed C++11 support (Thanks to Tobias Grimm).
|
||||||
|
- Fixed server assigment with source validation (Thanks to Patrick Boettcher).
|
||||||
|
- Added configurable RTP/RTCP ports (Thanks to chriszero).
|
||||||
|
- Added support for X-SATIP-RTSP-Port header.
|
||||||
|
- Added multicast and RTP-over-TCP support.
|
||||||
|
- Added support for activating/deactivating server on-the-fly.
|
||||||
|
- Extended command-line parameters for setting server quirks.
|
||||||
|
|
||||||
|
|
||||||
|
===================================
|
||||||
|
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.
|
||||||
|
|||||||
15
Makefile
15
Makefile
@@ -2,18 +2,10 @@
|
|||||||
# Makefile for SAT>IP plugin
|
# Makefile for SAT>IP plugin
|
||||||
#
|
#
|
||||||
|
|
||||||
# Debugging on/off
|
|
||||||
|
|
||||||
#SATIP_DEBUG = 1
|
|
||||||
|
|
||||||
# Use TinyXML instead of PugiXML
|
# Use TinyXML instead of PugiXML
|
||||||
|
|
||||||
#SATIP_USE_TINYXML = 1
|
#SATIP_USE_TINYXML = 1
|
||||||
|
|
||||||
# Strip debug symbols? Set eg. to /bin/true if not
|
|
||||||
|
|
||||||
STRIP = strip
|
|
||||||
|
|
||||||
# The official name of this plugin.
|
# The official name of this plugin.
|
||||||
# This name will be used in the '-P...' option of VDR to load the plugin.
|
# This name will be used in the '-P...' option of VDR to load the plugin.
|
||||||
# By default the main source file also carries this name.
|
# By default the main source file also carries this name.
|
||||||
@@ -40,6 +32,7 @@ TMPDIR ?= /tmp
|
|||||||
|
|
||||||
export CFLAGS = $(call PKGCFG,cflags)
|
export CFLAGS = $(call PKGCFG,cflags)
|
||||||
export CXXFLAGS = $(call PKGCFG,cxxflags)
|
export CXXFLAGS = $(call PKGCFG,cxxflags)
|
||||||
|
STRIP ?= /bin/true
|
||||||
|
|
||||||
### The version number of VDR's plugin API:
|
### The version number of VDR's plugin API:
|
||||||
|
|
||||||
@@ -75,10 +68,6 @@ else
|
|||||||
LIBS += -lpugixml
|
LIBS += -lpugixml
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifdef SATIP_DEBUG
|
|
||||||
DEFINES += -DDEBUG
|
|
||||||
endif
|
|
||||||
|
|
||||||
ifneq ($(strip $(GITTAG)),)
|
ifneq ($(strip $(GITTAG)),)
|
||||||
DEFINES += -DGITVERSION='"-GIT-$(GITTAG)"'
|
DEFINES += -DGITVERSION='"-GIT-$(GITTAG)"'
|
||||||
endif
|
endif
|
||||||
@@ -140,9 +129,7 @@ install-i18n: $(I18Nmsgs)
|
|||||||
|
|
||||||
$(SOFILE): $(OBJS)
|
$(SOFILE): $(OBJS)
|
||||||
$(CXX) $(CXXFLAGS) $(LDFLAGS) -shared $(OBJS) $(LIBS) -o $@
|
$(CXX) $(CXXFLAGS) $(LDFLAGS) -shared $(OBJS) $(LIBS) -o $@
|
||||||
ifndef SATIP_DEBUG
|
|
||||||
@$(STRIP) $@
|
@$(STRIP) $@
|
||||||
endif
|
|
||||||
|
|
||||||
install-lib: $(SOFILE)
|
install-lib: $(SOFILE)
|
||||||
install -D $^ $(DESTDIR)$(LIBDIR)/$^.$(APIVERSION)
|
install -D $^ $(DESTDIR)$(LIBDIR)/$^.$(APIVERSION)
|
||||||
|
|||||||
58
README
58
README
@@ -23,7 +23,8 @@ Requirements:
|
|||||||
TinyXML - a simple, small, C++ XML parser
|
TinyXML - a simple, small, C++ XML parser
|
||||||
http://www.grinninglizard.com/tinyxml/
|
http://www.grinninglizard.com/tinyxml/
|
||||||
|
|
||||||
- VDR >= 2.1.4 for scrambled channels
|
- Glibc >= 2.12 - the GNU C library (recvmmsg)
|
||||||
|
http://www.gnu.org/software/libc/
|
||||||
|
|
||||||
Description:
|
Description:
|
||||||
|
|
||||||
@@ -41,17 +42,30 @@ make -C satip-X.Y.Z install
|
|||||||
Configuration:
|
Configuration:
|
||||||
|
|
||||||
The plugin accepts a "--devices" (-d) command-line parameter defaulting
|
The plugin accepts a "--devices" (-d) command-line parameter defaulting
|
||||||
to one. This parameter defines how many simultaneous transponders can
|
to two. This parameter defines how many simultaneous transponders can
|
||||||
be received, if there are available SAT>IP tuners.
|
be received, if there are available SAT>IP tuners.
|
||||||
|
|
||||||
The plugin accepts also a "--server" (-s) command-line parameter, that
|
The plugin accepts also a "--server" (-s) command-line parameter, that
|
||||||
can be used to manually configure static SAT>IP servers if autodetection
|
can be used to manually configure static SAT>IP servers if autodetection
|
||||||
via UPnP somehow can't be used.
|
via UPnP somehow can't be used. The parameter string is a semicolon
|
||||||
|
separated list of "<ipaddress>|<model>|<description>" entries. The model
|
||||||
|
consists of a DVB system (DVBS2,DVBT2,DVBT,DVBC) and number of available
|
||||||
|
frontends separated by a hyphen:
|
||||||
|
|
||||||
|
vdr -P 'satip -s <ipaddress>[:<port>]|<model>[:<filter>]|<description>[:<quirk>];...'
|
||||||
|
vdr -P 'satip -s 192.168.0.1|DVBS2-2,DVBT2-2|OctopusNet'
|
||||||
|
vdr -P 'satip -s 192.168.0.1|DVBS2-4|OctopusNet;192.168.0.2|DVBT2-4|minisatip:0x18'
|
||||||
|
vdr -P 'satip -s 192.168.0.1:554|DVBS2-2:S19.2E|OctopusNet;192.168.0.2:8554|DVBS2-4:S19.2E,S1W|minisatip'
|
||||||
|
|
||||||
|
The plugin accepts a "--portrange" (-p) command-line parameter, that can
|
||||||
|
be used to manually specify the RTP & RTCP port range and therefore
|
||||||
|
enables using the plugin through a NAT (e.g. Docker bridged network).
|
||||||
|
A minimum of 2 ports per device is required.
|
||||||
|
|
||||||
SAT>IP satellite positions (aka. signal sources) shall be defined via
|
SAT>IP satellite positions (aka. signal sources) shall be defined via
|
||||||
sources.conf. If the source description begins with a number, it's used
|
sources.conf. If the source description begins with a number, it's used
|
||||||
as SAT>IP signal source selection parameter. Otherwise, the default
|
as SAT>IP signal source selection parameter. A special number zero can
|
||||||
parameter is one:
|
be used to disable the source. Otherwise, the default parameter is one:
|
||||||
|
|
||||||
S19.2E Astra 1KR/1L/1M/2C
|
S19.2E Astra 1KR/1L/1M/2C
|
||||||
=> Signal source = 1
|
=> Signal source = 1
|
||||||
@@ -62,9 +76,13 @@ S19.2E 2
|
|||||||
S19.2E 3 Astra 1KR/1L/1M/2C
|
S19.2E 3 Astra 1KR/1L/1M/2C
|
||||||
=> Signal source = 3
|
=> Signal source = 3
|
||||||
|
|
||||||
|
S19.2E 0 Astra 1KR/1L/1M/2C
|
||||||
|
=> Source is disabled
|
||||||
|
|
||||||
A channel can be assigned into a specific SAT>IP frontend by giving the
|
A channel can be assigned into a specific SAT>IP frontend by giving the
|
||||||
identifier number in RID field of a channels.conf entry.
|
identifier number in RID field of a channels.conf entry:
|
||||||
Valid range: 1 ... 8
|
FE = RID % 100
|
||||||
|
Valid range: 1 ... 99
|
||||||
|
|
||||||
Setup menu:
|
Setup menu:
|
||||||
|
|
||||||
@@ -76,6 +94,13 @@ Setup menu:
|
|||||||
option to "low". Similarly, the "high"
|
option to "low". Similarly, the "high"
|
||||||
value prefers the SAT>IP over the local
|
value prefers the SAT>IP over the local
|
||||||
DVB cards when selecting available devices.
|
DVB cards when selecting available devices.
|
||||||
|
- Use CI extension = no If you want to use the CI extension found
|
||||||
|
in some SAT>IP hardware (e.g. Digital
|
||||||
|
Devices OctopusNet), set this option to
|
||||||
|
"yes".
|
||||||
|
- CICAM #<slot> = <system> If you want to assign a CA system into
|
||||||
|
a specific CI slot, set this option to
|
||||||
|
a named one. Use "---" for autoselection.
|
||||||
- Enable EPG scanning = yes If you want exclude all SAT>IP devices
|
- Enable EPG scanning = yes If you want exclude all SAT>IP devices
|
||||||
from VDR's EIT background scanning, set
|
from VDR's EIT background scanning, set
|
||||||
this option to "no".
|
this option to "no".
|
||||||
@@ -91,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.
|
||||||
@@ -106,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.
|
||||||
|
|
||||||
@@ -113,12 +146,19 @@ Notes:
|
|||||||
your setup doesn't have firewalled the UDP port 1900.
|
your setup doesn't have firewalled the UDP port 1900.
|
||||||
|
|
||||||
- Stream decryption requires a separate CAM plugin that works without
|
- Stream decryption requires a separate CAM plugin that works without
|
||||||
direct access to any DVB card devices. The integrated CAM slot in
|
direct access to any DVB card devices. Also the integrated CAM slots
|
||||||
Octopus Net devices isn't supported.
|
in Octopus Net devices are supported.
|
||||||
|
|
||||||
- Tracing can be set on/off dynamically via command-line switch or
|
- Tracing can be set on/off dynamically via command-line switch or
|
||||||
SVDRP command.
|
SVDRP command.
|
||||||
|
|
||||||
|
- OctopusNet firmware 1.0.40 or greater recommended.
|
||||||
|
|
||||||
|
- Inverto OEM firmware 1.17.0.120 or greater recommended.
|
||||||
|
The firmware 1.16.0.120 can be downloaded and installed
|
||||||
|
from their webpage: http://www.inverto.tv/support/
|
||||||
|
An update to a newer firmware should be offered afterwards.
|
||||||
|
|
||||||
Acknowledgements:
|
Acknowledgements:
|
||||||
|
|
||||||
- Big thanks to Digital Devices GmbH for providing the Octopus Net
|
- Big thanks to Digital Devices GmbH for providing the Octopus Net
|
||||||
|
|||||||
64
common.c
64
common.c
@@ -79,10 +79,72 @@ cString ChangeCase(const cString &strP, bool upperP)
|
|||||||
|
|
||||||
const section_filter_table_type section_filter_table[SECTION_FILTER_TABLE_SIZE] =
|
const section_filter_table_type section_filter_table[SECTION_FILTER_TABLE_SIZE] =
|
||||||
{
|
{
|
||||||
/* description tag pid tid mask */
|
// description tag pid tid mask
|
||||||
{trNOOP("PAT (0x00)"), "PAT", 0x00, 0x00, 0xFF},
|
{trNOOP("PAT (0x00)"), "PAT", 0x00, 0x00, 0xFF},
|
||||||
{trNOOP("NIT (0x40)"), "NIT", 0x10, 0x40, 0xFF},
|
{trNOOP("NIT (0x40)"), "NIT", 0x10, 0x40, 0xFF},
|
||||||
{trNOOP("SDT (0x42)"), "SDT", 0x11, 0x42, 0xFF},
|
{trNOOP("SDT (0x42)"), "SDT", 0x11, 0x42, 0xFF},
|
||||||
{trNOOP("EIT (0x4E/0x4F/0x5X/0x6X)"), "EIT", 0x12, 0x40, 0xC0},
|
{trNOOP("EIT (0x4E/0x4F/0x5X/0x6X)"), "EIT", 0x12, 0x40, 0xC0},
|
||||||
{trNOOP("TDT (0x70)"), "TDT", 0x14, 0x70, 0xFF},
|
{trNOOP("TDT (0x70)"), "TDT", 0x14, 0x70, 0xFF},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const ca_systems_table_type ca_systems_table[CA_SYSTEMS_TABLE_SIZE] =
|
||||||
|
{
|
||||||
|
// http://www.dvb.org/index.php?id=174
|
||||||
|
// http://en.wikipedia.org/wiki/Conditional_access_system
|
||||||
|
// start end description
|
||||||
|
{0x0000, 0x0000, "---" }, // 0
|
||||||
|
{0x0100, 0x01FF, "SECA Mediaguard (100..1FF)"}, // 1
|
||||||
|
{0x0464, 0x0464, "EuroDec (464)" }, // 2
|
||||||
|
{0x0500, 0x05FF, "Viaccess (500..5FF)" }, // 3
|
||||||
|
{0x0600, 0x06FF, "Irdeto (600..6FF)" }, // 4
|
||||||
|
{0x0700, 0x07FF, "DigiCipher 2 (700..7FF)" }, // 5
|
||||||
|
{0x0900, 0x09FF, "NDS Videoguard (900..9FF)" }, // 6
|
||||||
|
{0x0B00, 0x0BFF, "Conax (B00..BFF)" }, // 7
|
||||||
|
{0x0D00, 0x0DFF, "CryptoWorks (D00..DFF)" }, // 8
|
||||||
|
{0x0E00, 0x0EFF, "PowerVu (E00..EFF)" }, // 9
|
||||||
|
{0x1000, 0x10FF, "RAS (1000..10FF)" }, // 10
|
||||||
|
{0x1200, 0x12FF, "NagraVision (1200..12FF)" }, // 11
|
||||||
|
{0x1700, 0x17FF, "VCAS (1700..17FF)" }, // 12
|
||||||
|
{0x1800, 0x18FF, "NagraVision (1800..18FF)" }, // 13
|
||||||
|
{0x22F0, 0x22F0, "Codicrypt (22F0)" }, // 14
|
||||||
|
{0x2600, 0x2600, "BISS (2600)" }, // 15
|
||||||
|
{0x2719, 0x2719, "VanyaCas (2719)" }, // 16
|
||||||
|
{0x4347, 0x4347, "CryptOn (4347)" }, // 17
|
||||||
|
{0x4800, 0x4800, "Accessgate (4800)" }, // 18
|
||||||
|
{0x4900, 0x4900, "China Crypt (4900)" }, // 19
|
||||||
|
{0x4A02, 0x4A02, "Tongfang (4A02)" }, // 20
|
||||||
|
{0x4A10, 0x4A10, "EasyCas (4A10)" }, // 21
|
||||||
|
{0x4A20, 0x4A20, "AlphaCrypt (4A20)" }, // 22
|
||||||
|
{0x4A60, 0x4A60, "SkyCrypt (4A60)" }, // 23
|
||||||
|
{0x4A61, 0x4A61, "Neotioncrypt (4A61)" }, // 24
|
||||||
|
{0x4A62, 0x4A62, "SkyCrypt (4A62)" }, // 25
|
||||||
|
{0x4A63, 0x4A63, "Neotion SHL (4A63)" }, // 26
|
||||||
|
{0x4A64, 0x4A6F, "SkyCrypt (4A64)" }, // 27
|
||||||
|
{0x4A70, 0x4A70, "DreamCrypt (4A70)" }, // 28
|
||||||
|
{0x4A80, 0x4A80, "ThalesCrypt (4A80)" }, // 29
|
||||||
|
{0x4AA1, 0x4AA1, "KeyFly (4AA1)" }, // 30
|
||||||
|
{0x4ABF, 0x4ABF, "CTI-CAS (4ABF)" }, // 31
|
||||||
|
{0x4AC1, 0x4AC1, "Latens (4AC1)" }, // 32
|
||||||
|
{0x4AD0, 0x4AD1, "X-Crypt (4AD0)" }, // 33
|
||||||
|
{0x4AD4, 0x4AD4, "OmniCrypt (4AD4)" }, // 34
|
||||||
|
{0x4AE0, 0x4AE1, "Z-Crypt (4AE0)" }, // 35
|
||||||
|
{0x4AE4, 0x4AE4, "CoreCrypt (4AE4)" }, // 36
|
||||||
|
{0x4AE5, 0x4AE5, "PRO-Crypt (4AE5)" }, // 37
|
||||||
|
{0x4AEA, 0x4AEA, "Cryptoguard (4AEA)" }, // 38
|
||||||
|
{0x4AEB, 0x4AEB, "Abel Quintic (4AEB)" }, // 39
|
||||||
|
{0x4AF0, 0x4AF0, "ABV (4AF0)" }, // 40
|
||||||
|
{0x5500, 0x5500, "Z-Crypt (5500)" }, // 41
|
||||||
|
{0x5501, 0x5501, "Griffin (5501)" }, // 42
|
||||||
|
{0x5581, 0x5581, "Bulcrypt (5581)" }, // 43
|
||||||
|
{0x7BE1, 0x7BE1, "DRE-Crypt (7BE1)" }, // 44
|
||||||
|
{0xA101, 0xA101, "RosCrypt-M (A101)" }, // 45
|
||||||
|
{0xEAD0, 0xEAD0, "VanyaCas (EAD0)" }, // 46
|
||||||
|
};
|
||||||
|
|
||||||
|
bool checkCASystem(unsigned int cicamP, int caidP)
|
||||||
|
{
|
||||||
|
// always skip the first row
|
||||||
|
if ((cicamP > 0) && (cicamP < ELEMENTS(ca_systems_table)))
|
||||||
|
return ((caidP >= ca_systems_table[cicamP].start) && (caidP <= ca_systems_table[cicamP].end));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|||||||
68
common.h
68
common.h
@@ -13,11 +13,11 @@
|
|||||||
#include <vdr/config.h>
|
#include <vdr/config.h>
|
||||||
#include <vdr/i18n.h>
|
#include <vdr/i18n.h>
|
||||||
|
|
||||||
#define ELEMENTS(x) (sizeof(x) / sizeof(x[0]))
|
#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
|
||||||
@@ -29,12 +29,15 @@
|
|||||||
#define SATIP_STATS_ACTIVE_PIDS_COUNT 10
|
#define SATIP_STATS_ACTIVE_PIDS_COUNT 10
|
||||||
#define SATIP_STATS_ACTIVE_FILTERS_COUNT 10
|
#define SATIP_STATS_ACTIVE_FILTERS_COUNT 10
|
||||||
|
|
||||||
#define MAX_DISABLED_SOURCES_COUNT 5
|
#define MAX_DISABLED_SOURCES_COUNT 25
|
||||||
#define SECTION_FILTER_TABLE_SIZE 5
|
#define SECTION_FILTER_TABLE_SIZE 5
|
||||||
|
|
||||||
|
#define MAX_CICAM_COUNT 2
|
||||||
|
#define CA_SYSTEMS_TABLE_SIZE 47
|
||||||
|
|
||||||
#define SATIP_CURL_EASY_GETINFO(X, Y, Z) \
|
#define SATIP_CURL_EASY_GETINFO(X, Y, Z) \
|
||||||
if ((res = curl_easy_getinfo((X), (Y), (Z))) != CURLE_OK) { \
|
if ((res = curl_easy_getinfo((X), (Y), (Z))) != CURLE_OK) { \
|
||||||
error("curl_easy_getinfo(%s) [%s,%d] failed: %s (%d)", #Y, __FILE__, __LINE__, curl_easy_strerror(res), res); \
|
esyslog("curl_easy_getinfo(%s) [%s,%d] failed: %s (%d)", #Y, __FILE__, __LINE__, curl_easy_strerror(res), res); \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define SATIP_CURL_EASY_SETOPT(X, Y, Z) \
|
#define SATIP_CURL_EASY_SETOPT(X, Y, Z) \
|
||||||
@@ -81,7 +84,53 @@
|
|||||||
} \
|
} \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof(arr[0]))
|
#define ELEMENTS(x) (sizeof(x) / sizeof(x[0]))
|
||||||
|
|
||||||
|
class cSatipMemoryBuffer {
|
||||||
|
private:
|
||||||
|
enum {
|
||||||
|
eMaxDataSize = MEGABYTE(2)
|
||||||
|
};
|
||||||
|
char *dataM;
|
||||||
|
size_t sizeM;
|
||||||
|
void *AllocBuffer(void *ptrP, size_t sizeP)
|
||||||
|
{
|
||||||
|
// There might be a realloc() out there that doesn't like reallocing NULL pointers, so we take care of it here
|
||||||
|
if (ptrP)
|
||||||
|
return realloc(ptrP, sizeP);
|
||||||
|
else
|
||||||
|
return malloc(sizeP);
|
||||||
|
}
|
||||||
|
// to prevent copy constructor and assignment
|
||||||
|
cSatipMemoryBuffer(const cSatipMemoryBuffer&);
|
||||||
|
cSatipMemoryBuffer& operator=(const cSatipMemoryBuffer&);
|
||||||
|
public:
|
||||||
|
cSatipMemoryBuffer() : dataM(NULL), sizeM(0) {}
|
||||||
|
~cSatipMemoryBuffer() { Reset(); }
|
||||||
|
size_t Add(char *dataP, size_t sizeP)
|
||||||
|
{
|
||||||
|
if (sizeP > 0) {
|
||||||
|
size_t len = sizeM + sizeP + 1;
|
||||||
|
if (len < eMaxDataSize) {
|
||||||
|
dataM = (char *)AllocBuffer(dataM, len);
|
||||||
|
if (dataM) {
|
||||||
|
memcpy(&(dataM[sizeM]), dataP, sizeP);
|
||||||
|
sizeM += sizeP;
|
||||||
|
dataM[sizeM] = 0;
|
||||||
|
return sizeP;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
esyslog("[%s,%d]: Failed to allocate memory", __FILE__, __LINE__);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
esyslog("[%s,%d]: Buffer overflow", __FILE__, __LINE__);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
};
|
||||||
|
char *Data(void) { return dataM; }
|
||||||
|
size_t Size(void) { return sizeM; }
|
||||||
|
void Reset(void) { FREE_POINTER(dataM); sizeM = 0; };
|
||||||
|
};
|
||||||
|
|
||||||
uint16_t ts_pid(const uint8_t *bufP);
|
uint16_t ts_pid(const uint8_t *bufP);
|
||||||
uint8_t payload(const uint8_t *bufP);
|
uint8_t payload(const uint8_t *bufP);
|
||||||
@@ -100,6 +149,15 @@ struct section_filter_table_type {
|
|||||||
|
|
||||||
extern const section_filter_table_type section_filter_table[SECTION_FILTER_TABLE_SIZE];
|
extern const section_filter_table_type section_filter_table[SECTION_FILTER_TABLE_SIZE];
|
||||||
|
|
||||||
|
struct ca_systems_table_type {
|
||||||
|
int start;
|
||||||
|
int end;
|
||||||
|
const char *description;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern const ca_systems_table_type ca_systems_table[CA_SYSTEMS_TABLE_SIZE];
|
||||||
|
extern bool checkCASystem(unsigned int cicamP, int caidP);
|
||||||
|
|
||||||
extern const char VERSION[];
|
extern const char VERSION[];
|
||||||
|
|
||||||
#endif // __SATIP_COMMON_H
|
#endif // __SATIP_COMMON_H
|
||||||
|
|||||||
45
config.c
45
config.c
@@ -14,56 +14,69 @@ cSatipConfig SatipConfig;
|
|||||||
cSatipConfig::cSatipConfig(void)
|
cSatipConfig::cSatipConfig(void)
|
||||||
: operatingModeM(eOperatingModeLow),
|
: operatingModeM(eOperatingModeLow),
|
||||||
traceModeM(eTraceModeNormal),
|
traceModeM(eTraceModeNormal),
|
||||||
|
ciExtensionM(0),
|
||||||
eitScanM(1),
|
eitScanM(1),
|
||||||
useBytesM(1)
|
useBytesM(1),
|
||||||
|
portRangeStartM(0),
|
||||||
|
portRangeStopM(0),
|
||||||
|
transportModeM(eTransportModeUnicast),
|
||||||
|
detachedModeM(false),
|
||||||
|
disableServerQuirksM(false),
|
||||||
|
useSingleModelServersM(false)
|
||||||
{
|
{
|
||||||
for (unsigned int i = 0; i < ARRAY_SIZE(disabledSourcesM); ++i)
|
for (unsigned int i = 0; i < ELEMENTS(cicamsM); ++i)
|
||||||
|
cicamsM[i] = 0;
|
||||||
|
for (unsigned int i = 0; i < ELEMENTS(disabledSourcesM); ++i)
|
||||||
disabledSourcesM[i] = cSource::stNone;
|
disabledSourcesM[i] = cSource::stNone;
|
||||||
for (unsigned int i = 0; i < ARRAY_SIZE(disabledFiltersM); ++i)
|
for (unsigned int i = 0; i < ELEMENTS(disabledFiltersM); ++i)
|
||||||
disabledFiltersM[i] = -1;
|
disabledFiltersM[i] = -1;
|
||||||
memset(configDirectoryM, 0, sizeof(configDirectoryM));
|
}
|
||||||
|
|
||||||
|
int cSatipConfig::GetCICAM(unsigned int indexP) const
|
||||||
|
{
|
||||||
|
return (indexP < ELEMENTS(cicamsM)) ? cicamsM[indexP] : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cSatipConfig::SetCICAM(unsigned int indexP, int cicamP)
|
||||||
|
{
|
||||||
|
if (indexP < ELEMENTS(cicamsM))
|
||||||
|
cicamsM[indexP] = cicamP;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int cSatipConfig::GetDisabledSourcesCount(void) const
|
unsigned int cSatipConfig::GetDisabledSourcesCount(void) const
|
||||||
{
|
{
|
||||||
unsigned int n = 0;
|
unsigned int n = 0;
|
||||||
while ((n < ARRAY_SIZE(disabledSourcesM) && (disabledSourcesM[n] != cSource::stNone)))
|
while ((n < ELEMENTS(disabledSourcesM) && (disabledSourcesM[n] != cSource::stNone)))
|
||||||
n++;
|
n++;
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
int cSatipConfig::GetDisabledSources(unsigned int indexP) const
|
int cSatipConfig::GetDisabledSources(unsigned int indexP) const
|
||||||
{
|
{
|
||||||
return (indexP < ARRAY_SIZE(disabledSourcesM)) ? disabledSourcesM[indexP] : cSource::stNone;
|
return (indexP < ELEMENTS(disabledSourcesM)) ? disabledSourcesM[indexP] : cSource::stNone;
|
||||||
}
|
}
|
||||||
|
|
||||||
void cSatipConfig::SetDisabledSources(unsigned int indexP, int sourceP)
|
void cSatipConfig::SetDisabledSources(unsigned int indexP, int sourceP)
|
||||||
{
|
{
|
||||||
if (indexP < ARRAY_SIZE(disabledSourcesM))
|
if (indexP < ELEMENTS(disabledSourcesM))
|
||||||
disabledSourcesM[indexP] = sourceP;
|
disabledSourcesM[indexP] = sourceP;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int cSatipConfig::GetDisabledFiltersCount(void) const
|
unsigned int cSatipConfig::GetDisabledFiltersCount(void) const
|
||||||
{
|
{
|
||||||
unsigned int n = 0;
|
unsigned int n = 0;
|
||||||
while ((n < ARRAY_SIZE(disabledFiltersM) && (disabledFiltersM[n] != -1)))
|
while ((n < ELEMENTS(disabledFiltersM) && (disabledFiltersM[n] != -1)))
|
||||||
n++;
|
n++;
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
int cSatipConfig::GetDisabledFilters(unsigned int indexP) const
|
int cSatipConfig::GetDisabledFilters(unsigned int indexP) const
|
||||||
{
|
{
|
||||||
return (indexP < ARRAY_SIZE(disabledFiltersM)) ? disabledFiltersM[indexP] : -1;
|
return (indexP < ELEMENTS(disabledFiltersM)) ? disabledFiltersM[indexP] : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void cSatipConfig::SetDisabledFilters(unsigned int indexP, int numberP)
|
void cSatipConfig::SetDisabledFilters(unsigned int indexP, int numberP)
|
||||||
{
|
{
|
||||||
if (indexP < ARRAY_SIZE(disabledFiltersM))
|
if (indexP < ELEMENTS(disabledFiltersM))
|
||||||
disabledFiltersM[indexP] = numberP;
|
disabledFiltersM[indexP] = numberP;
|
||||||
}
|
}
|
||||||
|
|
||||||
void cSatipConfig::SetConfigDirectory(const char *directoryP)
|
|
||||||
{
|
|
||||||
debug1("%s (%s)", __PRETTY_FUNCTION__, directoryP);
|
|
||||||
ERROR_IF(!realpath(directoryP, configDirectoryM), "Cannot canonicalize configuration directory");
|
|
||||||
}
|
|
||||||
|
|||||||
36
config.h
36
config.h
@@ -16,11 +16,18 @@ class cSatipConfig
|
|||||||
private:
|
private:
|
||||||
unsigned int operatingModeM;
|
unsigned int operatingModeM;
|
||||||
unsigned int traceModeM;
|
unsigned int traceModeM;
|
||||||
|
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 disableServerQuirksM;
|
||||||
|
bool useSingleModelServersM;
|
||||||
|
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];
|
||||||
char configDirectoryM[PATH_MAX];
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
enum eOperatingMode {
|
enum eOperatingMode {
|
||||||
@@ -30,6 +37,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,
|
||||||
@@ -59,21 +72,38 @@ public:
|
|||||||
void ToggleOperatingMode(void) { operatingModeM = (operatingModeM + 1) % eOperatingModeCount; }
|
void ToggleOperatingMode(void) { operatingModeM = (operatingModeM + 1) % eOperatingModeCount; }
|
||||||
unsigned int GetTraceMode(void) const { return traceModeM; }
|
unsigned int GetTraceMode(void) const { return traceModeM; }
|
||||||
bool IsTraceMode(eTraceMode modeP) const { return (traceModeM & modeP); }
|
bool IsTraceMode(eTraceMode modeP) const { return (traceModeM & modeP); }
|
||||||
|
unsigned int GetCIExtension(void) const { return ciExtensionM; }
|
||||||
|
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; }
|
||||||
const char *GetConfigDirectory(void) const { return configDirectoryM; }
|
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 GetDisableServerQuirks(void) const { return disableServerQuirksM; }
|
||||||
|
bool GetUseSingleModelServers(void) const { return useSingleModelServersM; }
|
||||||
unsigned int GetDisabledSourcesCount(void) const;
|
unsigned int GetDisabledSourcesCount(void) const;
|
||||||
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; }
|
||||||
|
|
||||||
void SetOperatingMode(unsigned int operatingModeP) { operatingModeM = operatingModeP; }
|
void SetOperatingMode(unsigned int operatingModeP) { operatingModeM = operatingModeP; }
|
||||||
void SetTraceMode(unsigned int modeP) { traceModeM = (modeP & eTraceModeMask); }
|
void SetTraceMode(unsigned int modeP) { traceModeM = (modeP & eTraceModeMask); }
|
||||||
|
void SetCIExtension(unsigned int onOffP) { ciExtensionM = onOffP; }
|
||||||
|
void 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 SetConfigDirectory(const char *directoryP);
|
void SetTransportMode(unsigned int transportModeP) { transportModeM = transportModeP; }
|
||||||
|
void SetDetachedMode(bool onOffP) { detachedModeM = onOffP; }
|
||||||
|
void SetDisableServerQuirks(bool onOffP) { disableServerQuirksM = onOffP; }
|
||||||
|
void SetUseSingleModelServers(bool onOffP) { useSingleModelServersM = onOffP; }
|
||||||
void SetDisabledSources(unsigned int indexP, int sourceP);
|
void 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; }
|
||||||
};
|
};
|
||||||
|
|
||||||
extern cSatipConfig SatipConfig;
|
extern cSatipConfig SatipConfig;
|
||||||
|
|||||||
91
device.c
91
device.c
@@ -103,7 +103,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();
|
||||||
for (cTimer *timer = Timers.First(); timer; timer = Timers.Next(timer)) {
|
LOCK_TIMERS_READ;
|
||||||
|
for (const cTimer *timer = Timers->First(); timer; timer = Timers->Next(timer)) {
|
||||||
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)
|
||||||
@@ -115,8 +116,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);
|
||||||
@@ -128,13 +133,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);
|
||||||
return cString::sprintf("SAT>IP device: %d\nCardIndex: %d\nStream: %s\nSignal: %s\nStream bitrate: %s\n%sChannel: %s",
|
LOCK_CHANNELS_READ;
|
||||||
|
return cString::sprintf("SAT>IP device: %d\nCardIndex: %d\nStream: %s\nSignal: %s\nStream bitrate: %s\n%sChannel: %s\n",
|
||||||
deviceIndexM, CardIndex(),
|
deviceIndexM, CardIndex(),
|
||||||
pTunerM ? *pTunerM->GetInformation() : "",
|
pTunerM ? *pTunerM->GetInformation() : "",
|
||||||
pTunerM ? *pTunerM->GetSignalStatus() : "",
|
pTunerM ? *pTunerM->GetSignalStatus() : "",
|
||||||
pTunerM ? *pTunerM->GetTunerStatistic() : "",
|
pTunerM ? *pTunerM->GetTunerStatistic() : "",
|
||||||
*GetBufferStatistic(),
|
*GetBufferStatistic(),
|
||||||
*Channels.GetByNumber(cDevice::CurrentChannel())->ToText());
|
*Channels->GetByNumber(cDevice::CurrentChannel())->ToText());
|
||||||
}
|
}
|
||||||
|
|
||||||
cString cSatipDevice::GetPidsInformation(void)
|
cString cSatipDevice::GetPidsInformation(void)
|
||||||
@@ -194,6 +200,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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -217,7 +225,13 @@ int cSatipDevice::SignalQuality(void) const
|
|||||||
|
|
||||||
bool cSatipDevice::ProvidesSource(int sourceP) const
|
bool cSatipDevice::ProvidesSource(int sourceP) const
|
||||||
{
|
{
|
||||||
debug9("%s (%c) [device %u]", __PRETTY_FUNCTION__, cSource::ToChar(sourceP), deviceIndexM);
|
cSource *s = Sources.Get(sourceP);
|
||||||
|
debug9("%s (%c) desc='%s' [device %u]", __PRETTY_FUNCTION__, cSource::ToChar(sourceP), s ? s->Description() : "", deviceIndexM);
|
||||||
|
if (SatipConfig.GetDetachedMode())
|
||||||
|
return false;
|
||||||
|
// source descriptions starting with '0' are disabled
|
||||||
|
if (s && s->Description() && (*(s->Description()) == '0'))
|
||||||
|
return false;
|
||||||
if (!SatipConfig.IsOperatingModeOff() && !!cSatipDiscover::GetInstance()->GetServer(sourceP)) {
|
if (!SatipConfig.IsOperatingModeOff() && !!cSatipDiscover::GetInstance()->GetServer(sourceP)) {
|
||||||
int numDisabledSourcesM = SatipConfig.GetDisabledSourcesCount();
|
int numDisabledSourcesM = SatipConfig.GetDisabledSourcesCount();
|
||||||
for (int i = 0; i < numDisabledSourcesM; ++i) {
|
for (int i = 0; i < numDisabledSourcesM; ++i) {
|
||||||
@@ -324,20 +338,20 @@ bool cSatipDevice::SetChannelDevice(const cChannel *channelP, bool liveViewP)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
cString address;
|
cString address;
|
||||||
cSatipServer *server = cSatipDiscover::GetInstance()->GetServer(channelP->Source(), channelP->Transponder(), dtp.System());
|
cSatipServer *server = cSatipDiscover::GetInstance()->AssignServer(deviceIndexM, channelP->Source(), channelP->Transponder(), dtp.System());
|
||||||
if (!server) {
|
if (!server) {
|
||||||
debug1("%s No suitable server found [device %u]", __PRETTY_FUNCTION__, deviceIndexM);
|
debug9("%s No suitable server found [device %u]", __PRETTY_FUNCTION__, deviceIndexM);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
cSatipDiscover::GetInstance()->SetTransponder(server, channelP->Transponder());
|
if (pTunerM && pTunerM->SetSource(server, channelP->Transponder(), *params, deviceIndexM)) {
|
||||||
if (pTunerM && pTunerM->SetSource(server, *params, deviceIndexM)) {
|
|
||||||
deviceNameM = cString::sprintf("%s %d %s", *DeviceType(), deviceIndexM, *cSatipDiscover::GetInstance()->GetServerString(server));
|
|
||||||
channelM = *channelP;
|
channelM = *channelP;
|
||||||
|
deviceNameM = cString::sprintf("%s %d %s", *DeviceType(), deviceIndexM, *cSatipDiscover::GetInstance()->GetServerString(server));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (pTunerM) {
|
else if (pTunerM) {
|
||||||
pTunerM->SetSource(NULL, NULL, deviceIndexM);
|
pTunerM->SetSource(NULL, 0, NULL, deviceIndexM);
|
||||||
|
deviceNameM = cString::sprintf("%s %d", *DeviceType(), deviceIndexM);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@@ -345,11 +359,11 @@ bool cSatipDevice::SetChannelDevice(const cChannel *channelP, bool liveViewP)
|
|||||||
|
|
||||||
bool cSatipDevice::SetPid(cPidHandle *handleP, int typeP, bool onP)
|
bool cSatipDevice::SetPid(cPidHandle *handleP, int typeP, bool onP)
|
||||||
{
|
{
|
||||||
debug9("%s (%d, %d, %d) [device %u]", __PRETTY_FUNCTION__, handleP->pid, 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;
|
||||||
@@ -357,7 +371,7 @@ bool cSatipDevice::SetPid(cPidHandle *handleP, int typeP, bool onP)
|
|||||||
|
|
||||||
int cSatipDevice::OpenFilter(u_short pidP, u_char tidP, u_char maskP)
|
int cSatipDevice::OpenFilter(u_short pidP, u_char tidP, u_char maskP)
|
||||||
{
|
{
|
||||||
debug9("%s (%d, %02X, %02X) [device %d]", __PRETTY_FUNCTION__, pidP, tidP, maskP, deviceIndexM);
|
debug12("%s (%d, %02X, %02X) [device %d]", __PRETTY_FUNCTION__, pidP, tidP, maskP, deviceIndexM);
|
||||||
if (pSectionFilterHandlerM) {
|
if (pSectionFilterHandlerM) {
|
||||||
int handle = pSectionFilterHandlerM->Open(pidP, tidP, maskP);
|
int handle = pSectionFilterHandlerM->Open(pidP, tidP, maskP);
|
||||||
if (pTunerM && (handle >= 0))
|
if (pTunerM && (handle >= 0))
|
||||||
@@ -371,7 +385,7 @@ void cSatipDevice::CloseFilter(int handleP)
|
|||||||
{
|
{
|
||||||
if (pSectionFilterHandlerM) {
|
if (pSectionFilterHandlerM) {
|
||||||
int pid = pSectionFilterHandlerM->GetPid(handleP);
|
int pid = pSectionFilterHandlerM->GetPid(handleP);
|
||||||
debug9("%s (%d) [device %u]", __PRETTY_FUNCTION__, pid, deviceIndexM);
|
debug12("%s (%d) [device %u]", __PRETTY_FUNCTION__, pid, deviceIndexM);
|
||||||
if (pTunerM)
|
if (pTunerM)
|
||||||
pTunerM->SetPid(pid, ptOther, false);
|
pTunerM->SetPid(pid, ptOther, false);
|
||||||
pSectionFilterHandlerM->Close(handleP);
|
pSectionFilterHandlerM->Close(handleP);
|
||||||
@@ -406,7 +420,7 @@ bool cSatipDevice::HasLock(int timeoutMsP) const
|
|||||||
bool cSatipDevice::HasInternalCam(void)
|
bool cSatipDevice::HasInternalCam(void)
|
||||||
{
|
{
|
||||||
debug16("%s [device %u]", __PRETTY_FUNCTION__, deviceIndexM);
|
debug16("%s [device %u]", __PRETTY_FUNCTION__, deviceIndexM);
|
||||||
return false;
|
return SatipConfig.GetCIExtension();
|
||||||
}
|
}
|
||||||
|
|
||||||
void cSatipDevice::WriteData(uchar *bufferP, int lengthP)
|
void cSatipDevice::WriteData(uchar *bufferP, int lengthP)
|
||||||
@@ -428,6 +442,45 @@ int cSatipDevice::GetId(void)
|
|||||||
return deviceIndexM;
|
return deviceIndexM;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int cSatipDevice::GetPmtPid(void)
|
||||||
|
{
|
||||||
|
int pid = channelM.Ca() ? ::GetPmtPid(channelM.Source(), channelM.Transponder(), channelM.Sid()) : 0;
|
||||||
|
debug11("%s pmtpid=%d source=%c transponder=%d sid=%d name=%s [device %u]", __PRETTY_FUNCTION__, pid, cSource::ToChar(channelM.Source()), channelM.Transponder(), channelM.Sid(), channelM.Name(), deviceIndexM);
|
||||||
|
return pid;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cSatipDevice::GetCISlot(void)
|
||||||
|
{
|
||||||
|
int slot = 0;
|
||||||
|
int ca = 0;
|
||||||
|
for (const int *id = channelM.Caids(); *id; ++id) {
|
||||||
|
if (checkCASystem(SatipConfig.GetCICAM(0), *id)) {
|
||||||
|
ca = *id;
|
||||||
|
slot = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if (checkCASystem(SatipConfig.GetCICAM(1), *id)) {
|
||||||
|
ca = *id;
|
||||||
|
slot = 2;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
debug11("%s slot=%d ca=%X name=%s [device %u]", __PRETTY_FUNCTION__, slot, ca, channelM.Name(), deviceIndexM);
|
||||||
|
return slot;
|
||||||
|
}
|
||||||
|
|
||||||
|
cString cSatipDevice::GetTnrParameterString(void)
|
||||||
|
{
|
||||||
|
if (channelM.Ca())
|
||||||
|
return GetTnrUrlParameters(&channelM);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool cSatipDevice::IsIdle(void)
|
||||||
|
{
|
||||||
|
return !Receiving();
|
||||||
|
}
|
||||||
|
|
||||||
uchar *cSatipDevice::GetData(int *availableP)
|
uchar *cSatipDevice::GetData(int *availableP)
|
||||||
{
|
{
|
||||||
debug16("%s [device %u]", __PRETTY_FUNCTION__, deviceIndexM);
|
debug16("%s [device %u]", __PRETTY_FUNCTION__, deviceIndexM);
|
||||||
@@ -471,8 +524,9 @@ void cSatipDevice::SkipData(int countP)
|
|||||||
bool cSatipDevice::GetTSPacket(uchar *&dataP)
|
bool cSatipDevice::GetTSPacket(uchar *&dataP)
|
||||||
{
|
{
|
||||||
debug16("%s [device %u]", __PRETTY_FUNCTION__, deviceIndexM);
|
debug16("%s [device %u]", __PRETTY_FUNCTION__, deviceIndexM);
|
||||||
|
if (SatipConfig.GetDetachedMode())
|
||||||
|
return false;
|
||||||
if (tsBufferM) {
|
if (tsBufferM) {
|
||||||
#if defined(APIVERSNUM) && APIVERSNUM >= 20104
|
|
||||||
if (cCamSlot *cs = CamSlot()) {
|
if (cCamSlot *cs = CamSlot()) {
|
||||||
if (cs->WantsTsData()) {
|
if (cs->WantsTsData()) {
|
||||||
int available;
|
int available;
|
||||||
@@ -484,7 +538,6 @@ bool cSatipDevice::GetTSPacket(uchar *&dataP)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
dataP = GetData();
|
dataP = GetData();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
6
device.h
6
device.h
@@ -43,7 +43,7 @@ private:
|
|||||||
|
|
||||||
// constructor & destructor
|
// constructor & destructor
|
||||||
public:
|
public:
|
||||||
cSatipDevice(unsigned int deviceIndexP);
|
explicit cSatipDevice(unsigned int deviceIndexP);
|
||||||
virtual ~cSatipDevice();
|
virtual ~cSatipDevice();
|
||||||
cString GetInformation(unsigned int pageP = SATIP_DEVICE_INFO_ALL);
|
cString GetInformation(unsigned int pageP = SATIP_DEVICE_INFO_ALL);
|
||||||
|
|
||||||
@@ -108,6 +108,10 @@ public:
|
|||||||
public:
|
public:
|
||||||
virtual void WriteData(u_char *bufferP, int lengthP);
|
virtual void WriteData(u_char *bufferP, int lengthP);
|
||||||
virtual int GetId(void);
|
virtual int GetId(void);
|
||||||
|
virtual int GetPmtPid(void);
|
||||||
|
virtual int GetCISlot(void);
|
||||||
|
virtual cString GetTnrParameterString(void);
|
||||||
|
virtual bool IsIdle(void);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // __SATIP_DEVICE_H
|
#endif // __SATIP_DEVICE_H
|
||||||
|
|||||||
@@ -14,9 +14,13 @@ public:
|
|||||||
virtual ~cSatipDeviceIf() {}
|
virtual ~cSatipDeviceIf() {}
|
||||||
virtual void WriteData(u_char *bufferP, int lengthP) = 0;
|
virtual void WriteData(u_char *bufferP, int lengthP) = 0;
|
||||||
virtual int GetId(void) = 0;
|
virtual int GetId(void) = 0;
|
||||||
|
virtual int GetPmtPid(void) = 0;
|
||||||
|
virtual int GetCISlot(void) = 0;
|
||||||
|
virtual cString GetTnrParameterString(void) = 0;
|
||||||
|
virtual bool IsIdle(void) = 0;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
cSatipDeviceIf(const cSatipDeviceIf&);
|
explicit cSatipDeviceIf(const cSatipDeviceIf&);
|
||||||
cSatipDeviceIf& operator=(const cSatipDeviceIf&);
|
cSatipDeviceIf& operator=(const cSatipDeviceIf&);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
212
discover.c
212
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->IpAddress(), s->IpPort(), s->Model(), s->Filters(), s->Description(), s->Quirk());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
instanceS->Activate();
|
instanceS->Activate();
|
||||||
@@ -47,44 +47,27 @@ void cSatipDiscover::Destroy(void)
|
|||||||
instanceS->Deactivate();
|
instanceS->Deactivate();
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t cSatipDiscover::WriteCallback(char *ptrP, size_t sizeP, size_t nmembP, void *dataP)
|
size_t cSatipDiscover::HeaderCallback(char *ptrP, size_t sizeP, size_t nmembP, void *dataP)
|
||||||
{
|
{
|
||||||
cSatipDiscover *obj = reinterpret_cast<cSatipDiscover *>(dataP);
|
cSatipDiscover *obj = reinterpret_cast<cSatipDiscover *>(dataP);
|
||||||
size_t len = sizeP * nmembP;
|
size_t len = sizeP * nmembP;
|
||||||
debug16("%s len=%zu", __PRETTY_FUNCTION__, len);
|
debug16("%s len=%zu", __PRETTY_FUNCTION__, len);
|
||||||
|
|
||||||
if (obj) {
|
if (obj && (len > 0))
|
||||||
CURLcode res = CURLE_OK;
|
obj->headerBufferM.Add(ptrP, len);
|
||||||
const char *desc = NULL, *model = NULL, *addr = NULL;
|
|
||||||
#ifdef USE_TINYXML
|
return len;
|
||||||
TiXmlDocument doc;
|
|
||||||
char *xml = MALLOC(char, len + 1);
|
|
||||||
memcpy(xml, ptrP, len);
|
|
||||||
*(xml + len + 1) = 0;
|
|
||||||
doc.Parse((const char *)xml);
|
|
||||||
TiXmlHandle docHandle(&doc);
|
|
||||||
TiXmlElement *descElement = docHandle.FirstChild("root").FirstChild("device").FirstChild("friendlyName").ToElement();
|
|
||||||
if (descElement)
|
|
||||||
desc = descElement->GetText() ? descElement->GetText() : "MyBrokenHardware";
|
|
||||||
TiXmlElement *modelElement = docHandle.FirstChild("root").FirstChild("device").FirstChild("satip:X_SATIPCAP").ToElement();
|
|
||||||
if (modelElement)
|
|
||||||
model = modelElement->GetText() ? modelElement->GetText() : "DVBS2-1";
|
|
||||||
#else
|
|
||||||
pugi::xml_document doc;
|
|
||||||
pugi::xml_parse_result result = doc.load_buffer(ptrP, len);
|
|
||||||
if (result) {
|
|
||||||
pugi::xml_node descNode = doc.first_element_by_path("root/device/friendlyName");
|
|
||||||
if (descNode)
|
|
||||||
desc = descNode.text().as_string("MyBrokenHardware");
|
|
||||||
pugi::xml_node modelNode = doc.first_element_by_path("root/device/satip:X_SATIPCAP");
|
|
||||||
if (modelNode)
|
|
||||||
model = modelNode.text().as_string("DVBS2-1");
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
SATIP_CURL_EASY_GETINFO(obj->handleM, CURLINFO_PRIMARY_IP, &addr);
|
|
||||||
obj->AddServer(addr, model, desc);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t cSatipDiscover::DataCallback(char *ptrP, size_t sizeP, size_t nmembP, void *dataP)
|
||||||
|
{
|
||||||
|
cSatipDiscover *obj = reinterpret_cast<cSatipDiscover *>(dataP);
|
||||||
|
size_t len = sizeP * nmembP;
|
||||||
|
debug16("%s len=%zu", __PRETTY_FUNCTION__, len);
|
||||||
|
|
||||||
|
if (obj && (len > 0))
|
||||||
|
obj->dataBufferM.Add(ptrP, len);
|
||||||
|
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -120,6 +103,8 @@ int cSatipDiscover::DebugCallback(CURL *handleP, curl_infotype typeP, char *data
|
|||||||
cSatipDiscover::cSatipDiscover()
|
cSatipDiscover::cSatipDiscover()
|
||||||
: cThread("SATIP discover"),
|
: cThread("SATIP discover"),
|
||||||
mutexM(),
|
mutexM(),
|
||||||
|
headerBufferM(),
|
||||||
|
dataBufferM(),
|
||||||
msearchM(*this),
|
msearchM(*this),
|
||||||
probeUrlListM(),
|
probeUrlListM(),
|
||||||
handleM(curl_easy_init()),
|
handleM(curl_easy_init()),
|
||||||
@@ -170,7 +155,7 @@ void cSatipDiscover::Action(void)
|
|||||||
probeIntervalM.Set(eProbeIntervalMs);
|
probeIntervalM.Set(eProbeIntervalMs);
|
||||||
msearchM.Probe();
|
msearchM.Probe();
|
||||||
mutexM.Lock();
|
mutexM.Lock();
|
||||||
serversM.Cleanup(eProbeIntervalMs * 2);
|
serversM.Cleanup(eCleanupTimeoutMs);
|
||||||
mutexM.Unlock();
|
mutexM.Unlock();
|
||||||
}
|
}
|
||||||
mutexM.Lock();
|
mutexM.Lock();
|
||||||
@@ -195,6 +180,7 @@ void cSatipDiscover::Fetch(const char *urlP)
|
|||||||
{
|
{
|
||||||
debug1("%s (%s)", __PRETTY_FUNCTION__, urlP);
|
debug1("%s (%s)", __PRETTY_FUNCTION__, urlP);
|
||||||
if (handleM && !isempty(urlP)) {
|
if (handleM && !isempty(urlP)) {
|
||||||
|
const char *addr = NULL;
|
||||||
long rc = 0;
|
long rc = 0;
|
||||||
CURLcode res = CURLE_OK;
|
CURLcode res = CURLE_OK;
|
||||||
|
|
||||||
@@ -203,8 +189,10 @@ 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_WRITEFUNCTION, cSatipDiscover::WriteCallback);
|
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_HEADERFUNCTION, cSatipDiscover::HeaderCallback);
|
||||||
|
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEHEADER, this);
|
||||||
|
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEFUNCTION, cSatipDiscover::DataCallback);
|
||||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEDATA, this);
|
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEDATA, this);
|
||||||
|
|
||||||
// No progress meter and no signaling
|
// No progress meter and no signaling
|
||||||
@@ -224,23 +212,99 @@ void cSatipDiscover::Fetch(const char *urlP)
|
|||||||
// Fetch the data
|
// Fetch the data
|
||||||
SATIP_CURL_EASY_PERFORM(handleM);
|
SATIP_CURL_EASY_PERFORM(handleM);
|
||||||
SATIP_CURL_EASY_GETINFO(handleM, CURLINFO_RESPONSE_CODE, &rc);
|
SATIP_CURL_EASY_GETINFO(handleM, CURLINFO_RESPONSE_CODE, &rc);
|
||||||
if (rc != 200)
|
SATIP_CURL_EASY_GETINFO(handleM, CURLINFO_PRIMARY_IP, &addr);
|
||||||
|
if (rc == 200) {
|
||||||
|
ParseDeviceInfo(addr, ParseRtspPort());
|
||||||
|
headerBufferM.Reset();
|
||||||
|
dataBufferM.Reset();
|
||||||
|
}
|
||||||
|
else
|
||||||
error("Discovery detected invalid status code: %ld", rc);
|
error("Discovery detected invalid status code: %ld", rc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void cSatipDiscover::AddServer(const char *addrP, const char *modelP, const char * descP)
|
int cSatipDiscover::ParseRtspPort(void)
|
||||||
{
|
{
|
||||||
debug1("%s (%s, %s, %s)", __PRETTY_FUNCTION__, addrP, modelP, descP);
|
debug1("%s", __PRETTY_FUNCTION__);
|
||||||
|
char *s, *p = headerBufferM.Data();
|
||||||
|
char *r = strtok_r(p, "\r\n", &s);
|
||||||
|
int port = SATIP_DEFAULT_RTSP_PORT;
|
||||||
|
|
||||||
|
while (r) {
|
||||||
|
debug16("%s (%zu): %s", __PRETTY_FUNCTION__, headerBufferM.Size(), r);
|
||||||
|
r = skipspace(r);
|
||||||
|
if (strstr(r, "X-SATIP-RTSP-Port")) {
|
||||||
|
int tmp = -1;
|
||||||
|
if (sscanf(r, "X-SATIP-RTSP-Port:%11d", &tmp) == 1) {
|
||||||
|
port = tmp;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
r = strtok_r(NULL, "\r\n", &s);
|
||||||
|
}
|
||||||
|
|
||||||
|
return port;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cSatipDiscover::ParseDeviceInfo(const char *addrP, const int portP)
|
||||||
|
{
|
||||||
|
debug1("%s (%s, %d)", __PRETTY_FUNCTION__, addrP, portP);
|
||||||
|
const char *desc = NULL, *model = NULL;
|
||||||
|
#ifdef USE_TINYXML
|
||||||
|
TiXmlDocument doc;
|
||||||
|
doc.Parse(dataBufferM.Data());
|
||||||
|
TiXmlHandle docHandle(&doc);
|
||||||
|
TiXmlElement *descElement = docHandle.FirstChild("root").FirstChild("device").FirstChild("friendlyName").ToElement();
|
||||||
|
if (descElement)
|
||||||
|
desc = descElement->GetText() ? descElement->GetText() : "MyBrokenHardware";
|
||||||
|
TiXmlElement *modelElement = docHandle.FirstChild("root").FirstChild("device").FirstChild("satip:X_SATIPCAP").ToElement();
|
||||||
|
if (modelElement)
|
||||||
|
model = modelElement->GetText() ? modelElement->GetText() : "DVBS2-1";
|
||||||
|
#else
|
||||||
|
pugi::xml_document doc;
|
||||||
|
if (doc.load_buffer(dataBufferM.Data(), dataBufferM.Size())) {
|
||||||
|
pugi::xml_node descNode = doc.first_element_by_path("root/device/friendlyName");
|
||||||
|
if (descNode)
|
||||||
|
desc = descNode.text().as_string("MyBrokenHardware");
|
||||||
|
pugi::xml_node modelNode = doc.first_element_by_path("root/device/satip:X_SATIPCAP");
|
||||||
|
if (modelNode)
|
||||||
|
model = modelNode.text().as_string("DVBS2-1");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
AddServer(addrP, portP, model, NULL, desc, cSatipServer::eSatipQuirkNone);
|
||||||
|
}
|
||||||
|
|
||||||
|
void cSatipDiscover::AddServer(const char *addrP, const int portP, const char *modelP, const char *filtersP, const char *descP, const int quirkP)
|
||||||
|
{
|
||||||
|
debug1("%s (%s, %d, %s, %s, %s, %d)", __PRETTY_FUNCTION__, addrP, portP, modelP, filtersP, descP, quirkP);
|
||||||
cMutexLock MutexLock(&mutexM);
|
cMutexLock MutexLock(&mutexM);
|
||||||
cSatipServer *tmp = new cSatipServer(addrP, modelP, descP);
|
if (SatipConfig.GetUseSingleModelServers() && modelP && !isempty(modelP)) {
|
||||||
// Validate against existing servers
|
int n = 0;
|
||||||
|
char *s, *p = strdup(modelP);
|
||||||
|
char *r = strtok_r(p, ",", &s);
|
||||||
|
while (r) {
|
||||||
|
r = skipspace(r);
|
||||||
|
cString desc = cString::sprintf("%s #%d", !isempty(descP) ? descP : "MyBrokenHardware", n++);
|
||||||
|
cSatipServer *tmp = new cSatipServer(addrP, portP, r, filtersP, desc, quirkP);
|
||||||
if (!serversM.Update(tmp)) {
|
if (!serversM.Update(tmp)) {
|
||||||
info("Adding server '%s|%s|%s'", tmp->Address(), tmp->Model(), tmp->Description());
|
info("Adding server '%s|%s|%s' Filters: %s CI: %s Quirks: %s", tmp->Address(), tmp->Model(), tmp->Description(), !isempty(tmp->Filters()) ? tmp->Filters() : "none", tmp->HasCI() ? "yes" : "no", tmp->HasQuirk() ? tmp->Quirks() : "none");
|
||||||
serversM.Add(tmp);
|
serversM.Add(tmp);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
DELETENULL(tmp);
|
DELETENULL(tmp);
|
||||||
|
r = strtok_r(NULL, ",", &s);
|
||||||
|
}
|
||||||
|
FREE_POINTER(p);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
cSatipServer *tmp = new cSatipServer(addrP, portP, modelP, filtersP, descP, quirkP);
|
||||||
|
if (!serversM.Update(tmp)) {
|
||||||
|
info("Adding server '%s|%s|%s' Filters: %s CI: %s Quirks: %s", tmp->Address(), tmp->Model(), tmp->Description(), !isempty(tmp->Filters()) ? tmp->Filters() : "none", tmp->HasCI() ? "yes" : "no", tmp->HasQuirk() ? tmp->Quirks() : "none");
|
||||||
|
serversM.Add(tmp);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
DELETENULL(tmp);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int cSatipDiscover::GetServerCount(void)
|
int cSatipDiscover::GetServerCount(void)
|
||||||
@@ -250,11 +314,18 @@ int cSatipDiscover::GetServerCount(void)
|
|||||||
return serversM.Count();
|
return serversM.Count();
|
||||||
}
|
}
|
||||||
|
|
||||||
cSatipServer *cSatipDiscover::GetServer(int sourceP, int transponderP, int systemP)
|
cSatipServer *cSatipDiscover::AssignServer(int deviceIdP, int sourceP, int transponderP, int systemP)
|
||||||
{
|
{
|
||||||
debug16("%s (%d, %d, %d)", __PRETTY_FUNCTION__, sourceP, transponderP, systemP);
|
debug16("%s (%d, %d, %d, %d)", __PRETTY_FUNCTION__, deviceIdP, sourceP, transponderP, systemP);
|
||||||
cMutexLock MutexLock(&mutexM);
|
cMutexLock MutexLock(&mutexM);
|
||||||
return serversM.Find(sourceP, transponderP, systemP);
|
return serversM.Assign(deviceIdP, sourceP, transponderP, systemP);
|
||||||
|
}
|
||||||
|
|
||||||
|
cSatipServer *cSatipDiscover::GetServer(int sourceP)
|
||||||
|
{
|
||||||
|
debug16("%s (%d)", __PRETTY_FUNCTION__, sourceP);
|
||||||
|
cMutexLock MutexLock(&mutexM);
|
||||||
|
return serversM.Find(sourceP);
|
||||||
}
|
}
|
||||||
|
|
||||||
cSatipServer *cSatipDiscover::GetServer(cSatipServer *serverP)
|
cSatipServer *cSatipDiscover::GetServer(cSatipServer *serverP)
|
||||||
@@ -285,18 +356,53 @@ cString cSatipDiscover::GetServerList(void)
|
|||||||
return serversM.List();
|
return serversM.List();
|
||||||
}
|
}
|
||||||
|
|
||||||
void cSatipDiscover::SetTransponder(cSatipServer *serverP, int transponderP)
|
void cSatipDiscover::ActivateServer(cSatipServer *serverP, bool onOffP)
|
||||||
{
|
|
||||||
debug16("%s (, %d)", __PRETTY_FUNCTION__, transponderP);
|
|
||||||
cMutexLock MutexLock(&mutexM);
|
|
||||||
serversM.SetTransponder(serverP, transponderP);
|
|
||||||
}
|
|
||||||
|
|
||||||
void cSatipDiscover::UseServer(cSatipServer *serverP, bool onOffP)
|
|
||||||
{
|
{
|
||||||
debug16("%s (, %d)", __PRETTY_FUNCTION__, onOffP);
|
debug16("%s (, %d)", __PRETTY_FUNCTION__, onOffP);
|
||||||
cMutexLock MutexLock(&mutexM);
|
cMutexLock MutexLock(&mutexM);
|
||||||
serversM.Use(serverP, onOffP);
|
serversM.Activate(serverP, onOffP);
|
||||||
|
}
|
||||||
|
|
||||||
|
void cSatipDiscover::AttachServer(cSatipServer *serverP, int deviceIdP, int transponderP)
|
||||||
|
{
|
||||||
|
debug16("%s (, %d, %d)", __PRETTY_FUNCTION__, deviceIdP, transponderP);
|
||||||
|
cMutexLock MutexLock(&mutexM);
|
||||||
|
serversM.Attach(serverP, deviceIdP, transponderP);
|
||||||
|
}
|
||||||
|
|
||||||
|
void cSatipDiscover::DetachServer(cSatipServer *serverP, int deviceIdP, int transponderP)
|
||||||
|
{
|
||||||
|
debug16("%s (, %d, %d)", __PRETTY_FUNCTION__, deviceIdP, transponderP);
|
||||||
|
cMutexLock MutexLock(&mutexM);
|
||||||
|
serversM.Detach(serverP, deviceIdP, transponderP);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool cSatipDiscover::IsServerQuirk(cSatipServer *serverP, int quirkP)
|
||||||
|
{
|
||||||
|
debug16("%s (, %d)", __PRETTY_FUNCTION__, quirkP);
|
||||||
|
cMutexLock MutexLock(&mutexM);
|
||||||
|
return serversM.IsQuirk(serverP, quirkP);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool cSatipDiscover::HasServerCI(cSatipServer *serverP)
|
||||||
|
{
|
||||||
|
debug16("%s", __PRETTY_FUNCTION__);
|
||||||
|
cMutexLock MutexLock(&mutexM);
|
||||||
|
return serversM.HasCI(serverP);
|
||||||
|
}
|
||||||
|
|
||||||
|
cString cSatipDiscover::GetServerAddress(cSatipServer *serverP)
|
||||||
|
{
|
||||||
|
debug16("%s", __PRETTY_FUNCTION__);
|
||||||
|
cMutexLock MutexLock(&mutexM);
|
||||||
|
return serversM.GetAddress(serverP);
|
||||||
|
}
|
||||||
|
|
||||||
|
int cSatipDiscover::GetServerPort(cSatipServer *serverP)
|
||||||
|
{
|
||||||
|
debug16("%s", __PRETTY_FUNCTION__);
|
||||||
|
cMutexLock MutexLock(&mutexM);
|
||||||
|
return serversM.GetPort(serverP);
|
||||||
}
|
}
|
||||||
|
|
||||||
int cSatipDiscover::NumProvidedSystems(void)
|
int cSatipDiscover::NumProvidedSystems(void)
|
||||||
|
|||||||
35
discover.h
35
discover.h
@@ -13,6 +13,7 @@
|
|||||||
#include <vdr/thread.h>
|
#include <vdr/thread.h>
|
||||||
#include <vdr/tools.h>
|
#include <vdr/tools.h>
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
#include "discoverif.h"
|
#include "discoverif.h"
|
||||||
#include "msearch.h"
|
#include "msearch.h"
|
||||||
#include "server.h"
|
#include "server.h"
|
||||||
@@ -20,16 +21,22 @@
|
|||||||
|
|
||||||
class cSatipDiscoverServer : public cListObject {
|
class cSatipDiscoverServer : public cListObject {
|
||||||
private:
|
private:
|
||||||
|
int ipPortM;
|
||||||
|
int quirkM;
|
||||||
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 *ipAddressP, const int ipPortP, const char *modelP, const char *filtersP, const char *descriptionP, const int quirkP)
|
||||||
{
|
{
|
||||||
ipAddressM = ipAddressP; modelM = modelP; descriptionM = descriptionP;
|
ipAddressM = ipAddressP; ipPortM = ipPortP; modelM = modelP; filtersM = filtersP; descriptionM = descriptionP; quirkM = quirkP;
|
||||||
}
|
}
|
||||||
|
int IpPort(void) { return ipPortM; }
|
||||||
|
int Quirk(void) { return quirkM; }
|
||||||
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; }
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -42,12 +49,16 @@ private:
|
|||||||
eSleepTimeoutMs = 500, // in milliseconds
|
eSleepTimeoutMs = 500, // in milliseconds
|
||||||
eConnectTimeoutMs = 1500, // in milliseconds
|
eConnectTimeoutMs = 1500, // in milliseconds
|
||||||
eProbeTimeoutMs = 2000, // in milliseconds
|
eProbeTimeoutMs = 2000, // in milliseconds
|
||||||
eProbeIntervalMs = 60000 // in milliseconds
|
eProbeIntervalMs = 60000, // in milliseconds
|
||||||
|
eCleanupTimeoutMs = 124000 // in milliseoonds
|
||||||
};
|
};
|
||||||
static cSatipDiscover *instanceS;
|
static cSatipDiscover *instanceS;
|
||||||
static size_t WriteCallback(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 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;
|
||||||
cSatipMsearch msearchM;
|
cSatipMsearch msearchM;
|
||||||
cStringList probeUrlListM;
|
cStringList probeUrlListM;
|
||||||
CURL *handleM;
|
CURL *handleM;
|
||||||
@@ -56,7 +67,9 @@ private:
|
|||||||
cSatipServers serversM;
|
cSatipServers serversM;
|
||||||
void Activate(void);
|
void Activate(void);
|
||||||
void Deactivate(void);
|
void Deactivate(void);
|
||||||
void AddServer(const char *addrP, const char *modelP, const char *descP);
|
int ParseRtspPort(void);
|
||||||
|
void ParseDeviceInfo(const char *addrP, const int portP);
|
||||||
|
void AddServer(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();
|
||||||
@@ -74,12 +87,18 @@ public:
|
|||||||
virtual ~cSatipDiscover();
|
virtual ~cSatipDiscover();
|
||||||
void TriggerScan(void) { probeIntervalM.Set(0); }
|
void TriggerScan(void) { probeIntervalM.Set(0); }
|
||||||
int GetServerCount(void);
|
int GetServerCount(void);
|
||||||
cSatipServer *GetServer(int sourceP, int transponderP = 0, int systemP = -1);
|
cSatipServer *AssignServer(int deviceIdP, int sourceP, int transponderP, int systemP);
|
||||||
|
cSatipServer *GetServer(int sourceP);
|
||||||
cSatipServer *GetServer(cSatipServer *serverP);
|
cSatipServer *GetServer(cSatipServer *serverP);
|
||||||
cSatipServers *GetServers(void);
|
cSatipServers *GetServers(void);
|
||||||
cString GetServerString(cSatipServer *serverP);
|
cString GetServerString(cSatipServer *serverP);
|
||||||
void SetTransponder(cSatipServer *serverP, int transponderP);
|
void ActivateServer(cSatipServer *serverP, bool onOffP);
|
||||||
void UseServer(cSatipServer *serverP, bool onOffP);
|
void AttachServer(cSatipServer *serverP, int deviceIdP, int transponderP);
|
||||||
|
void DetachServer(cSatipServer *serverP, int deviceIdP, int transponderP);
|
||||||
|
bool IsServerQuirk(cSatipServer *serverP, int quirkP);
|
||||||
|
bool HasServerCI(cSatipServer *serverP);
|
||||||
|
cString GetServerAddress(cSatipServer *serverP);
|
||||||
|
int GetServerPort(cSatipServer *serverP);
|
||||||
cString GetServerList(void);
|
cString GetServerList(void);
|
||||||
int NumProvidedSystems(void);
|
int NumProvidedSystems(void);
|
||||||
|
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ public:
|
|||||||
virtual void SetUrl(const char *urlP) = 0;
|
virtual void SetUrl(const char *urlP) = 0;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
cSatipDiscoverIf(const cSatipDiscoverIf&);
|
explicit cSatipDiscoverIf(const cSatipDiscoverIf&);
|
||||||
cSatipDiscoverIf& operator=(const cSatipDiscoverIf&);
|
cSatipDiscoverIf& operator=(const cSatipDiscoverIf&);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
7
log.h
7
log.h
@@ -32,11 +32,11 @@
|
|||||||
#define debug9(x...) void( SatipConfig.IsTraceMode(cSatipConfig::eTraceModeDebug9) ? dsyslog("SATIP9: " x) : void() )
|
#define debug9(x...) void( SatipConfig.IsTraceMode(cSatipConfig::eTraceModeDebug9) ? dsyslog("SATIP9: " x) : void() )
|
||||||
// 0x0200: RTCP packets
|
// 0x0200: RTCP packets
|
||||||
#define debug10(x...) void( SatipConfig.IsTraceMode(cSatipConfig::eTraceModeDebug10) ? dsyslog("SATIP10: " x) : void() )
|
#define debug10(x...) void( SatipConfig.IsTraceMode(cSatipConfig::eTraceModeDebug10) ? dsyslog("SATIP10: " x) : void() )
|
||||||
// 0x0400: TBD
|
// 0x0400: CI
|
||||||
#define debug11(x...) void( SatipConfig.IsTraceMode(cSatipConfig::eTraceModeDebug11) ? dsyslog("SATIP11: " x) : void() )
|
#define debug11(x...) void( SatipConfig.IsTraceMode(cSatipConfig::eTraceModeDebug11) ? dsyslog("SATIP11: " x) : void() )
|
||||||
// 0x0800: TBD
|
// 0x0800: Pids
|
||||||
#define debug12(x...) void( SatipConfig.IsTraceMode(cSatipConfig::eTraceModeDebug12) ? dsyslog("SATIP12: " x) : void() )
|
#define debug12(x...) void( SatipConfig.IsTraceMode(cSatipConfig::eTraceModeDebug12) ? dsyslog("SATIP12: " x) : void() )
|
||||||
// 0x1000: TBD
|
// 0x1000: Discovery
|
||||||
#define debug13(x...) void( SatipConfig.IsTraceMode(cSatipConfig::eTraceModeDebug13) ? dsyslog("SATIP13: " x) : void() )
|
#define debug13(x...) void( SatipConfig.IsTraceMode(cSatipConfig::eTraceModeDebug13) ? dsyslog("SATIP13: " x) : void() )
|
||||||
// 0x2000: TBD
|
// 0x2000: TBD
|
||||||
#define debug14(x...) void( SatipConfig.IsTraceMode(cSatipConfig::eTraceModeDebug14) ? dsyslog("SATIP14: " x) : void() )
|
#define debug14(x...) void( SatipConfig.IsTraceMode(cSatipConfig::eTraceModeDebug14) ? dsyslog("SATIP14: " x) : void() )
|
||||||
@@ -46,4 +46,3 @@
|
|||||||
#define debug16(x...) void( SatipConfig.IsTraceMode(cSatipConfig::eTraceModeDebug16) ? dsyslog("SATIP16: " x) : void() )
|
#define debug16(x...) void( SatipConfig.IsTraceMode(cSatipConfig::eTraceModeDebug16) ? dsyslog("SATIP16: " x) : void() )
|
||||||
|
|
||||||
#endif // __SATIP_LOG_H
|
#endif // __SATIP_LOG_H
|
||||||
|
|
||||||
|
|||||||
17
msearch.c
17
msearch.c
@@ -29,12 +29,13 @@ 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!");
|
||||||
}
|
}
|
||||||
|
|
||||||
cSatipMsearch::~cSatipMsearch()
|
cSatipMsearch::~cSatipMsearch()
|
||||||
{
|
{
|
||||||
|
FREE_POINTER(bufferM);
|
||||||
}
|
}
|
||||||
|
|
||||||
void cSatipMsearch::Probe(void)
|
void cSatipMsearch::Probe(void)
|
||||||
@@ -44,6 +45,9 @@ void cSatipMsearch::Probe(void)
|
|||||||
cSatipPoller::GetInstance()->Register(*this);
|
cSatipPoller::GetInstance()->Register(*this);
|
||||||
registeredM = true;
|
registeredM = true;
|
||||||
}
|
}
|
||||||
|
// Send two queries with one second interval
|
||||||
|
Write(bcastAddressS, reinterpret_cast<const unsigned char *>(bcastMessageS), strlen(bcastMessageS));
|
||||||
|
cCondWait::SleepMs(1000);
|
||||||
Write(bcastAddressS, reinterpret_cast<const unsigned char *>(bcastMessageS), strlen(bcastMessageS));
|
Write(bcastAddressS, reinterpret_cast<const unsigned char *>(bcastMessageS), strlen(bcastMessageS));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -59,12 +63,12 @@ void cSatipMsearch::Process(void)
|
|||||||
int length;
|
int length;
|
||||||
while ((length = Read(bufferM, bufferLenM)) > 0) {
|
while ((length = Read(bufferM, bufferLenM)) > 0) {
|
||||||
bufferM[min(length, int(bufferLenM - 1))] = 0;
|
bufferM[min(length, int(bufferLenM - 1))] = 0;
|
||||||
debug3("%s len=%d buf=%s", __PRETTY_FUNCTION__, length, bufferM);
|
debug13("%s len=%d buf=%s", __PRETTY_FUNCTION__, length, bufferM);
|
||||||
bool status = false, valid = false;
|
bool status = false, valid = false;
|
||||||
char *s, *p = reinterpret_cast<char *>(bufferM), *location = NULL;
|
char *s, *p = reinterpret_cast<char *>(bufferM), *location = NULL;
|
||||||
char *r = strtok_r(p, "\r\n", &s);
|
char *r = strtok_r(p, "\r\n", &s);
|
||||||
while (r) {
|
while (r) {
|
||||||
debug3("%s r=%s", __PRETTY_FUNCTION__, r);
|
debug13("%s r=%s", __PRETTY_FUNCTION__, r);
|
||||||
// Check the status code
|
// Check the status code
|
||||||
// HTTP/1.1 200 OK
|
// HTTP/1.1 200 OK
|
||||||
if (!status && startswith(r, "HTTP/1.1 200 OK"))
|
if (!status && startswith(r, "HTTP/1.1 200 OK"))
|
||||||
@@ -93,11 +97,14 @@ void cSatipMsearch::Process(void)
|
|||||||
r = strtok_r(NULL, "\r\n", &s);
|
r = strtok_r(NULL, "\r\n", &s);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (errno != EAGAIN && errno != EWOULDBLOCK)
|
|
||||||
error("Error %d reading in %s", errno, *ToString());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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";
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ private:
|
|||||||
bool registeredM;
|
bool registeredM;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
cSatipMsearch(cSatipDiscoverIf &discoverP);
|
explicit cSatipMsearch(cSatipDiscoverIf &discoverP);
|
||||||
virtual ~cSatipMsearch();
|
virtual ~cSatipMsearch();
|
||||||
void Probe(void);
|
void Probe(void);
|
||||||
|
|
||||||
@@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
358
param.c
358
param.c
@@ -147,15 +147,6 @@ cString GetTransponderUrlParameters(const cChannel *channelP)
|
|||||||
cDvbTransponderParameters dtp(channelP->Parameters());
|
cDvbTransponderParameters dtp(channelP->Parameters());
|
||||||
int DataSlice = 0;
|
int DataSlice = 0;
|
||||||
int C2TuningFrequencyType = 0;
|
int C2TuningFrequencyType = 0;
|
||||||
#if defined(APIVERSNUM) && APIVERSNUM < 20106
|
|
||||||
int Pilot = PILOT_AUTO;
|
|
||||||
int T2SystemId = 0;
|
|
||||||
int SisoMiso = 0;
|
|
||||||
#else
|
|
||||||
int Pilot = dtp.Pilot();
|
|
||||||
int T2SystemId = dtp.T2SystemId();
|
|
||||||
int SisoMiso = dtp.SisoMiso();
|
|
||||||
#endif
|
|
||||||
float freq = channelP->Frequency();
|
float freq = channelP->Frequency();
|
||||||
char type = cSource::ToChar(channelP->Source());
|
char type = cSource::ToChar(channelP->Source());
|
||||||
cSource *source = Sources.Get(channelP->Source());
|
cSource *source = Sources.Get(channelP->Source());
|
||||||
@@ -167,34 +158,349 @@ cString GetTransponderUrlParameters(const cChannel *channelP)
|
|||||||
freq /= 1000L;
|
freq /= 1000L;
|
||||||
#define ST(s) if (strchr(s, type) && (strchr(s, '0' + dtp.System() + 1) || strchr(s, '*')))
|
#define ST(s) if (strchr(s, type) && (strchr(s, '0' + dtp.System() + 1) || strchr(s, '*')))
|
||||||
#define STBUFLEFT (sizeof(buffer) - (q - buffer))
|
#define STBUFLEFT (sizeof(buffer) - (q - buffer))
|
||||||
|
ST(" S 1") { // to comply with SAT>IP protocol specification 1.2.2
|
||||||
|
dtp.SetPilot(PILOT_OFF);
|
||||||
|
dtp.SetModulation(QPSK);
|
||||||
|
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);
|
||||||
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", 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, 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 2") q += PrintUrlString(q, STBUFLEFT, Pilot, SatipPilotValues);
|
|
||||||
ST(" S 2") 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 2") 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() > 0)
|
ST(" S *") q += PrintUrlString(q, STBUFLEFT, dtp.Modulation(), SatipModulationValues);
|
||||||
q += snprintf(q, STBUFLEFT, "&fe=%d", channelP->Rid());
|
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
|
||||||
|
|||||||
72
po/ca_ES.po
72
po/ca_ES.po
@@ -1,14 +1,14 @@
|
|||||||
# VDR plugin language source file.
|
# VDR plugin language source file.
|
||||||
# Copyright (C) 2007-2014 Rolf Ahrenberg
|
# Copyright (C) 2007-2016 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
|
# Gabriel Bonich, 2014-2015
|
||||||
#
|
#
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: vdr-satip 1.0.0\n"
|
"Project-Id-Version: vdr-satip 2.3.0\n"
|
||||||
"Report-Msgid-Bugs-To: <see README>\n"
|
"Report-Msgid-Bugs-To: <see README>\n"
|
||||||
"POT-Creation-Date: 2014-12-24 12:24+0200\n"
|
"POT-Creation-Date: 2016-12-18 12:18+0200\n"
|
||||||
"PO-Revision-Date: 2014-12-24 12:24+0200\n"
|
"PO-Revision-Date: 2016-12-18 12:18+0200\n"
|
||||||
"Last-Translator: Gabriel Bonich <gbonich@gmail.com>\n"
|
"Last-Translator: Gabriel Bonich <gbonich@gmail.com>\n"
|
||||||
"Language-Team: Catalan <vdr@linuxtv.org>\n"
|
"Language-Team: Catalan <vdr@linuxtv.org>\n"
|
||||||
"Language: ca\n"
|
"Language: ca\n"
|
||||||
@@ -38,7 +38,7 @@ msgid "SAT>IP Devices"
|
|||||||
msgstr "SAT>IP Dispositius"
|
msgstr "SAT>IP Dispositius"
|
||||||
|
|
||||||
msgid "SAT>IP Server"
|
msgid "SAT>IP Server"
|
||||||
msgstr ""
|
msgstr "SAT>IP Server"
|
||||||
|
|
||||||
msgid "Address"
|
msgid "Address"
|
||||||
msgstr "Adressa"
|
msgstr "Adressa"
|
||||||
@@ -49,11 +49,14 @@ msgstr "Model"
|
|||||||
msgid "Description"
|
msgid "Description"
|
||||||
msgstr "Descripció"
|
msgstr "Descripció"
|
||||||
|
|
||||||
|
msgid "CI extension"
|
||||||
|
msgstr "Extensió CI"
|
||||||
|
|
||||||
msgid "Creation date"
|
msgid "Creation date"
|
||||||
msgstr "Creació de data"
|
msgstr "Creació de data"
|
||||||
|
|
||||||
msgid "SAT>IP Device Status"
|
msgid "SAT>IP Device Status"
|
||||||
msgstr ""
|
msgstr "SAT>IP Estat Dispositiu"
|
||||||
|
|
||||||
msgid "SAT>IP Information"
|
msgid "SAT>IP Information"
|
||||||
msgstr "SAT>IP Informació"
|
msgstr "SAT>IP Informació"
|
||||||
@@ -82,9 +85,18 @@ msgstr "Normal"
|
|||||||
msgid "high"
|
msgid "high"
|
||||||
msgstr "Alt"
|
msgstr "Alt"
|
||||||
|
|
||||||
msgid "Button$Devices"
|
msgid "Unicast"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Multicast"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "RTP-over-TCP"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Button$Devices"
|
||||||
|
msgstr "Dispositius"
|
||||||
|
|
||||||
msgid "Operating mode"
|
msgid "Operating mode"
|
||||||
msgstr "Mode de operació"
|
msgstr "Mode de operació"
|
||||||
|
|
||||||
@@ -96,13 +108,37 @@ msgid ""
|
|||||||
"normal - devices are working within normal parameters\n"
|
"normal - devices are working within normal parameters\n"
|
||||||
"high - devices are working at the highest priority"
|
"high - devices are working at the highest priority"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Defineig la manera de operar els Disposituis SAT>IP:\n"
|
"Defineig la manera de operar els Dispositius SAT>IP:\n"
|
||||||
"\n"
|
"\n"
|
||||||
"Apagat - Dispositius desactivats\n"
|
"Apagat - Dispositius desactivats\n"
|
||||||
"Baix - Dispositius treballan a baixa prioritat\n"
|
"Baix - Dispositius treballan a baixa prioritat\n"
|
||||||
"Normal - Dispositius treballan en parametres normals\n"
|
"Normal - Dispositius treballan en parametres normals\n"
|
||||||
"Alta - Dispositius treballan a prioritat Alta"
|
"Alta - Dispositius treballan a prioritat Alta"
|
||||||
|
|
||||||
|
msgid "Enable CI extension"
|
||||||
|
msgstr "Habilita la extenció CI"
|
||||||
|
|
||||||
|
msgid ""
|
||||||
|
"Define whether a CI extension shall be used.\n"
|
||||||
|
"\n"
|
||||||
|
"This setting enables integrated CI/CAM handling found in some SAT>IP hardware (e.g. Digital Devices OctopusNet)."
|
||||||
|
msgstr ""
|
||||||
|
"Definir si s'utilitzarà una extensió de CI.\n"
|
||||||
|
"\n"
|
||||||
|
"Aquesta configuració permet utilitzar CI/CAM integrat que es troba en alguns equips SAT>IP (ex. Digital Devices OctopusNet)."
|
||||||
|
|
||||||
|
msgid "CI/CAM"
|
||||||
|
msgstr "CI/CAM"
|
||||||
|
|
||||||
|
msgid ""
|
||||||
|
"Define a desired CAM type for the CI slot.\n"
|
||||||
|
"\n"
|
||||||
|
"The '---' option lets SAT>IP hardware do the auto-selection."
|
||||||
|
msgstr ""
|
||||||
|
"Definir quin tipus de CAM vols per a la ranura CI.\n"
|
||||||
|
"\n"
|
||||||
|
"L'opció '---' permet l'equip SAT>IP fer la selecció automàtica."
|
||||||
|
|
||||||
msgid "Enable EPG scanning"
|
msgid "Enable EPG scanning"
|
||||||
msgstr "Activa Escanneig EPG"
|
msgstr "Activa Escanneig EPG"
|
||||||
|
|
||||||
@@ -116,7 +152,7 @@ msgstr ""
|
|||||||
"Aquesta configuració desactiva la funcionalitat d'escaneig EIT automàtica per a tots els dispositius SAT>IP."
|
"Aquesta configuració desactiva la funcionalitat d'escaneig EIT automàtica per a tots els dispositius SAT>IP."
|
||||||
|
|
||||||
msgid "Disabled sources"
|
msgid "Disabled sources"
|
||||||
msgstr ""
|
msgstr "Desactiva entrades"
|
||||||
|
|
||||||
msgid "none"
|
msgid "none"
|
||||||
msgstr "no"
|
msgstr "no"
|
||||||
@@ -126,9 +162,12 @@ msgid ""
|
|||||||
"\n"
|
"\n"
|
||||||
"SAT>IP servers might not have all satellite positions available and such sources can be blacklisted here."
|
"SAT>IP servers might not have all satellite positions available and such sources can be blacklisted here."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
"Definir nombre de entrades que es desactiven.\n"
|
||||||
|
"\n"
|
||||||
|
"SAT>IP els servidors podrien no tenir totes les posicions dels satèl·lits disponibles i aquestes entrades poden ser la llista negra."
|
||||||
|
|
||||||
msgid "Define a source to be blacklisted."
|
msgid "Define a source to be blacklisted."
|
||||||
msgstr ""
|
msgstr "Definir una entrada a la llista negra"
|
||||||
|
|
||||||
msgid "Disabled filters"
|
msgid "Disabled filters"
|
||||||
msgstr "Desactiva filtres"
|
msgstr "Desactiva filtres"
|
||||||
@@ -148,8 +187,17 @@ 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 "Active SAT>IP servers:"
|
msgid "Transport mode"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid ""
|
||||||
|
"Define which transport mode shall be used.\n"
|
||||||
|
"\n"
|
||||||
|
"Unicast, Multicast, RTP-over-TCP"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Active SAT>IP servers:"
|
||||||
|
msgstr "Activa SAT>IP servers:"
|
||||||
|
|
||||||
msgid "Help"
|
msgid "Help"
|
||||||
msgstr "Ajuda"
|
msgstr "Ajuda"
|
||||||
|
|||||||
74
po/de_DE.po
74
po/de_DE.po
@@ -1,14 +1,14 @@
|
|||||||
# VDR plugin language source file.
|
# VDR plugin language source file.
|
||||||
# Copyright (C) 2007-2014 Rolf Ahrenberg
|
# Copyright (C) 2007-2016 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
|
# Frank Neumann, 2014-2016
|
||||||
#
|
#
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: vdr-satip 1.0.0\n"
|
"Project-Id-Version: vdr-satip 2.3.0\n"
|
||||||
"Report-Msgid-Bugs-To: <see README>\n"
|
"Report-Msgid-Bugs-To: <see README>\n"
|
||||||
"POT-Creation-Date: 2014-12-24 12:24+0200\n"
|
"POT-Creation-Date: 2016-12-18 12:18+0200\n"
|
||||||
"PO-Revision-Date: 2014-12-24 12:24+0200\n"
|
"PO-Revision-Date: 2016-12-18 12:18+0200\n"
|
||||||
"Last-Translator: Frank Neumann <fnu@yavdr.org>\n"
|
"Last-Translator: Frank Neumann <fnu@yavdr.org>\n"
|
||||||
"Language-Team: German <vdr@linuxtv.org>\n"
|
"Language-Team: German <vdr@linuxtv.org>\n"
|
||||||
"Language: de\n"
|
"Language: de\n"
|
||||||
@@ -49,6 +49,9 @@ msgstr "Modell"
|
|||||||
msgid "Description"
|
msgid "Description"
|
||||||
msgstr "Beschreibung"
|
msgstr "Beschreibung"
|
||||||
|
|
||||||
|
msgid "CI extension"
|
||||||
|
msgstr "CI Erweiterung"
|
||||||
|
|
||||||
msgid "Creation date"
|
msgid "Creation date"
|
||||||
msgstr "Zeitpunkt der Erstellung"
|
msgstr "Zeitpunkt der Erstellung"
|
||||||
|
|
||||||
@@ -82,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 ""
|
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"
|
||||||
@@ -96,13 +108,37 @@ 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"
|
||||||
"normal - Geräte arbeiten innerhalb der gewöhnlichen Parameter\n"
|
"normal - Geräte arbeiten innerhalb der gewöhnlichen Parameter\n"
|
||||||
"hoch - Geräte arbeiten mit höchste Priorität"
|
"hoch - Geräte arbeiten mit höchste Priorität"
|
||||||
|
|
||||||
|
msgid "Enable CI extension"
|
||||||
|
msgstr "Aktiviere CI Erweiterung"
|
||||||
|
|
||||||
|
msgid ""
|
||||||
|
"Define whether a CI extension shall be used.\n"
|
||||||
|
"\n"
|
||||||
|
"This setting enables integrated CI/CAM handling found in some SAT>IP hardware (e.g. Digital Devices OctopusNet)."
|
||||||
|
msgstr ""
|
||||||
|
"Legt fest ob eine CI Erweiterung genutzt werden soll.\n"
|
||||||
|
"\n"
|
||||||
|
"Diese Einstellung aktiviert die Nutzung des integrierten CI/CAM einiger SAT>IP Geräte (z.B. Digital Devices OctopusNet)."
|
||||||
|
|
||||||
|
msgid "CI/CAM"
|
||||||
|
msgstr "CI/CAM"
|
||||||
|
|
||||||
|
msgid ""
|
||||||
|
"Define a desired CAM type for the CI slot.\n"
|
||||||
|
"\n"
|
||||||
|
"The '---' option lets SAT>IP hardware do the auto-selection."
|
||||||
|
msgstr ""
|
||||||
|
"Bestimmt welcher CI Einschub für ein CAM genutzt werden soll.\n"
|
||||||
|
"\n"
|
||||||
|
"Die Option '---' überlässt der SAT>IP Hardware die automatische Auswahl."
|
||||||
|
|
||||||
msgid "Enable EPG scanning"
|
msgid "Enable EPG scanning"
|
||||||
msgstr "Aktiviere EPG Aktualisierung"
|
msgstr "Aktiviere EPG Aktualisierung"
|
||||||
|
|
||||||
@@ -111,7 +147,7 @@ msgid ""
|
|||||||
"\n"
|
"\n"
|
||||||
"This setting disables the automatic EIT scanning functionality for all SAT>IP devices."
|
"This setting disables the automatic EIT scanning functionality for all SAT>IP devices."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Definiert ob EPG im Hintergrund aktualisiert werden soll oder nicht.\n"
|
"Legt fest ob EPG im Hintergrund aktualisiert werden soll oder nicht.\n"
|
||||||
"\n"
|
"\n"
|
||||||
"Diese Einstellung schaltet die automatische EIT Aktualisierung für alle SAT>IP Geräte."
|
"Diese Einstellung schaltet die automatische EIT Aktualisierung für alle SAT>IP Geräte."
|
||||||
|
|
||||||
@@ -126,7 +162,7 @@ msgid ""
|
|||||||
"\n"
|
"\n"
|
||||||
"SAT>IP servers might not have all satellite positions available and such sources can be blacklisted here."
|
"SAT>IP servers might not have all satellite positions available and such sources can be blacklisted here."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Definiert die Anzahl der deaktivierten Quellen.\n"
|
"Legt die Anzahl der deaktivierten Quellen fest.\n"
|
||||||
"\n"
|
"\n"
|
||||||
"Für einige SAT>IP server sind nicht alle Satellitenpositionen verfügbar, nicht verfügbare Quellen können hier ausgeblendet werden"
|
"Für einige SAT>IP server sind nicht alle Satellitenpositionen verfügbar, nicht verfügbare Quellen können hier ausgeblendet werden"
|
||||||
|
|
||||||
@@ -143,16 +179,28 @@ 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:"
|
||||||
|
|
||||||
msgid "Help"
|
msgid "Help"
|
||||||
msgstr "Hilfe"
|
msgstr "Hilfe"
|
||||||
|
|||||||
70
po/es_ES.po
70
po/es_ES.po
@@ -1,14 +1,14 @@
|
|||||||
# VDR plugin language source file.
|
# VDR plugin language source file.
|
||||||
# Copyright (C) 2007-2014 Rolf Ahrenberg
|
# Copyright (C) 2007-2016 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
|
# Gabriel Bonich, 2014-2015
|
||||||
#
|
#
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: vdr-satip 1.0.0\n"
|
"Project-Id-Version: vdr-satip 2.3.0\n"
|
||||||
"Report-Msgid-Bugs-To: <see README>\n"
|
"Report-Msgid-Bugs-To: <see README>\n"
|
||||||
"POT-Creation-Date: 2014-12-24 12:24+0200\n"
|
"POT-Creation-Date: 2016-12-18 12:18+0200\n"
|
||||||
"PO-Revision-Date: 2014-12-24 12:24+0200\n"
|
"PO-Revision-Date: 2016-12-18 12:18+0200\n"
|
||||||
"Last-Translator: Gabriel Bonich <gbonich@gmail.com>\n"
|
"Last-Translator: Gabriel Bonich <gbonich@gmail.com>\n"
|
||||||
"Language-Team: Spanish <vdr@linuxtv.org>\n"
|
"Language-Team: Spanish <vdr@linuxtv.org>\n"
|
||||||
"Language: es\n"
|
"Language: es\n"
|
||||||
@@ -38,7 +38,7 @@ msgid "SAT>IP Devices"
|
|||||||
msgstr "SAT>IP Dispositivos"
|
msgstr "SAT>IP Dispositivos"
|
||||||
|
|
||||||
msgid "SAT>IP Server"
|
msgid "SAT>IP Server"
|
||||||
msgstr ""
|
msgstr "SAT>IP Server"
|
||||||
|
|
||||||
msgid "Address"
|
msgid "Address"
|
||||||
msgstr "Dirección"
|
msgstr "Dirección"
|
||||||
@@ -49,11 +49,14 @@ msgstr "Modelo"
|
|||||||
msgid "Description"
|
msgid "Description"
|
||||||
msgstr "Descripción"
|
msgstr "Descripción"
|
||||||
|
|
||||||
|
msgid "CI extension"
|
||||||
|
msgstr "Extensión CI"
|
||||||
|
|
||||||
msgid "Creation date"
|
msgid "Creation date"
|
||||||
msgstr "Fecha creación"
|
msgstr "Fecha creación"
|
||||||
|
|
||||||
msgid "SAT>IP Device Status"
|
msgid "SAT>IP Device Status"
|
||||||
msgstr ""
|
msgstr "SAT>IP Estado del Dispositivo"
|
||||||
|
|
||||||
msgid "SAT>IP Information"
|
msgid "SAT>IP Information"
|
||||||
msgstr "SAT>IP Información"
|
msgstr "SAT>IP Información"
|
||||||
@@ -82,9 +85,18 @@ msgstr "Normal"
|
|||||||
msgid "high"
|
msgid "high"
|
||||||
msgstr "Alto"
|
msgstr "Alto"
|
||||||
|
|
||||||
msgid "Button$Devices"
|
msgid "Unicast"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Multicast"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "RTP-over-TCP"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Button$Devices"
|
||||||
|
msgstr "Dispositivos"
|
||||||
|
|
||||||
msgid "Operating mode"
|
msgid "Operating mode"
|
||||||
msgstr "Modo de operación"
|
msgstr "Modo de operación"
|
||||||
|
|
||||||
@@ -103,6 +115,30 @@ msgstr ""
|
|||||||
"Normal - Dispositivos trabajando con prioridad Normal\n"
|
"Normal - Dispositivos trabajando con prioridad Normal\n"
|
||||||
"Alta - Dispositivos trabajando con prioridad Alta"
|
"Alta - Dispositivos trabajando con prioridad Alta"
|
||||||
|
|
||||||
|
msgid "Enable CI extension"
|
||||||
|
msgstr "Habilitar extensión CI"
|
||||||
|
|
||||||
|
msgid ""
|
||||||
|
"Define whether a CI extension shall be used.\n"
|
||||||
|
"\n"
|
||||||
|
"This setting enables integrated CI/CAM handling found in some SAT>IP hardware (e.g. Digital Devices OctopusNet)."
|
||||||
|
msgstr ""
|
||||||
|
"Definir si se utilizará una extensión de CI.\n"
|
||||||
|
"\n"
|
||||||
|
"Esto permite la configuración CI/CAM integrado que se encuentra en algunos equipos SAT>IP (ej. Digital Devices OctopusNet)."
|
||||||
|
|
||||||
|
msgid "CI/CAM"
|
||||||
|
msgstr "CI/CAM"
|
||||||
|
|
||||||
|
msgid ""
|
||||||
|
"Define a desired CAM type for the CI slot.\n"
|
||||||
|
"\n"
|
||||||
|
"The '---' option lets SAT>IP hardware do the auto-selection."
|
||||||
|
msgstr ""
|
||||||
|
"Definir el tipo de CAM para la ranura CI.\n"
|
||||||
|
"\n"
|
||||||
|
"La opción '---' permite al equipo SAT>IP hacer la selección automática."
|
||||||
|
|
||||||
msgid "Enable EPG scanning"
|
msgid "Enable EPG scanning"
|
||||||
msgstr "Activa Escaneo EPG"
|
msgstr "Activa Escaneo EPG"
|
||||||
|
|
||||||
@@ -116,7 +152,7 @@ msgstr ""
|
|||||||
"Esta configuración desactiva la funcionalidad del escaneo EIT automática para todos los Dispositivos SAT>IP."
|
"Esta configuración desactiva la funcionalidad del escaneo EIT automática para todos los Dispositivos SAT>IP."
|
||||||
|
|
||||||
msgid "Disabled sources"
|
msgid "Disabled sources"
|
||||||
msgstr ""
|
msgstr "Desactiva fuentes"
|
||||||
|
|
||||||
msgid "none"
|
msgid "none"
|
||||||
msgstr "no"
|
msgstr "no"
|
||||||
@@ -126,9 +162,12 @@ msgid ""
|
|||||||
"\n"
|
"\n"
|
||||||
"SAT>IP servers might not have all satellite positions available and such sources can be blacklisted here."
|
"SAT>IP servers might not have all satellite positions available and such sources can be blacklisted here."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
"Definir número de fuentes desactivadas.\n"
|
||||||
|
"\n"
|
||||||
|
"SAT>IP servidores que no tenga todas las posiciones de los satélites disponibles y estas se ponen en la lista negra."
|
||||||
|
|
||||||
msgid "Define a source to be blacklisted."
|
msgid "Define a source to be blacklisted."
|
||||||
msgstr ""
|
msgstr "Define fuentes de la lista negra"
|
||||||
|
|
||||||
msgid "Disabled filters"
|
msgid "Disabled filters"
|
||||||
msgstr "Desactiva filtros"
|
msgstr "Desactiva filtros"
|
||||||
@@ -148,8 +187,17 @@ 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 "Active SAT>IP servers:"
|
msgid "Transport mode"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid ""
|
||||||
|
"Define which transport mode shall be used.\n"
|
||||||
|
"\n"
|
||||||
|
"Unicast, Multicast, RTP-over-TCP"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Active SAT>IP servers:"
|
||||||
|
msgstr "Activa SAT>IP servers:"
|
||||||
|
|
||||||
msgid "Help"
|
msgid "Help"
|
||||||
msgstr "Ayuda"
|
msgstr "Ayuda"
|
||||||
|
|||||||
58
po/fi_FI.po
58
po/fi_FI.po
@@ -1,14 +1,14 @@
|
|||||||
# VDR plugin language source file.
|
# VDR plugin language source file.
|
||||||
# Copyright (C) 2007-2014 Rolf Ahrenberg
|
# Copyright (C) 2007-2016 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, 2014
|
# Rolf Ahrenberg, 2015-2016
|
||||||
#
|
#
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: vdr-satip 1.0.0\n"
|
"Project-Id-Version: vdr-satip 2.3.0\n"
|
||||||
"Report-Msgid-Bugs-To: <see README>\n"
|
"Report-Msgid-Bugs-To: <see README>\n"
|
||||||
"POT-Creation-Date: 2014-12-24 12:24+0200\n"
|
"POT-Creation-Date: 2016-12-18 12:18+0200\n"
|
||||||
"PO-Revision-Date: 2014-12-24 12:24+0200\n"
|
"PO-Revision-Date: 2016-12-18 12:18+0200\n"
|
||||||
"Last-Translator: Rolf Ahrenberg\n"
|
"Last-Translator: Rolf Ahrenberg\n"
|
||||||
"Language-Team: Finnish <vdr@linuxtv.org>\n"
|
"Language-Team: Finnish <vdr@linuxtv.org>\n"
|
||||||
"Language: fi\n"
|
"Language: fi\n"
|
||||||
@@ -49,6 +49,9 @@ msgstr "Malli"
|
|||||||
msgid "Description"
|
msgid "Description"
|
||||||
msgstr "Kuvaus"
|
msgstr "Kuvaus"
|
||||||
|
|
||||||
|
msgid "CI extension"
|
||||||
|
msgstr "CI-laajennos"
|
||||||
|
|
||||||
msgid "Creation date"
|
msgid "Creation date"
|
||||||
msgstr "Luontiajankohta"
|
msgstr "Luontiajankohta"
|
||||||
|
|
||||||
@@ -82,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"
|
||||||
|
|
||||||
@@ -102,6 +114,30 @@ msgstr ""
|
|||||||
"normaali - laitteet toimivat normaalilla prioriteetilla\n"
|
"normaali - laitteet toimivat normaalilla prioriteetilla\n"
|
||||||
"korkea - laitteet toimivat korkealla prioriteetilla"
|
"korkea - laitteet toimivat korkealla prioriteetilla"
|
||||||
|
|
||||||
|
msgid "Enable CI extension"
|
||||||
|
msgstr "Käytä CI-laajennosta"
|
||||||
|
|
||||||
|
msgid ""
|
||||||
|
"Define whether a CI extension shall be used.\n"
|
||||||
|
"\n"
|
||||||
|
"This setting enables integrated CI/CAM handling found in some SAT>IP hardware (e.g. Digital Devices OctopusNet)."
|
||||||
|
msgstr ""
|
||||||
|
"Määrittele CI-laajennoksen käyttöönotto\n"
|
||||||
|
"\n"
|
||||||
|
"Tällä asetuksella saadaan otettua käyttöön SAT>IP-laitteiden sisäinen CI-paikka (esim. Digital Devices OctopusNet)."
|
||||||
|
|
||||||
|
msgid "CI/CAM"
|
||||||
|
msgstr "CI/CAM"
|
||||||
|
|
||||||
|
msgid ""
|
||||||
|
"Define a desired CAM type for the CI slot.\n"
|
||||||
|
"\n"
|
||||||
|
"The '---' option lets SAT>IP hardware do the auto-selection."
|
||||||
|
msgstr ""
|
||||||
|
"Määrittele haluttu CAM-tyyppi CI-paikalle.\n"
|
||||||
|
"\n"
|
||||||
|
"Vaihtoehto '---' antaa SAT>IP-laitteen valita automaattisesti käytetyn CI-paikan."
|
||||||
|
|
||||||
msgid "Enable EPG scanning"
|
msgid "Enable EPG scanning"
|
||||||
msgstr "Käytä ohjelmaoppaan taustapäivitystä"
|
msgstr "Käytä ohjelmaoppaan taustapäivitystä"
|
||||||
|
|
||||||
@@ -150,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:"
|
||||||
|
|
||||||
|
|||||||
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,10 +14,11 @@ 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:
|
||||||
cSatipPollerIf(const cSatipPollerIf&);
|
explicit cSatipPollerIf(const cSatipPollerIf&);
|
||||||
cSatipPollerIf& operator=(const cSatipPollerIf&);
|
cSatipPollerIf& operator=(const cSatipPollerIf&);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
18
rtcp.c
18
rtcp.c
@@ -25,7 +25,7 @@ cSatipRtcp::cSatipRtcp(cSatipTunerIf &tunerP)
|
|||||||
cSatipRtcp::~cSatipRtcp()
|
cSatipRtcp::~cSatipRtcp()
|
||||||
{
|
{
|
||||||
debug1("%s [device %d]", __PRETTY_FUNCTION__, tunerM.GetId());
|
debug1("%s [device %d]", __PRETTY_FUNCTION__, tunerM.GetId());
|
||||||
DELETE_POINTER(bufferM);
|
FREE_POINTER(bufferM);
|
||||||
}
|
}
|
||||||
|
|
||||||
int cSatipRtcp::GetFd(void)
|
int cSatipRtcp::GetFd(void)
|
||||||
@@ -36,7 +36,7 @@ int cSatipRtcp::GetFd(void)
|
|||||||
|
|
||||||
int cSatipRtcp::GetApplicationOffset(int *lengthP)
|
int cSatipRtcp::GetApplicationOffset(int *lengthP)
|
||||||
{
|
{
|
||||||
debug16("%s (%d) [device %d]", __PRETTY_FUNCTION__, *lengthP, tunerM.GetId());
|
debug16("%s (%d) [device %d]", __PRETTY_FUNCTION__, lengthP ? *lengthP : -1, tunerM.GetId());
|
||||||
if (!lengthP)
|
if (!lengthP)
|
||||||
return -1;
|
return -1;
|
||||||
int offset = 0;
|
int offset = 0;
|
||||||
@@ -50,7 +50,7 @@ int cSatipRtcp::GetApplicationOffset(int *lengthP)
|
|||||||
//unsigned int st = bufferM[offset] & 0x1F;
|
//unsigned int st = bufferM[offset] & 0x1F;
|
||||||
// Payload type
|
// Payload type
|
||||||
unsigned int pt = bufferM[offset + 1] & 0xFF;
|
unsigned int pt = bufferM[offset + 1] & 0xFF;
|
||||||
// Lenght
|
// Length
|
||||||
unsigned int length = ((bufferM[offset + 2] & 0xFF) << 8) | (bufferM[offset + 3] & 0xFF);
|
unsigned int length = ((bufferM[offset + 2] & 0xFF) << 8) | (bufferM[offset + 3] & 0xFF);
|
||||||
// Convert it to bytes
|
// Convert it to bytes
|
||||||
length = (length + 1) * 4;
|
length = (length + 1) * 4;
|
||||||
@@ -89,8 +89,16 @@ void cSatipRtcp::Process(void)
|
|||||||
if (offset >= 0)
|
if (offset >= 0)
|
||||||
tunerM.ProcessApplicationData(bufferM + offset, length);
|
tunerM.ProcessApplicationData(bufferM + offset, length);
|
||||||
}
|
}
|
||||||
if (errno != EAGAIN && errno != EWOULDBLOCK)
|
}
|
||||||
error("Error %d reading in %s", errno, *ToString());
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
5
rtcp.h
5
rtcp.h
@@ -20,16 +20,17 @@ private:
|
|||||||
cSatipTunerIf &tunerM;
|
cSatipTunerIf &tunerM;
|
||||||
unsigned int bufferLenM;
|
unsigned int bufferLenM;
|
||||||
unsigned char *bufferM;
|
unsigned char *bufferM;
|
||||||
int GetApplicationOffset(int *lenghtP);
|
int GetApplicationOffset(int *lengthP);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
cSatipRtcp(cSatipTunerIf &tunerP);
|
explicit cSatipRtcp(cSatipTunerIf &tunerP);
|
||||||
virtual ~cSatipRtcp();
|
virtual ~cSatipRtcp();
|
||||||
|
|
||||||
// for internal poller interface
|
// for internal poller interface
|
||||||
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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
27
rtp.c
27
rtp.c
@@ -29,7 +29,7 @@ cSatipRtp::cSatipRtp(cSatipTunerIf &tunerP)
|
|||||||
cSatipRtp::~cSatipRtp()
|
cSatipRtp::~cSatipRtp()
|
||||||
{
|
{
|
||||||
debug1("%s [device %d]", __PRETTY_FUNCTION__, tunerM.GetId());
|
debug1("%s [device %d]", __PRETTY_FUNCTION__, tunerM.GetId());
|
||||||
DELETE_POINTER(bufferM);
|
FREE_POINTER(bufferM);
|
||||||
}
|
}
|
||||||
|
|
||||||
int cSatipRtp::GetFd(void)
|
int cSatipRtp::GetFd(void)
|
||||||
@@ -51,7 +51,7 @@ void cSatipRtp::Close(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int cSatipRtp::GetHeaderLenght(unsigned char *bufferP, unsigned int lengthP)
|
int cSatipRtp::GetHeaderLength(unsigned char *bufferP, unsigned int lengthP)
|
||||||
{
|
{
|
||||||
debug16("%s (, %d) [device %d]", __PRETTY_FUNCTION__, lengthP, tunerM.GetId());
|
debug16("%s (, %d) [device %d]", __PRETTY_FUNCTION__, lengthP, tunerM.GetId());
|
||||||
unsigned int headerlen = 0;
|
unsigned int headerlen = 0;
|
||||||
@@ -88,7 +88,7 @@ int cSatipRtp::GetHeaderLenght(unsigned char *bufferP, unsigned int lengthP)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
sequenceNumberM = seq;
|
sequenceNumberM = seq;
|
||||||
// Header lenght
|
// Header length
|
||||||
headerlen = (3 + cc) * (unsigned int)sizeof(uint32_t);
|
headerlen = (3 + cc) * (unsigned int)sizeof(uint32_t);
|
||||||
// Check if extension
|
// Check if extension
|
||||||
if (x) {
|
if (x) {
|
||||||
@@ -130,21 +130,34 @@ void cSatipRtp::Process(void)
|
|||||||
count = ReadMulti(bufferM, lenMsg, eRtpPacketReadCount, eMaxUdpPacketSizeB);
|
count = ReadMulti(bufferM, lenMsg, eRtpPacketReadCount, eMaxUdpPacketSizeB);
|
||||||
for (int i = 0; i < count; ++i) {
|
for (int i = 0; i < count; ++i) {
|
||||||
unsigned char *p = &bufferM[i * eMaxUdpPacketSizeB];
|
unsigned char *p = &bufferM[i * eMaxUdpPacketSizeB];
|
||||||
int headerlen = GetHeaderLenght(p, lenMsg[i]);
|
int headerlen = GetHeaderLength(p, lenMsg[i]);
|
||||||
if ((headerlen >= 0) && (headerlen < (int)lenMsg[i]))
|
if ((headerlen >= 0) && (headerlen < (int)lenMsg[i]))
|
||||||
tunerM.ProcessVideoData(p + headerlen, lenMsg[i] - headerlen);
|
tunerM.ProcessVideoData(p + headerlen, lenMsg[i] - headerlen);
|
||||||
}
|
}
|
||||||
} while (count >= eRtpPacketReadCount);
|
} while (count >= eRtpPacketReadCount);
|
||||||
|
|
||||||
if (errno != EAGAIN && errno != EWOULDBLOCK)
|
|
||||||
error("Error %d reading in %s [device %d]", errno, *ToString(), tunerM.GetId());
|
|
||||||
|
|
||||||
elapsed = processing.Elapsed();
|
elapsed = processing.Elapsed();
|
||||||
if (elapsed > 1)
|
if (elapsed > 1)
|
||||||
debug6("%s %d read(s) took %" PRIu64 " ms [device %d]", __PRETTY_FUNCTION__, count, elapsed, tunerM.GetId());
|
debug6("%s %d read(s) took %" PRIu64 " ms [device %d]", __PRETTY_FUNCTION__, count, elapsed, tunerM.GetId());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void cSatipRtp::Process(unsigned char *dataP, int lengthP)
|
||||||
|
{
|
||||||
|
debug16("%s [device %d]", __PRETTY_FUNCTION__, tunerM.GetId());
|
||||||
|
if (dataP && lengthP > 0) {
|
||||||
|
uint64_t elapsed;
|
||||||
|
cTimeMs processing(0);
|
||||||
|
int headerlen = GetHeaderLength(dataP, lengthP);
|
||||||
|
if ((headerlen >= 0) && (headerlen < lengthP))
|
||||||
|
tunerM.ProcessVideoData(dataP + headerlen, lengthP - headerlen);
|
||||||
|
|
||||||
|
elapsed = processing.Elapsed();
|
||||||
|
if (elapsed > 1)
|
||||||
|
debug6("%s %d read(s) took %" PRIu64 " ms [device %d]", __PRETTY_FUNCTION__, lengthP, elapsed, tunerM.GetId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
cString cSatipRtp::ToString(void) const
|
cString cSatipRtp::ToString(void) const
|
||||||
{
|
{
|
||||||
return cString::sprintf("RTP [device %d]", tunerM.GetId());
|
return cString::sprintf("RTP [device %d]", tunerM.GetId());
|
||||||
|
|||||||
5
rtp.h
5
rtp.h
@@ -25,10 +25,10 @@ private:
|
|||||||
time_t lastErrorReportM;
|
time_t lastErrorReportM;
|
||||||
int packetErrorsM;
|
int packetErrorsM;
|
||||||
int sequenceNumberM;
|
int sequenceNumberM;
|
||||||
int GetHeaderLenght(unsigned char *bufferP, unsigned int lengthP);
|
int GetHeaderLength(unsigned char *bufferP, unsigned int lengthP);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
cSatipRtp(cSatipTunerIf &tunerP);
|
explicit cSatipRtp(cSatipTunerIf &tunerP);
|
||||||
virtual ~cSatipRtp();
|
virtual ~cSatipRtp();
|
||||||
virtual void Close(void);
|
virtual void Close(void);
|
||||||
|
|
||||||
@@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
292
rtsp.c
292
rtsp.c
@@ -15,9 +15,16 @@
|
|||||||
|
|
||||||
cSatipRtsp::cSatipRtsp(cSatipTunerIf &tunerP)
|
cSatipRtsp::cSatipRtsp(cSatipTunerIf &tunerP)
|
||||||
: tunerM(tunerP),
|
: tunerM(tunerP),
|
||||||
modeM(cmUnicast),
|
headerBufferM(),
|
||||||
|
dataBufferM(),
|
||||||
handleM(NULL),
|
handleM(NULL),
|
||||||
headerListM(NULL)
|
headerListM(NULL),
|
||||||
|
errorNoMoreM(""),
|
||||||
|
errorOutOfRangeM(""),
|
||||||
|
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();
|
||||||
@@ -29,46 +36,50 @@ cSatipRtsp::~cSatipRtsp()
|
|||||||
Destroy();
|
Destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t cSatipRtsp::HeaderCallback(void *ptrP, size_t sizeP, size_t nmembP, void *dataP)
|
size_t cSatipRtsp::HeaderCallback(char *ptrP, size_t sizeP, size_t nmembP, void *dataP)
|
||||||
{
|
|
||||||
cSatipRtsp *obj = reinterpret_cast<cSatipRtsp *>(dataP);
|
|
||||||
size_t len = sizeP * nmembP;
|
|
||||||
debug16("%s len=%zu", __PRETTY_FUNCTION__, len);
|
|
||||||
|
|
||||||
char *s, *p = (char *)ptrP;
|
|
||||||
char *r = strtok_r(p, "\r\n", &s);
|
|
||||||
|
|
||||||
while (obj && r) {
|
|
||||||
debug16("%s (%zu): %s", __PRETTY_FUNCTION__, len, r);
|
|
||||||
r = skipspace(r);
|
|
||||||
if (strstr(r, "com.ses.streamID")) {
|
|
||||||
int streamid = -1;
|
|
||||||
if (sscanf(r, "com.ses.streamID:%11d", &streamid) == 1)
|
|
||||||
obj->tunerM.SetStreamId(streamid);
|
|
||||||
}
|
|
||||||
else if (strstr(r, "Session:")) {
|
|
||||||
int timeout = -1;
|
|
||||||
char *session = NULL;
|
|
||||||
if (sscanf(r, "Session:%m[^;];timeout=%11d", &session, &timeout) == 2)
|
|
||||||
obj->tunerM.SetSessionTimeout(skipspace(session), timeout * 1000);
|
|
||||||
else if (sscanf(r, "Session:%m[^;]", &session) == 1)
|
|
||||||
obj->tunerM.SetSessionTimeout(skipspace(session), -1);
|
|
||||||
FREE_POINTER(session);
|
|
||||||
}
|
|
||||||
r = strtok_r(NULL, "\r\n", &s);
|
|
||||||
}
|
|
||||||
|
|
||||||
return len;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t cSatipRtsp::WriteCallback(void *ptrP, size_t sizeP, size_t nmembP, void *dataP)
|
|
||||||
{
|
{
|
||||||
cSatipRtsp *obj = reinterpret_cast<cSatipRtsp *>(dataP);
|
cSatipRtsp *obj = reinterpret_cast<cSatipRtsp *>(dataP);
|
||||||
size_t len = sizeP * nmembP;
|
size_t len = sizeP * nmembP;
|
||||||
debug16("%s len=%zu", __PRETTY_FUNCTION__, len);
|
debug16("%s len=%zu", __PRETTY_FUNCTION__, len);
|
||||||
|
|
||||||
if (obj && (len > 0))
|
if (obj && (len > 0))
|
||||||
obj->tunerM.ProcessApplicationData((u_char*)ptrP, len);
|
obj->headerBufferM.Add(ptrP, len);
|
||||||
|
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t cSatipRtsp::DataCallback(char *ptrP, size_t sizeP, size_t nmembP, void *dataP)
|
||||||
|
{
|
||||||
|
cSatipRtsp *obj = reinterpret_cast<cSatipRtsp *>(dataP);
|
||||||
|
size_t len = sizeP * nmembP;
|
||||||
|
debug16("%s len=%zu", __PRETTY_FUNCTION__, len);
|
||||||
|
|
||||||
|
if (obj)
|
||||||
|
obj->dataBufferM.Add(ptrP, len);
|
||||||
|
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t cSatipRtsp::InterleaveCallback(char *ptrP, size_t sizeP, size_t nmembP, void *dataP)
|
||||||
|
{
|
||||||
|
cSatipRtsp *obj = reinterpret_cast<cSatipRtsp *>(dataP);
|
||||||
|
size_t len = sizeP * nmembP;
|
||||||
|
debug16("%s len=%zu", __PRETTY_FUNCTION__, len);
|
||||||
|
|
||||||
|
if (obj && ptrP && len > 0) {
|
||||||
|
char tag = ptrP[0] & 0xFF;
|
||||||
|
if (tag == '$') {
|
||||||
|
int count = ((ptrP[2] & 0xFF) << 8) | (ptrP[3] & 0xFF);
|
||||||
|
if (count > 0) {
|
||||||
|
unsigned int channel = ptrP[1] & 0xFF;
|
||||||
|
u_char *data = (u_char *)&ptrP[4];
|
||||||
|
if (channel == obj->interleavedRtpIdM)
|
||||||
|
obj->tunerM.ProcessRtpData(data, count);
|
||||||
|
else if (channel == obj->interleavedRtcpIdM)
|
||||||
|
obj->tunerM.ProcessRtcpData(data, count);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
@@ -102,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());
|
||||||
@@ -138,6 +164,9 @@ void cSatipRtsp::Create(void)
|
|||||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_TIMEOUT_MS, (long)eConnectTimeoutMs);
|
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_TIMEOUT_MS, (long)eConnectTimeoutMs);
|
||||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_CONNECTTIMEOUT_MS, (long)eConnectTimeoutMs);
|
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_CONNECTTIMEOUT_MS, (long)eConnectTimeoutMs);
|
||||||
|
|
||||||
|
// Limit download speed (bytes/s)
|
||||||
|
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_MAX_RECV_SPEED_LARGE, eMaxDownloadSpeedMBits * 131072L);
|
||||||
|
|
||||||
// Set user-agent
|
// Set user-agent
|
||||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_USERAGENT, *cString::sprintf("vdr-%s/%s (device %d)", PLUGIN_NAME_I18N, VERSION, tunerM.GetId()));
|
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_USERAGENT, *cString::sprintf("vdr-%s/%s (device %d)", PLUGIN_NAME_I18N, VERSION, tunerM.GetId()));
|
||||||
}
|
}
|
||||||
@@ -186,9 +215,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)) {
|
||||||
@@ -197,14 +226,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;
|
||||||
}
|
}
|
||||||
@@ -216,10 +248,25 @@ bool cSatipRtsp::Setup(const char *uriP, int rtpPortP, int rtcpPortP)
|
|||||||
// Set header callback for catching the session and timeout
|
// Set header callback for catching the session and timeout
|
||||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_HEADERFUNCTION, cSatipRtsp::HeaderCallback);
|
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_HEADERFUNCTION, cSatipRtsp::HeaderCallback);
|
||||||
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_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);
|
||||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEHEADER, NULL);
|
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEHEADER, NULL);
|
||||||
|
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEFUNCTION, NULL);
|
||||||
|
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEDATA, NULL);
|
||||||
|
if (headerBufferM.Size() > 0) {
|
||||||
|
ParseHeader();
|
||||||
|
headerBufferM.Reset();
|
||||||
|
}
|
||||||
|
if (dataBufferM.Size() > 0) {
|
||||||
|
ParseData();
|
||||||
|
dataBufferM.Reset();
|
||||||
|
}
|
||||||
|
|
||||||
result = ValidateLatestResponse(&rc);
|
result = ValidateLatestResponse(&rc);
|
||||||
debug5("%s (%s, %d, %d) Response %ld in %" PRIu64 " ms [device %d]", __PRETTY_FUNCTION__, uriP, rtpPortP, rtcpPortP, rc, processing.Elapsed(), tunerM.GetId());
|
debug5("%s (%s, %d, %d) Response %ld in %" PRIu64 " ms [device %d]", __PRETTY_FUNCTION__, uriP, rtpPortP, rtcpPortP, rc, processing.Elapsed(), tunerM.GetId());
|
||||||
@@ -253,11 +300,15 @@ bool cSatipRtsp::Describe(const char *uriP)
|
|||||||
|
|
||||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_RTSP_STREAM_URI, uriP);
|
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_RTSP_STREAM_URI, uriP);
|
||||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_RTSP_REQUEST, (long)CURL_RTSPREQ_DESCRIBE);
|
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_RTSP_REQUEST, (long)CURL_RTSPREQ_DESCRIBE);
|
||||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEFUNCTION, cSatipRtsp::WriteCallback);
|
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_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);
|
||||||
|
if (dataBufferM.Size() > 0) {
|
||||||
|
tunerM.ProcessApplicationData((u_char *)dataBufferM.Data(), dataBufferM.Size());
|
||||||
|
dataBufferM.Reset();
|
||||||
|
}
|
||||||
|
|
||||||
result = ValidateLatestResponse(&rc);
|
result = ValidateLatestResponse(&rc);
|
||||||
debug5("%s (%s) Response %ld in %" PRIu64 " ms [device %d]", __PRETTY_FUNCTION__, uriP, rc, processing.Elapsed(), tunerM.GetId());
|
debug5("%s (%s) Response %ld in %" PRIu64 " ms [device %d]", __PRETTY_FUNCTION__, uriP, rc, processing.Elapsed(), tunerM.GetId());
|
||||||
@@ -278,7 +329,15 @@ bool cSatipRtsp::Play(const char *uriP)
|
|||||||
|
|
||||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_RTSP_STREAM_URI, uriP);
|
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_RTSP_STREAM_URI, uriP);
|
||||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_RTSP_REQUEST, (long)CURL_RTSPREQ_PLAY);
|
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_RTSP_REQUEST, (long)CURL_RTSPREQ_PLAY);
|
||||||
|
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEFUNCTION, cSatipRtsp::DataCallback);
|
||||||
|
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEDATA, this);
|
||||||
SATIP_CURL_EASY_PERFORM(handleM);
|
SATIP_CURL_EASY_PERFORM(handleM);
|
||||||
|
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEFUNCTION, NULL);
|
||||||
|
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEDATA, NULL);
|
||||||
|
if (dataBufferM.Size() > 0) {
|
||||||
|
ParseData();
|
||||||
|
dataBufferM.Reset();
|
||||||
|
}
|
||||||
|
|
||||||
result = ValidateLatestResponse(&rc);
|
result = ValidateLatestResponse(&rc);
|
||||||
debug5("%s (%s) Response %ld in %" PRIu64 " ms [device %d]", __PRETTY_FUNCTION__, uriP, rc, processing.Elapsed(), tunerM.GetId());
|
debug5("%s (%s) Response %ld in %" PRIu64 " ms [device %d]", __PRETTY_FUNCTION__, uriP, rc, processing.Elapsed(), tunerM.GetId());
|
||||||
@@ -299,7 +358,17 @@ bool cSatipRtsp::Teardown(const char *uriP)
|
|||||||
|
|
||||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_RTSP_STREAM_URI, uriP);
|
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_RTSP_STREAM_URI, uriP);
|
||||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_RTSP_REQUEST, (long)CURL_RTSPREQ_TEARDOWN);
|
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_RTSP_REQUEST, (long)CURL_RTSPREQ_TEARDOWN);
|
||||||
|
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEFUNCTION, cSatipRtsp::DataCallback);
|
||||||
|
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEDATA, this);
|
||||||
|
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_INTERLEAVEFUNCTION, NULL);
|
||||||
|
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_INTERLEAVEDATA, NULL);
|
||||||
SATIP_CURL_EASY_PERFORM(handleM);
|
SATIP_CURL_EASY_PERFORM(handleM);
|
||||||
|
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEFUNCTION, NULL);
|
||||||
|
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEDATA, NULL);
|
||||||
|
if (dataBufferM.Size() > 0) {
|
||||||
|
ParseData();
|
||||||
|
dataBufferM.Reset();
|
||||||
|
}
|
||||||
|
|
||||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_RTSP_CLIENT_CSEQ, 1L);
|
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_RTSP_CLIENT_CSEQ, 1L);
|
||||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_RTSP_SESSION_ID, NULL);
|
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_RTSP_SESSION_ID, NULL);
|
||||||
@@ -311,24 +380,153 @@ bool cSatipRtsp::Teardown(const char *uriP)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void cSatipRtsp::ParseHeader(void)
|
||||||
|
{
|
||||||
|
debug1("%s [device %d]", __PRETTY_FUNCTION__, tunerM.GetId());
|
||||||
|
char *s, *p = headerBufferM.Data();
|
||||||
|
char *r = strtok_r(p, "\r\n", &s);
|
||||||
|
|
||||||
|
while (r) {
|
||||||
|
debug16("%s (%zu): %s", __PRETTY_FUNCTION__, headerBufferM.Size(), r);
|
||||||
|
r = skipspace(r);
|
||||||
|
if (strstr(r, "com.ses.streamID")) {
|
||||||
|
int streamid = -1;
|
||||||
|
if (sscanf(r, "com.ses.streamID:%11d", &streamid) == 1)
|
||||||
|
tunerM.SetStreamId(streamid);
|
||||||
|
}
|
||||||
|
else if (strstr(r, "Session:")) {
|
||||||
|
int timeout = -1;
|
||||||
|
char *session = NULL;
|
||||||
|
if (sscanf(r, "Session:%m[^;];timeout=%11d", &session, &timeout) == 2)
|
||||||
|
tunerM.SetSessionTimeout(skipspace(session), timeout * 1000);
|
||||||
|
else if (sscanf(r, "Session:%m[^;]", &session) == 1)
|
||||||
|
tunerM.SetSessionTimeout(skipspace(session), -1);
|
||||||
|
FREE_POINTER(session);
|
||||||
|
}
|
||||||
|
else if (strstr(r, "Transport:")) {
|
||||||
|
CURLcode res = CURLE_OK;
|
||||||
|
int rtp = -1, rtcp = -1, ttl = -1;
|
||||||
|
char *tmp = NULL, *destination = NULL, *source = NULL;
|
||||||
|
interleavedRtpIdM = 0;
|
||||||
|
interleavedRtcpIdM = 1;
|
||||||
|
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_INTERLEAVEFUNCTION, NULL);
|
||||||
|
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_INTERLEAVEDATA, NULL);
|
||||||
|
if (sscanf(r, "Transport:%m[^;];unicast;client_port=%11d-%11d", &tmp, &rtp, &rtcp) == 3) {
|
||||||
|
modeM = cSatipConfig::eTransportModeUnicast;
|
||||||
|
tunerM.SetupTransport(rtp, rtcp, NULL, NULL);
|
||||||
|
}
|
||||||
|
else if (sscanf(r, "Transport:%m[^;];multicast;destination=%m[^;];port=%11d-%11d;ttl=%11d;source=%m[^;]", &tmp, &destination, &rtp, &rtcp, &ttl, &source) == 6 ||
|
||||||
|
sscanf(r, "Transport:%m[^;];multicast;destination=%m[^;];port=%11d-%11d;ttl=%11d", &tmp, &destination, &rtp, &rtcp, &ttl) == 5) {
|
||||||
|
modeM = cSatipConfig::eTransportModeMulticast;
|
||||||
|
tunerM.SetupTransport(rtp, rtcp, destination, source);
|
||||||
|
}
|
||||||
|
else if (sscanf(r, "Transport:%m[^;];interleaved=%11d-%11d", &tmp, &rtp, &rtcp) == 3) {
|
||||||
|
interleavedRtpIdM = rtp;
|
||||||
|
interleavedRtcpIdM = rtcp;
|
||||||
|
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_INTERLEAVEFUNCTION, cSatipRtsp::InterleaveCallback);
|
||||||
|
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_INTERLEAVEDATA, this);
|
||||||
|
modeM = cSatipConfig::eTransportModeRtpOverTcp;
|
||||||
|
tunerM.SetupTransport(-1, -1, NULL, NULL);
|
||||||
|
}
|
||||||
|
FREE_POINTER(tmp);
|
||||||
|
FREE_POINTER(destination);
|
||||||
|
FREE_POINTER(source);
|
||||||
|
}
|
||||||
|
r = strtok_r(NULL, "\r\n", &s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void cSatipRtsp::ParseData(void)
|
||||||
|
{
|
||||||
|
debug1("%s [device %d]", __PRETTY_FUNCTION__, tunerM.GetId());
|
||||||
|
char *s, *p = dataBufferM.Data();
|
||||||
|
char *r = strtok_r(p, "\r\n", &s);
|
||||||
|
|
||||||
|
while (r) {
|
||||||
|
debug16("%s (%zu): %s", __PRETTY_FUNCTION__, dataBufferM.Size(), r);
|
||||||
|
r = skipspace(r);
|
||||||
|
if (strstr(r, "No-More:")) {
|
||||||
|
char *tmp = NULL;
|
||||||
|
if (sscanf(r, "No-More:%m[^;]", &tmp) == 1) {
|
||||||
|
errorNoMoreM = skipspace(tmp);
|
||||||
|
debug3("%s No-More: %s [device %d]", __PRETTY_FUNCTION__, *errorNoMoreM, tunerM.GetId());
|
||||||
|
}
|
||||||
|
FREE_POINTER(tmp);
|
||||||
|
}
|
||||||
|
else if (strstr(r, "Out-of-Range:")) {
|
||||||
|
char *tmp = NULL;
|
||||||
|
if (sscanf(r, "Out-of-Range:%m[^;]", &tmp) == 1) {
|
||||||
|
errorOutOfRangeM = skipspace(tmp);
|
||||||
|
debug3("%s Out-of-Range: %s [device %d]", __PRETTY_FUNCTION__, *errorOutOfRangeM, tunerM.GetId());
|
||||||
|
}
|
||||||
|
FREE_POINTER(tmp);
|
||||||
|
}
|
||||||
|
else if (strstr(r, "Check-Syntax:")) {
|
||||||
|
char *tmp = NULL;
|
||||||
|
if (sscanf(r, "Check-Syntax:%m[^;]", &tmp) == 1) {
|
||||||
|
errorCheckSyntaxM = skipspace(tmp);
|
||||||
|
debug3("%s Check-Syntax: %s [device %d]", __PRETTY_FUNCTION__, *errorCheckSyntaxM, tunerM.GetId());
|
||||||
|
}
|
||||||
|
FREE_POINTER(tmp);
|
||||||
|
}
|
||||||
|
r = strtok_r(NULL, "\r\n", &s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool cSatipRtsp::ValidateLatestResponse(long *rcP)
|
bool cSatipRtsp::ValidateLatestResponse(long *rcP)
|
||||||
{
|
{
|
||||||
bool result = false;
|
bool result = false;
|
||||||
|
|
||||||
if (handleM) {
|
if (handleM) {
|
||||||
|
char *url = NULL;
|
||||||
long rc = 0;
|
long rc = 0;
|
||||||
CURLcode res = CURLE_OK;
|
CURLcode res = CURLE_OK;
|
||||||
SATIP_CURL_EASY_GETINFO(handleM, CURLINFO_RESPONSE_CODE, &rc);
|
SATIP_CURL_EASY_GETINFO(handleM, CURLINFO_RESPONSE_CODE, &rc);
|
||||||
if (rc == 200)
|
switch (rc) {
|
||||||
|
case 200:
|
||||||
result = true;
|
result = true;
|
||||||
else if (rc != 0) {
|
break;
|
||||||
char *url = NULL;
|
case 400:
|
||||||
|
// SETUP PLAY TEARDOWN
|
||||||
|
// The message body of the response may contain the "Check-Syntax:" parameter followed
|
||||||
|
// by the malformed syntax
|
||||||
|
if (!isempty(*errorCheckSyntaxM)) {
|
||||||
|
SATIP_CURL_EASY_GETINFO(handleM, CURLINFO_EFFECTIVE_URL, &url);
|
||||||
|
error("Check syntax: %s (error code %ld: %s) [device %d]", *errorCheckSyntaxM, rc, url, tunerM.GetId());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 403:
|
||||||
|
// SETUP PLAY TEARDOWN
|
||||||
|
// The message body of the response may contain the "Out-of-Range:" parameter followed
|
||||||
|
// by a space-separated list of the attribute names that are not understood:
|
||||||
|
// "src" "fe" "freq" "pol" "msys" "mtype" "plts" "ro" "sr" "fec" "pids" "addpids" "delpids" "mcast"
|
||||||
|
if (!isempty(*errorOutOfRangeM)) {
|
||||||
|
SATIP_CURL_EASY_GETINFO(handleM, CURLINFO_EFFECTIVE_URL, &url);
|
||||||
|
error("Out of range: %s (error code %ld: %s) [device %d]", *errorOutOfRangeM, rc, url, tunerM.GetId());
|
||||||
|
// Reseting the connection wouldn't help anything due to invalid channel configuration, so let it be successful
|
||||||
|
result = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 503:
|
||||||
|
// SETUP PLAY
|
||||||
|
// The message body of the response may contain the "No-More:" parameter followed
|
||||||
|
// by a space-separated list of the missing ressources: “sessions” "frontends" "pids
|
||||||
|
if (!isempty(*errorNoMoreM)) {
|
||||||
|
SATIP_CURL_EASY_GETINFO(handleM, CURLINFO_EFFECTIVE_URL, &url);
|
||||||
|
error("No more: %s (error code %ld: %s) [device %d]", *errorNoMoreM, rc, url, tunerM.GetId());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
SATIP_CURL_EASY_GETINFO(handleM, CURLINFO_EFFECTIVE_URL, &url);
|
SATIP_CURL_EASY_GETINFO(handleM, CURLINFO_EFFECTIVE_URL, &url);
|
||||||
error("Detected invalid status code %ld: %s [device %d]", rc, url, tunerM.GetId());
|
error("Detected invalid status code %ld: %s [device %d]", rc, url, tunerM.GetId());
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
if (rcP)
|
if (rcP)
|
||||||
*rcP = rc;
|
*rcP = rc;
|
||||||
}
|
}
|
||||||
|
errorNoMoreM = "";
|
||||||
|
errorOutOfRangeM = "";
|
||||||
|
errorCheckSyntaxM = "";
|
||||||
debug1("%s result=%s [device %d]", __PRETTY_FUNCTION__, result ? "ok" : "failed", tunerM.GetId());
|
debug1("%s result=%s [device %d]", __PRETTY_FUNCTION__, result ? "ok" : "failed", tunerM.GetId());
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
|||||||
24
rtsp.h
24
rtsp.h
@@ -15,26 +15,37 @@
|
|||||||
#error "libcurl is missing required RTSP support"
|
#error "libcurl is missing required RTSP support"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
#include "tunerif.h"
|
#include "tunerif.h"
|
||||||
|
|
||||||
class cSatipRtsp {
|
class cSatipRtsp {
|
||||||
private:
|
private:
|
||||||
static size_t HeaderCallback(void *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 WriteCallback(void *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
|
||||||
|
eMaxDownloadSpeedMBits = 20, // in megabits per second
|
||||||
};
|
};
|
||||||
enum eCommunicationMode { cmUnicast, cmMulticast };
|
|
||||||
|
|
||||||
cSatipTunerIf &tunerM;
|
cSatipTunerIf &tunerM;
|
||||||
eCommunicationMode modeM;
|
cSatipMemoryBuffer headerBufferM;
|
||||||
|
cSatipMemoryBuffer dataBufferM;
|
||||||
CURL *handleM;
|
CURL *handleM;
|
||||||
struct curl_slist *headerListM;
|
struct curl_slist *headerListM;
|
||||||
|
cString errorNoMoreM;
|
||||||
|
cString errorOutOfRangeM;
|
||||||
|
cString errorCheckSyntaxM;
|
||||||
|
int modeM;
|
||||||
|
unsigned int interleavedRtpIdM;
|
||||||
|
unsigned int interleavedRtcpIdM;
|
||||||
|
|
||||||
void Create(void);
|
void Create(void);
|
||||||
void Destroy(void);
|
void Destroy(void);
|
||||||
|
void ParseHeader(void);
|
||||||
|
void ParseData(void);
|
||||||
bool ValidateLatestResponse(long *rcP);
|
bool ValidateLatestResponse(long *rcP);
|
||||||
|
|
||||||
// to prevent copy constructor and assignment
|
// to prevent copy constructor and assignment
|
||||||
@@ -42,13 +53,14 @@ private:
|
|||||||
cSatipRtsp& operator=(const cSatipRtsp&);
|
cSatipRtsp& operator=(const cSatipRtsp&);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
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 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);
|
||||||
|
|||||||
185
satip.c
185
satip.c
@@ -19,15 +19,15 @@
|
|||||||
#warning "CURL version >= 7.36.0 is recommended"
|
#warning "CURL version >= 7.36.0 is recommended"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(APIVERSNUM) && APIVERSNUM < 20000
|
#if defined(APIVERSNUM) && APIVERSNUM < 20301
|
||||||
#error "VDR-2.0.0 API version or greater is required!"
|
#error "VDR-2.3.1 API version or greater is required!"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef GITVERSION
|
#ifndef GITVERSION
|
||||||
#define GITVERSION ""
|
#define GITVERSION ""
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
const char VERSION[] = "1.0.0" GITVERSION;
|
const char VERSION[] = "2.3.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 +35,8 @@ 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 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);
|
||||||
public:
|
public:
|
||||||
@@ -61,7 +63,7 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
cPluginSatip::cPluginSatip(void)
|
cPluginSatip::cPluginSatip(void)
|
||||||
: deviceCountM(1),
|
: deviceCountM(2),
|
||||||
serversM(NULL)
|
serversM(NULL)
|
||||||
{
|
{
|
||||||
debug16("%s", __PRETTY_FUNCTION__);
|
debug16("%s", __PRETTY_FUNCTION__);
|
||||||
@@ -81,8 +83,14 @@ const char *cPluginSatip::CommandLineHelp(void)
|
|||||||
debug1("%s", __PRETTY_FUNCTION__);
|
debug1("%s", __PRETTY_FUNCTION__);
|
||||||
// Return a string that describes all known command line options.
|
// Return a string that describes all known command line options.
|
||||||
return " -d <num>, --devices=<number> set number of devices to be created\n"
|
return " -d <num>, --devices=<number> set number of devices to be created\n"
|
||||||
" -s <ipaddr>|<model>|<desc>, --server=<ipaddr1>|<model1>|<desc1>;<ipaddr2>|<model2>|<desc2>\n"
|
" -t <mode>, --trace=<mode> set the tracing mode\n"
|
||||||
" define hard-coded SAT>IP server(s)\n";
|
" -s <ipaddr>|<model>|<desc>, --server=<ipaddr1>|<model1>|<desc1>;<ipaddr2>:<port>|<model2>:<filter>|<desc2>:<quirk>\n"
|
||||||
|
" define hard-coded SAT>IP server(s)\n"
|
||||||
|
" -D, --detach set the detached mode on\n"
|
||||||
|
" -S, --single set the single model server mode on\n"
|
||||||
|
" -n, --noquirks disable autodetection of the server quirks\n"
|
||||||
|
" -p, --portrange=<start>-<end> set a range of ports used for the RT[C]P server\n"
|
||||||
|
" a minimum of 2 ports per device is required.\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
bool cPluginSatip::ProcessArgs(int argc, char *argv[])
|
bool cPluginSatip::ProcessArgs(int argc, char *argv[])
|
||||||
@@ -93,11 +101,17 @@ 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' },
|
||||||
|
{ "detach", no_argument, NULL, 'D' },
|
||||||
|
{ "single", no_argument, NULL, 'S' },
|
||||||
|
{ "noquirks", no_argument, NULL, 'n' },
|
||||||
{ NULL, no_argument, NULL, 0 }
|
{ NULL, no_argument, NULL, 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
cString server;
|
||||||
|
cString portrange;
|
||||||
int c;
|
int c;
|
||||||
while ((c = getopt_long(argc, argv, "d:t:s:", long_options, NULL)) != -1) {
|
while ((c = getopt_long(argc, argv, "d:t:s:p:DSn", long_options, NULL)) != -1) {
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case 'd':
|
case 'd':
|
||||||
deviceCountM = strtol(optarg, NULL, 0);
|
deviceCountM = strtol(optarg, NULL, 0);
|
||||||
@@ -106,12 +120,29 @@ bool cPluginSatip::ProcessArgs(int argc, char *argv[])
|
|||||||
SatipConfig.SetTraceMode(strtol(optarg, NULL, 0));
|
SatipConfig.SetTraceMode(strtol(optarg, NULL, 0));
|
||||||
break;
|
break;
|
||||||
case 's':
|
case 's':
|
||||||
ParseServer(optarg);
|
server = optarg;
|
||||||
|
break;
|
||||||
|
case 'D':
|
||||||
|
SatipConfig.SetDetachedMode(true);
|
||||||
|
break;
|
||||||
|
case 'S':
|
||||||
|
SatipConfig.SetUseSingleModelServers(true);
|
||||||
|
break;
|
||||||
|
case 'n':
|
||||||
|
SatipConfig.SetDisableServerQuirks(true);
|
||||||
|
break;
|
||||||
|
case 'p':
|
||||||
|
portrange = optarg;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (!isempty(*portrange))
|
||||||
|
ParsePortRange(portrange);
|
||||||
|
// this must be done after all parameters are parsed
|
||||||
|
if (!isempty(*server))
|
||||||
|
ParseServer(*server);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -121,7 +152,6 @@ bool cPluginSatip::Initialize(void)
|
|||||||
// Initialize any background activities the plugin shall perform.
|
// Initialize any background activities the plugin shall perform.
|
||||||
if (curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK)
|
if (curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK)
|
||||||
error("Unable to initialize CURL");
|
error("Unable to initialize CURL");
|
||||||
SatipConfig.SetConfigDirectory(cPlugin::ResourceDirectory(PLUGIN_NAME_I18N));
|
|
||||||
cSatipPoller::GetInstance()->Initialize();
|
cSatipPoller::GetInstance()->Initialize();
|
||||||
cSatipDiscover::GetInstance()->Initialize(serversM);
|
cSatipDiscover::GetInstance()->Initialize(serversM);
|
||||||
return cSatipDevice::Initialize(deviceCountM);
|
return cSatipDevice::Initialize(deviceCountM);
|
||||||
@@ -197,12 +227,14 @@ void cPluginSatip::ParseServer(const char *paramP)
|
|||||||
{
|
{
|
||||||
debug1("%s (%s)", __PRETTY_FUNCTION__, paramP);
|
debug1("%s (%s)", __PRETTY_FUNCTION__, paramP);
|
||||||
int n = 0;
|
int n = 0;
|
||||||
char *s, *p = (char *)paramP;
|
char *s, *p = strdup(paramP);
|
||||||
char *r = strtok_r(p, ";", &s);
|
char *r = strtok_r(p, ";", &s);
|
||||||
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 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);
|
||||||
@@ -210,13 +242,34 @@ 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:
|
||||||
|
{
|
||||||
serverAddr = r2;
|
serverAddr = r2;
|
||||||
|
char *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;
|
||||||
@@ -224,21 +277,71 @@ 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 ipaddr=%s port=%d model=%s (%s) desc=%s (%d)", __PRETTY_FUNCTION__, *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(*serverAddr, serverPort, *serverModel, *serverFilters, *serverDescription, serverQuirk));
|
||||||
}
|
}
|
||||||
++n;
|
++n;
|
||||||
r = strtok_r(NULL, ";", &s);
|
r = strtok_r(NULL, ";", &s);
|
||||||
}
|
}
|
||||||
|
FREE_POINTER(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
void cPluginSatip::ParsePortRange(const char *paramP)
|
||||||
|
{
|
||||||
|
char *s, *p = skipspace(paramP);
|
||||||
|
char *r = strtok_r(p, "-", &s);
|
||||||
|
unsigned int rangeStart = 0;
|
||||||
|
unsigned int rangeStop = 0;
|
||||||
|
if (r) {
|
||||||
|
rangeStart = strtol(r, NULL, 0);
|
||||||
|
r = strtok_r(NULL, "-", &s);
|
||||||
|
}
|
||||||
|
if (r)
|
||||||
|
rangeStop = strtol(r, NULL, 0);
|
||||||
|
else {
|
||||||
|
error("Port range argument not valid '%s'", paramP);
|
||||||
|
rangeStart = 0;
|
||||||
|
rangeStop = 0;
|
||||||
|
}
|
||||||
|
if (rangeStart % 2) {
|
||||||
|
error("The given range start port must be even!");
|
||||||
|
rangeStart = 0;
|
||||||
|
rangeStop = 0;
|
||||||
|
}
|
||||||
|
else if (rangeStop - rangeStart + 1 < deviceCountM * 2) {
|
||||||
|
error("The given port range is to small: %d < %d!", rangeStop - rangeStart + 1, deviceCountM * 2);
|
||||||
|
rangeStart = 0;
|
||||||
|
rangeStop = 0;
|
||||||
|
}
|
||||||
|
SatipConfig.SetPortRangeStart(rangeStart);
|
||||||
|
SatipConfig.SetPortRangeStop(rangeStop);
|
||||||
|
}
|
||||||
|
|
||||||
|
int cPluginSatip::ParseCicams(const char *valueP, int *cicamsP)
|
||||||
|
{
|
||||||
|
debug1("%s (%s,)", __PRETTY_FUNCTION__, valueP);
|
||||||
|
int n = 0;
|
||||||
|
char *s, *p = strdup(valueP);
|
||||||
|
char *r = strtok_r(p, " ", &s);
|
||||||
|
while (r) {
|
||||||
|
r = skipspace(r);
|
||||||
|
debug3("%s cicams[%d]=%s", __PRETTY_FUNCTION__, n, r);
|
||||||
|
if (n < MAX_CICAM_COUNT) {
|
||||||
|
cicamsP[n++] = atoi(r);
|
||||||
|
}
|
||||||
|
r = strtok_r(NULL, " ", &s);
|
||||||
|
}
|
||||||
|
FREE_POINTER(p);
|
||||||
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
int cPluginSatip::ParseSources(const char *valueP, int *sourcesP)
|
int cPluginSatip::ParseSources(const char *valueP, int *sourcesP)
|
||||||
{
|
{
|
||||||
debug1("%s (%s,)", __PRETTY_FUNCTION__, valueP);
|
debug1("%s (%s,)", __PRETTY_FUNCTION__, valueP);
|
||||||
int n = 0;
|
int n = 0;
|
||||||
char *s, *p = (char *)valueP;
|
char *s, *p = strdup(valueP);
|
||||||
char *r = strtok_r(p, " ", &s);
|
char *r = strtok_r(p, " ", &s);
|
||||||
while (r) {
|
while (r) {
|
||||||
r = skipspace(r);
|
r = skipspace(r);
|
||||||
@@ -246,8 +349,9 @@ int cPluginSatip::ParseSources(const char *valueP, int *sourcesP)
|
|||||||
if (n < MAX_DISABLED_SOURCES_COUNT) {
|
if (n < MAX_DISABLED_SOURCES_COUNT) {
|
||||||
sourcesP[n++] = cSource::FromString(r);
|
sourcesP[n++] = cSource::FromString(r);
|
||||||
}
|
}
|
||||||
r = strtok_r(NULL, " \n", &s);
|
r = strtok_r(NULL, " ", &s);
|
||||||
}
|
}
|
||||||
|
FREE_POINTER(p);
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -259,7 +363,7 @@ int cPluginSatip::ParseFilters(const char *valueP, int *filtersP)
|
|||||||
while (valueP && *valueP && (n < SECTION_FILTER_TABLE_SIZE)) {
|
while (valueP && *valueP && (n < SECTION_FILTER_TABLE_SIZE)) {
|
||||||
strn0cpy(buffer, valueP, sizeof(buffer));
|
strn0cpy(buffer, valueP, sizeof(buffer));
|
||||||
int i = atoi(buffer);
|
int i = atoi(buffer);
|
||||||
debug3(":%s filters[%d]=%d", __PRETTY_FUNCTION__, n, i);
|
debug3("%s filters[%d]=%d", __PRETTY_FUNCTION__, n, i);
|
||||||
if (i >= 0)
|
if (i >= 0)
|
||||||
filtersP[n++] = i;
|
filtersP[n++] = i;
|
||||||
if ((valueP = strchr(valueP, ' ')) != NULL)
|
if ((valueP = strchr(valueP, ' ')) != NULL)
|
||||||
@@ -274,11 +378,21 @@ bool cPluginSatip::SetupParse(const char *nameP, const char *valueP)
|
|||||||
// Parse your own setup parameters and store their values.
|
// Parse your own setup parameters and store their values.
|
||||||
if (!strcasecmp(nameP, "OperatingMode"))
|
if (!strcasecmp(nameP, "OperatingMode"))
|
||||||
SatipConfig.SetOperatingMode(atoi(valueP));
|
SatipConfig.SetOperatingMode(atoi(valueP));
|
||||||
|
else if (!strcasecmp(nameP, "EnableCIExtension"))
|
||||||
|
SatipConfig.SetCIExtension(atoi(valueP));
|
||||||
|
else if (!strcasecmp(nameP, "CICAM")) {
|
||||||
|
int Cicams[MAX_CICAM_COUNT];
|
||||||
|
for (unsigned int i = 0; i < ELEMENTS(Cicams); ++i)
|
||||||
|
Cicams[i] = 0;
|
||||||
|
unsigned int CicamsCount = ParseCicams(valueP, Cicams);
|
||||||
|
for (unsigned int i = 0; i < CicamsCount; ++i)
|
||||||
|
SatipConfig.SetCICAM(i, Cicams[i]);
|
||||||
|
}
|
||||||
else if (!strcasecmp(nameP, "EnableEITScan"))
|
else if (!strcasecmp(nameP, "EnableEITScan"))
|
||||||
SatipConfig.SetEITScan(atoi(valueP));
|
SatipConfig.SetEITScan(atoi(valueP));
|
||||||
else if (!strcasecmp(nameP, "DisabledSources")) {
|
else if (!strcasecmp(nameP, "DisabledSources")) {
|
||||||
int DisabledSources[MAX_DISABLED_SOURCES_COUNT];
|
int DisabledSources[MAX_DISABLED_SOURCES_COUNT];
|
||||||
for (unsigned int i = 0; i < ARRAY_SIZE(DisabledSources); ++i)
|
for (unsigned int i = 0; i < ELEMENTS(DisabledSources); ++i)
|
||||||
DisabledSources[i] = cSource::stNone;
|
DisabledSources[i] = cSource::stNone;
|
||||||
unsigned int DisabledSourcesCount = ParseSources(valueP, DisabledSources);
|
unsigned int DisabledSourcesCount = ParseSources(valueP, DisabledSources);
|
||||||
for (unsigned int i = 0; i < DisabledSourcesCount; ++i)
|
for (unsigned int i = 0; i < DisabledSourcesCount; ++i)
|
||||||
@@ -286,12 +400,14 @@ bool cPluginSatip::SetupParse(const char *nameP, const char *valueP)
|
|||||||
}
|
}
|
||||||
else if (!strcasecmp(nameP, "DisabledFilters")) {
|
else if (!strcasecmp(nameP, "DisabledFilters")) {
|
||||||
int DisabledFilters[SECTION_FILTER_TABLE_SIZE];
|
int DisabledFilters[SECTION_FILTER_TABLE_SIZE];
|
||||||
for (unsigned int i = 0; i < ARRAY_SIZE(DisabledFilters); ++i)
|
for (unsigned int i = 0; i < ELEMENTS(DisabledFilters); ++i)
|
||||||
DisabledFilters[i] = -1;
|
DisabledFilters[i] = -1;
|
||||||
unsigned int DisabledFiltersCount = ParseFilters(valueP, DisabledFilters);
|
unsigned int DisabledFiltersCount = ParseFilters(valueP, DisabledFilters);
|
||||||
for (unsigned int i = 0; i < DisabledFiltersCount; ++i)
|
for (unsigned int i = 0; i < DisabledFiltersCount; ++i)
|
||||||
SatipConfig.SetDisabledFilters(i, DisabledFilters[i]);
|
SatipConfig.SetDisabledFilters(i, DisabledFilters[i]);
|
||||||
}
|
}
|
||||||
|
else if (!strcasecmp(nameP, "TransportMode"))
|
||||||
|
SatipConfig.SetTransportMode(atoi(valueP));
|
||||||
else
|
else
|
||||||
return false;
|
return false;
|
||||||
return true;
|
return true;
|
||||||
@@ -321,8 +437,12 @@ const char **cPluginSatip::SVDRPHelpPages(void)
|
|||||||
" Lists status information of SAT>IP devices.\n",
|
" Lists status information of SAT>IP devices.\n",
|
||||||
"CONT\n"
|
"CONT\n"
|
||||||
" Shows SAT>IP device count.\n",
|
" Shows SAT>IP device count.\n",
|
||||||
"OPER\n"
|
"OPER [ off | low | normal | high ]\n"
|
||||||
" Toggles operating mode of SAT>IP devices.\n",
|
" Gets and(or sets operating mode of SAT>IP devices.\n",
|
||||||
|
"ATTA\n"
|
||||||
|
" Attach active SAT>IP servers.\n",
|
||||||
|
"DETA\n"
|
||||||
|
" Detachs active SAT>IP servers.\n",
|
||||||
"TRAC [ <mode> ]\n"
|
"TRAC [ <mode> ]\n"
|
||||||
" Gets and/or sets used tracing mode.\n",
|
" Gets and/or sets used tracing mode.\n",
|
||||||
NULL
|
NULL
|
||||||
@@ -389,8 +509,19 @@ cString cPluginSatip::SVDRPCommand(const char *commandP, const char *optionP, in
|
|||||||
}
|
}
|
||||||
else if (strcasecmp(commandP, "OPER") == 0) {
|
else if (strcasecmp(commandP, "OPER") == 0) {
|
||||||
cString mode;
|
cString mode;
|
||||||
SatipConfig.ToggleOperatingMode();
|
unsigned int oper = SatipConfig.GetOperatingMode();
|
||||||
switch (SatipConfig.GetOperatingMode()) {
|
if (optionP && *optionP) {
|
||||||
|
if (strcasecmp(optionP, "off") == 0)
|
||||||
|
oper = cSatipConfig::eOperatingModeOff;
|
||||||
|
else if (strcasecmp(optionP, "low") == 0)
|
||||||
|
oper = cSatipConfig::eOperatingModeLow;
|
||||||
|
else if (strcasecmp(optionP, "normal") == 0)
|
||||||
|
oper = cSatipConfig::eOperatingModeNormal;
|
||||||
|
else if (strcasecmp(optionP, "high") == 0)
|
||||||
|
oper = cSatipConfig::eOperatingModeHigh;
|
||||||
|
SatipConfig.SetOperatingMode(oper);
|
||||||
|
}
|
||||||
|
switch (oper) {
|
||||||
case cSatipConfig::eOperatingModeOff:
|
case cSatipConfig::eOperatingModeOff:
|
||||||
mode = "off";
|
mode = "off";
|
||||||
break;
|
break;
|
||||||
@@ -409,6 +540,16 @@ cString cPluginSatip::SVDRPCommand(const char *commandP, const char *optionP, in
|
|||||||
}
|
}
|
||||||
return cString::sprintf("SATIP operating mode: %s\n", *mode);
|
return cString::sprintf("SATIP operating mode: %s\n", *mode);
|
||||||
}
|
}
|
||||||
|
else if (strcasecmp(commandP, "ATTA") == 0) {
|
||||||
|
SatipConfig.SetDetachedMode(false);
|
||||||
|
info("SATIP servers attached");
|
||||||
|
return cString("SATIP servers attached");
|
||||||
|
}
|
||||||
|
else if (strcasecmp(commandP, "DETA") == 0) {
|
||||||
|
SatipConfig.SetDetachedMode(true);
|
||||||
|
info("SATIP servers detached");
|
||||||
|
return cString("SATIP servers detached");
|
||||||
|
}
|
||||||
else if (strcasecmp(commandP, "TRAC") == 0) {
|
else if (strcasecmp(commandP, "TRAC") == 0) {
|
||||||
if (optionP && *optionP)
|
if (optionP && *optionP)
|
||||||
SatipConfig.SetTraceMode(strtol(optionP, NULL, 0));
|
SatipConfig.SetTraceMode(strtol(optionP, NULL, 0));
|
||||||
|
|||||||
@@ -338,6 +338,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);
|
||||||
|
|||||||
@@ -80,6 +80,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);
|
||||||
|
|||||||
468
server.c
468
server.c
@@ -12,23 +12,107 @@
|
|||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "server.h"
|
#include "server.h"
|
||||||
|
|
||||||
|
// --- cSatipFrontend ---------------------------------------------------------
|
||||||
|
|
||||||
|
cSatipFrontend::cSatipFrontend(const int indexP, const char *descriptionP)
|
||||||
|
: indexM(indexP),
|
||||||
|
transponderM(0),
|
||||||
|
deviceIdM(-1),
|
||||||
|
descriptionM(descriptionP)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
cSatipFrontend::~cSatipFrontend()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- cSatipFrontends --------------------------------------------------------
|
||||||
|
|
||||||
|
bool cSatipFrontends::Matches(int deviceIdP, int transponderP)
|
||||||
|
{
|
||||||
|
for (cSatipFrontend *f = First(); f; f = Next(f)) {
|
||||||
|
if (f->Attached() && (f->DeviceId() == deviceIdP) && (f->Transponder() == transponderP))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool cSatipFrontends::Assign(int deviceIdP, int transponderP)
|
||||||
|
{
|
||||||
|
cSatipFrontend *tmp = NULL;
|
||||||
|
// Prefer any unused one
|
||||||
|
for (cSatipFrontend *f = First(); f; f = Next(f)) {
|
||||||
|
if (!f->Attached() || (f->DeviceId() == deviceIdP)) {
|
||||||
|
tmp = f;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (tmp) {
|
||||||
|
tmp->SetTransponder(transponderP);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool cSatipFrontends::Attach(int deviceIdP, int transponderP)
|
||||||
|
{
|
||||||
|
for (cSatipFrontend *f = First(); f; f = Next(f)) {
|
||||||
|
if (f->Transponder() == transponderP) {
|
||||||
|
f->Attach(deviceIdP);
|
||||||
|
debug9("%s (%d, %d) %s/#%d", __PRETTY_FUNCTION__, deviceIdP, transponderP, *f->Description(), f->Index());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool cSatipFrontends::Detach(int deviceIdP, int transponderP)
|
||||||
|
{
|
||||||
|
for (cSatipFrontend *f = First(); f; f = Next(f)) {
|
||||||
|
if (f->Transponder() == transponderP) {
|
||||||
|
f->Detach(deviceIdP);
|
||||||
|
debug9("%s (%d, %d) %s/#%d", __PRETTY_FUNCTION__, deviceIdP, transponderP, *f->Description(), f->Index());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// --- cSatipServer -----------------------------------------------------------
|
// --- cSatipServer -----------------------------------------------------------
|
||||||
|
|
||||||
cSatipServer::cSatipServer(const char *addressP, const char *modelP, const char *descriptionP)
|
cSatipServer::cSatipServer(const char *addressP, const int portP, const char *modelP, const char *filtersP, const char *descriptionP, const int quirkP)
|
||||||
: addressM(addressP),
|
: addressM((addressP && *addressP) ? addressP : "0.0.0.0"),
|
||||||
modelM(modelP),
|
modelM((modelP && *modelP) ? modelP : "DVBS-1"),
|
||||||
descriptionM(descriptionP),
|
filtersM((filtersP && *filtersP) ? filtersP : ""),
|
||||||
modelTypeM(eSatipModelTypeNone),
|
descriptionM(!isempty(descriptionP) ? descriptionP : "MyBrokenHardware"),
|
||||||
quirkM(eSatipQuirkNone),
|
quirksM(""),
|
||||||
useCountM(0),
|
portM(portP),
|
||||||
transponderM(0),
|
quirkM(quirkP),
|
||||||
|
hasCiM(false),
|
||||||
|
activeM(true),
|
||||||
createdM(time(NULL)),
|
createdM(time(NULL)),
|
||||||
lastSeenM(0)
|
lastSeenM(0)
|
||||||
{
|
{
|
||||||
memset(modelCountM, 0, sizeof(modelCountM));
|
memset(sourceFiltersM, 0, sizeof(sourceFiltersM));
|
||||||
if (isempty(*modelM))
|
if (!isempty(*filtersM)) {
|
||||||
modelM = "DVBS-1";
|
char *s, *p = strdup(*filtersM);
|
||||||
if (!isempty(*descriptionM)) {
|
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()) {
|
||||||
// These devices contain a session id bug:
|
// These devices contain a session id bug:
|
||||||
// Inverto Airscreen Server IDL 400 ?
|
// Inverto Airscreen Server IDL 400 ?
|
||||||
// Elgato EyeTV Netstream 4Sat ?
|
// Elgato EyeTV Netstream 4Sat ?
|
||||||
@@ -37,56 +121,94 @@ cSatipServer::cSatipServer(const char *addressP, const char *modelP, const char
|
|||||||
strstr(*descriptionM, "Triax SatIP Converter") // Triax TSS 400
|
strstr(*descriptionM, "Triax SatIP Converter") // Triax TSS 400
|
||||||
)
|
)
|
||||||
quirkM |= eSatipQuirkSessionId;
|
quirkM |= eSatipQuirkSessionId;
|
||||||
|
// These devices contain support for RTP over TCP:
|
||||||
|
if (strstr(*descriptionM, "minisatip") || // minisatip server
|
||||||
|
strstr(*descriptionM, "DVBViewer") || // DVBViewer Media Server
|
||||||
|
strstr(*descriptionM, "GSSBOX") || // Grundig Sat Systems GSS.box DSI 400
|
||||||
|
strstr(*descriptionM, "DIGIBIT") || // Telestar Digibit R1
|
||||||
|
strstr(*descriptionM, "Triax SatIP Converter") // Triax TSS 400
|
||||||
|
)
|
||||||
|
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, "fritzdvbc") // Fritz!WLAN Repeater DVB-C
|
||||||
|
)
|
||||||
quirkM |= eSatipQuirkPlayPids;
|
quirkM |= eSatipQuirkPlayPids;
|
||||||
// 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, "fritzdvbc") || // Fritz!WLAN Repeater DVB-C
|
||||||
|
strstr(*descriptionM, "Schwaiger Sat>IP Server") // Schwaiger MS41IP
|
||||||
|
)
|
||||||
quirkM |= eSatipQuirkForceLock;
|
quirkM |= eSatipQuirkForceLock;
|
||||||
if (quirkM != eSatipQuirkNone)
|
// These devices support the X_PMT protocol extension
|
||||||
info("Malfunctioning '%s' server detected! Please, fix the firmware.", *descriptionM);
|
if (strstr(*descriptionM, "OctopusNet") || // Digital Devices OctopusNet
|
||||||
|
strstr(*descriptionM, "minisatip") // minisatip server
|
||||||
|
)
|
||||||
|
quirkM |= eSatipQuirkCiXpmt;
|
||||||
|
// These devices support the TNR protocol extension
|
||||||
|
if (strstr(*descriptionM, "DVBViewer") // DVBViewer Media Server
|
||||||
|
)
|
||||||
|
quirkM |= eSatipQuirkCiTnr;
|
||||||
|
// These devices don't support auto-detection of pilot tones
|
||||||
|
if (strstr(*descriptionM, "GSSBOX") || // Grundig Sat Systems GSS.box DSI 400
|
||||||
|
strstr(*descriptionM, "DIGIBIT") || // Telestar Digibit R1
|
||||||
|
strstr(*descriptionM, "Triax SatIP Converter") // Triax TSS 400
|
||||||
|
// 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;
|
||||||
}
|
}
|
||||||
char *s, *p = strdup(*modelM);
|
char *s, *p = strdup(*modelM);
|
||||||
char *r = strtok_r(p, ",", &s);
|
char *r = strtok_r(p, ",", &s);
|
||||||
while (r) {
|
while (r) {
|
||||||
if (strstr(r, "DVBS2")) {
|
char *c;
|
||||||
modelTypeM |= cSatipServer::eSatipModelTypeDVBS2;
|
if (c = strstr(r, "DVBS2-")) {
|
||||||
if (char *c = strstr(r, "-"))
|
int count = atoi(c + 6);
|
||||||
modelCountM[eSatipModuleDVBS2] = atoi(++c);
|
for (int i = 1; i <= count; ++i)
|
||||||
else
|
frontendsM[eSatipFrontendDVBS2].Add(new cSatipFrontend(i, "DVB-S2"));
|
||||||
modelCountM[eSatipModuleDVBS2] = 1;
|
|
||||||
}
|
}
|
||||||
if (strstr(r, "DVBT2")) {
|
else if (c = strstr(r, "DVBT-")) {
|
||||||
modelTypeM |= cSatipServer::eSatipModelTypeDVBT2;
|
int count = atoi(c + 5);
|
||||||
if (char *c = strstr(r, "-"))
|
for (int i = 1; i <= count; ++i)
|
||||||
modelCountM[eSatipModuleDVBT2] = atoi(++c);
|
frontendsM[eSatipFrontendDVBT].Add(new cSatipFrontend(i, "DVB-T"));
|
||||||
else
|
|
||||||
modelCountM[eSatipModuleDVBT2] = 1;
|
|
||||||
}
|
}
|
||||||
if (strstr(r, "DVBT")) {
|
else if (c = strstr(r, "DVBT2-")) {
|
||||||
modelTypeM |= cSatipServer::eSatipModelTypeDVBT;
|
int count = atoi(c + 6);
|
||||||
if (char *c = strstr(r, "-"))
|
for (int i = 1; i <= count; ++i)
|
||||||
modelCountM[eSatipModuleDVBT] = atoi(++c);
|
frontendsM[eSatipFrontendDVBT2].Add(new cSatipFrontend(i, "DVB-T2"));
|
||||||
else
|
|
||||||
modelCountM[eSatipModuleDVBT] = 1;
|
|
||||||
}
|
}
|
||||||
if (strstr(r, "DVBC2")) {
|
else if (c = strstr(r, "DVBC-")) {
|
||||||
modelTypeM |= cSatipServer::eSatipModelTypeDVBC2;
|
int count = atoi(c + 5);
|
||||||
if (char *c = strstr(r, "-"))
|
for (int i = 1; i <= count; ++i)
|
||||||
modelCountM[eSatipModuleDVBC2] = atoi(++c);
|
frontendsM[eSatipFrontendDVBC].Add(new cSatipFrontend(i, "DVB-C"));
|
||||||
else
|
|
||||||
modelCountM[eSatipModuleDVBC2] = 1;
|
|
||||||
}
|
}
|
||||||
if (strstr(r, "DVBC")) {
|
else if (c = strstr(r, "DVBC2-")) {
|
||||||
modelTypeM |= cSatipServer::eSatipModelTypeDVBC;
|
int count = atoi(c + 6);
|
||||||
if (char *c = strstr(r, "-"))
|
for (int i = 1; i <= count; ++i)
|
||||||
modelCountM[eSatipModuleDVBC] = atoi(++c);
|
frontendsM[eSatipFrontendDVBC2].Add(new cSatipFrontend(i, "DVB-C2"));
|
||||||
else
|
|
||||||
modelCountM[eSatipModuleDVBC] = 1;
|
|
||||||
}
|
}
|
||||||
r = strtok_r(NULL, ",", &s);
|
r = strtok_r(NULL, ",", &s);
|
||||||
}
|
}
|
||||||
free(p);
|
FREE_POINTER(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
cSatipServer::~cSatipServer()
|
cSatipServer::~cSatipServer()
|
||||||
@@ -96,15 +218,124 @@ cSatipServer::~cSatipServer()
|
|||||||
int cSatipServer::Compare(const cListObject &listObjectP) const
|
int cSatipServer::Compare(const cListObject &listObjectP) const
|
||||||
{
|
{
|
||||||
const cSatipServer *s = (const cSatipServer *)&listObjectP;
|
const cSatipServer *s = (const cSatipServer *)&listObjectP;
|
||||||
return strcasecmp(*addressM, *s->addressM);
|
int result = strcasecmp(*addressM, *s->addressM);
|
||||||
|
if (!result) {
|
||||||
|
result = strcasecmp(*modelM, *s->modelM);
|
||||||
|
if (!result)
|
||||||
|
result = strcasecmp(*descriptionM, *s->descriptionM);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void cSatipServer::Use(bool onOffP)
|
bool cSatipServer::IsValidSource(int sourceP)
|
||||||
{
|
{
|
||||||
if (onOffP)
|
if (sourceFiltersM[0]) {
|
||||||
++useCountM;
|
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 result = false;
|
||||||
|
if (IsValidSource(sourceP)) {
|
||||||
|
if (cSource::IsType(sourceP, 'S'))
|
||||||
|
result = frontendsM[eSatipFrontendDVBS2].Assign(deviceIdP, transponderP);
|
||||||
|
else if (cSource::IsType(sourceP, 'T')) {
|
||||||
|
if (systemP)
|
||||||
|
result = frontendsM[eSatipFrontendDVBT2].Assign(deviceIdP, transponderP);
|
||||||
else
|
else
|
||||||
--useCountM;
|
result = frontendsM[eSatipFrontendDVBT].Assign(deviceIdP, transponderP) || frontendsM[eSatipFrontendDVBT2].Assign(deviceIdP, transponderP);
|
||||||
|
}
|
||||||
|
else if (cSource::IsType(sourceP, 'C')) {
|
||||||
|
if (systemP)
|
||||||
|
result = frontendsM[eSatipFrontendDVBC2].Assign(deviceIdP, transponderP);
|
||||||
|
else
|
||||||
|
result = frontendsM[eSatipFrontendDVBC].Assign(deviceIdP, transponderP) || frontendsM[eSatipFrontendDVBC2].Assign(deviceIdP, transponderP);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool cSatipServer::Matches(int sourceP)
|
||||||
|
{
|
||||||
|
if (IsValidSource(sourceP)) {
|
||||||
|
if (cSource::IsType(sourceP, 'S'))
|
||||||
|
return GetModulesDVBS2();
|
||||||
|
else if (cSource::IsType(sourceP, 'T'))
|
||||||
|
return GetModulesDVBT() || GetModulesDVBT2();
|
||||||
|
else if (cSource::IsType(sourceP, 'C'))
|
||||||
|
return GetModulesDVBC() || GetModulesDVBC2();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool cSatipServer::Matches(int deviceIdP, int sourceP, int systemP, int transponderP)
|
||||||
|
{
|
||||||
|
bool result = false;
|
||||||
|
if (IsValidSource(sourceP)) {
|
||||||
|
if (cSource::IsType(sourceP, 'S'))
|
||||||
|
result = frontendsM[eSatipFrontendDVBS2].Matches(deviceIdP, transponderP);
|
||||||
|
else if (cSource::IsType(sourceP, 'T')) {
|
||||||
|
if (systemP)
|
||||||
|
result = frontendsM[eSatipFrontendDVBT2].Matches(deviceIdP, transponderP);
|
||||||
|
else
|
||||||
|
result = frontendsM[eSatipFrontendDVBT].Matches(deviceIdP, transponderP) || frontendsM[eSatipFrontendDVBT2].Matches(deviceIdP, transponderP);
|
||||||
|
}
|
||||||
|
else if (cSource::IsType(sourceP, 'C')) {
|
||||||
|
if (systemP)
|
||||||
|
result = frontendsM[eSatipFrontendDVBC2].Matches(deviceIdP, transponderP);
|
||||||
|
else
|
||||||
|
result = frontendsM[eSatipFrontendDVBC].Matches(deviceIdP, transponderP) || frontendsM[eSatipFrontendDVBC2].Matches(deviceIdP, transponderP);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cSatipServer::Attach(int deviceIdP, int transponderP)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < eSatipFrontendCount; ++i) {
|
||||||
|
if (frontendsM[i].Attach(deviceIdP, transponderP))
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void cSatipServer::Detach(int deviceIdP, int transponderP)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < eSatipFrontendCount; ++i) {
|
||||||
|
if (frontendsM[i].Detach(deviceIdP, transponderP))
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int cSatipServer::GetModulesDVBS2(void)
|
||||||
|
{
|
||||||
|
return frontendsM[eSatipFrontendDVBS2].Count();
|
||||||
|
}
|
||||||
|
|
||||||
|
int cSatipServer::GetModulesDVBT(void)
|
||||||
|
{
|
||||||
|
return frontendsM[eSatipFrontendDVBT].Count();
|
||||||
|
}
|
||||||
|
|
||||||
|
int cSatipServer::GetModulesDVBT2(void)
|
||||||
|
{
|
||||||
|
return frontendsM[eSatipFrontendDVBT2].Count();
|
||||||
|
}
|
||||||
|
|
||||||
|
int cSatipServer::GetModulesDVBC(void)
|
||||||
|
{
|
||||||
|
return frontendsM[eSatipFrontendDVBC].Count();
|
||||||
|
}
|
||||||
|
|
||||||
|
int cSatipServer::GetModulesDVBC2(void)
|
||||||
|
{
|
||||||
|
return frontendsM[eSatipFrontendDVBC2].Count();
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- cSatipServers ----------------------------------------------------------
|
// --- cSatipServers ----------------------------------------------------------
|
||||||
@@ -112,49 +343,32 @@ void cSatipServer::Use(bool onOffP)
|
|||||||
cSatipServer *cSatipServers::Find(cSatipServer *serverP)
|
cSatipServer *cSatipServers::Find(cSatipServer *serverP)
|
||||||
{
|
{
|
||||||
for (cSatipServer *s = First(); s; s = Next(s)) {
|
for (cSatipServer *s = First(); s; s = Next(s)) {
|
||||||
if (s == serverP)
|
if (s->Compare(*serverP) == 0)
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
cSatipServer *cSatipServers::Find(int sourceP, int transponderP, int systemP)
|
cSatipServer *cSatipServers::Find(int sourceP)
|
||||||
{
|
{
|
||||||
cSatipServer *result = NULL;
|
|
||||||
int model = 0;
|
|
||||||
if (cSource::IsType(sourceP, 'S'))
|
|
||||||
model |= cSatipServer::eSatipModelTypeDVBS2;
|
|
||||||
else if (cSource::IsType(sourceP, 'T')) {
|
|
||||||
if (systemP < 0)
|
|
||||||
model |= cSatipServer::eSatipModelTypeDVBT2 | cSatipServer::eSatipModelTypeDVBT;
|
|
||||||
else
|
|
||||||
model |= systemP ? cSatipServer::eSatipModelTypeDVBT2 : cSatipServer::eSatipModelTypeDVBT;
|
|
||||||
}
|
|
||||||
else if (cSource::IsType(sourceP, 'C'))
|
|
||||||
model |= cSatipServer::eSatipModelTypeDVBC;
|
|
||||||
for (cSatipServer *s = First(); s; s = Next(s)) {
|
for (cSatipServer *s = First(); s; s = Next(s)) {
|
||||||
if (s->Match(model) && s->Used() && (s->Transponder() == transponderP))
|
if (s->Matches(sourceP))
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
cSatipServer *cSatipServers::Assign(int deviceIdP, int sourceP, int transponderP, int systemP)
|
||||||
|
{
|
||||||
|
for (cSatipServer *s = First(); s; s = Next(s)) {
|
||||||
|
if (s->IsActive() && s->Matches(deviceIdP, sourceP, systemP, transponderP))
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
for (cSatipServer *s = First(); s; s = Next(s)) {
|
for (cSatipServer *s = First(); s; s = Next(s)) {
|
||||||
if (s->Match(model)) {
|
if (s->IsActive() && s->Assign(deviceIdP, sourceP, systemP, transponderP))
|
||||||
result = s;
|
return s;
|
||||||
if (!s->Used()) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
void cSatipServers::SetTransponder(cSatipServer *serverP, bool transponderP)
|
|
||||||
{
|
|
||||||
for (cSatipServer *s = First(); s; s = Next(s)) {
|
|
||||||
if (s == serverP) {
|
|
||||||
s->SetTransponder(transponderP);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
cSatipServer *cSatipServers::Update(cSatipServer *serverP)
|
cSatipServer *cSatipServers::Update(cSatipServer *serverP)
|
||||||
@@ -168,16 +382,60 @@ cSatipServer *cSatipServers::Update(cSatipServer *serverP)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void cSatipServers::Use(cSatipServer *serverP, bool onOffP)
|
void cSatipServers::Activate(cSatipServer *serverP, bool onOffP)
|
||||||
{
|
{
|
||||||
for (cSatipServer *s = First(); s; s = Next(s)) {
|
for (cSatipServer *s = First(); s; s = Next(s)) {
|
||||||
if (s == serverP) {
|
if (s == serverP) {
|
||||||
s->Use(onOffP);
|
s->Activate(onOffP);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void cSatipServers::Attach(cSatipServer *serverP, int deviceIdP, int transponderP)
|
||||||
|
{
|
||||||
|
for (cSatipServer *s = First(); s; s = Next(s)) {
|
||||||
|
if (s == serverP) {
|
||||||
|
s->Attach(deviceIdP, transponderP);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void cSatipServers::Detach(cSatipServer *serverP, int deviceIdP, int transponderP)
|
||||||
|
{
|
||||||
|
for (cSatipServer *s = First(); s; s = Next(s)) {
|
||||||
|
if (s == serverP) {
|
||||||
|
s->Detach(deviceIdP, transponderP);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool cSatipServers::IsQuirk(cSatipServer *serverP, int quirkP)
|
||||||
|
{
|
||||||
|
bool result = false;
|
||||||
|
for (cSatipServer *s = First(); s; s = Next(s)) {
|
||||||
|
if (s == serverP) {
|
||||||
|
result = s->Quirk(quirkP);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool cSatipServers::HasCI(cSatipServer *serverP)
|
||||||
|
{
|
||||||
|
bool result = false;
|
||||||
|
for (cSatipServer *s = First(); s; s = Next(s)) {
|
||||||
|
if (s == serverP) {
|
||||||
|
result = s->HasCI();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
void cSatipServers::Cleanup(uint64_t intervalMsP)
|
void cSatipServers::Cleanup(uint64_t intervalMsP)
|
||||||
{
|
{
|
||||||
for (cSatipServer *s = First(); s; s = Next(s)) {
|
for (cSatipServer *s = First(); s; s = Next(s)) {
|
||||||
@@ -188,6 +446,30 @@ void cSatipServers::Cleanup(uint64_t intervalMsP)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cString cSatipServers::GetAddress(cSatipServer *serverP)
|
||||||
|
{
|
||||||
|
cString address = "";
|
||||||
|
for (cSatipServer *s = First(); s; s = Next(s)) {
|
||||||
|
if (s == serverP) {
|
||||||
|
address = s->Address();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return address;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cSatipServers::GetPort(cSatipServer *serverP)
|
||||||
|
{
|
||||||
|
int port = SATIP_DEFAULT_RTSP_PORT;
|
||||||
|
for (cSatipServer *s = First(); s; s = Next(s)) {
|
||||||
|
if (s == serverP) {
|
||||||
|
port = s->Port();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return port;
|
||||||
|
}
|
||||||
|
|
||||||
cString cSatipServers::GetString(cSatipServer *serverP)
|
cString cSatipServers::GetString(cSatipServer *serverP)
|
||||||
{
|
{
|
||||||
cString list = "";
|
cString list = "";
|
||||||
@@ -204,7 +486,7 @@ cString cSatipServers::List(void)
|
|||||||
{
|
{
|
||||||
cString list = "";
|
cString list = "";
|
||||||
for (cSatipServer *s = First(); s; s = Next(s))
|
for (cSatipServer *s = First(); s; s = Next(s))
|
||||||
list = cString::sprintf("%s%s|%s|%s\n", *list, s->Address(), s->Model(), s->Description());
|
list = cString::sprintf("%s%c %s|%s|%s\n", *list, s->IsActive() ? '+' : '-', s->Address(), s->Model(), s->Description());
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -213,13 +495,15 @@ int cSatipServers::NumProvidedSystems(void)
|
|||||||
int count = 0;
|
int count = 0;
|
||||||
for (cSatipServer *s = First(); s; s = Next(s)) {
|
for (cSatipServer *s = First(); s; s = Next(s)) {
|
||||||
// DVB-S2: qpsk, 8psk, 16apsk, 32apsk
|
// DVB-S2: qpsk, 8psk, 16apsk, 32apsk
|
||||||
count += s->Satellite() * 4;
|
count += s->GetModulesDVBS2() * 4;
|
||||||
// DVB-T2: qpsk, qam16, qam64, qam256
|
|
||||||
// DVB-T: qpsk, qam16, qam64
|
// DVB-T: qpsk, qam16, qam64
|
||||||
count += s->Terrestrial2() ? s->Terrestrial2() * 4 : s->Terrestrial() * 3;
|
count += s->GetModulesDVBT() * 3;
|
||||||
// DVB-C2: qam16, qam32, qam64, qam128, qam256
|
// DVB-T2: qpsk, qam16, qam64, qam256
|
||||||
|
count += s->GetModulesDVBT2() * 4;
|
||||||
// DVB-C: qam64, qam128, qam256
|
// DVB-C: qam64, qam128, qam256
|
||||||
count += s->Cable2() ? s->Cable2() * 5 : s->Cable() * 3;
|
count += s->GetModulesDVBC() * 3;
|
||||||
|
// DVB-C2: qam16, qam32, qam64, qam128, qam256
|
||||||
|
count += s->GetModulesDVBC2() * 5;
|
||||||
}
|
}
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|||||||
124
server.h
124
server.h
@@ -8,28 +8,69 @@
|
|||||||
#ifndef __SATIP_SERVER_H
|
#ifndef __SATIP_SERVER_H
|
||||||
#define __SATIP_SERVER_H
|
#define __SATIP_SERVER_H
|
||||||
|
|
||||||
|
class cSatipServer;
|
||||||
|
|
||||||
|
// --- cSatipFrontend ---------------------------------------------------------
|
||||||
|
|
||||||
|
class cSatipFrontend : public cListObject {
|
||||||
|
private:
|
||||||
|
int indexM;
|
||||||
|
int transponderM;
|
||||||
|
int deviceIdM;
|
||||||
|
cString descriptionM;
|
||||||
|
|
||||||
|
public:
|
||||||
|
cSatipFrontend(const int indexP, const char *descriptionP);
|
||||||
|
virtual ~cSatipFrontend();
|
||||||
|
void Attach(int deviceIdP) { deviceIdM = deviceIdP; }
|
||||||
|
void Detach(int deviceIdP) { if (deviceIdP == deviceIdM) deviceIdM = -1; }
|
||||||
|
cString Description(void) { return descriptionM; }
|
||||||
|
bool Attached(void) { return (deviceIdM >= 0); }
|
||||||
|
int Index(void) { return indexM; }
|
||||||
|
int Transponder(void) { return transponderM; }
|
||||||
|
int DeviceId(void) { return deviceIdM; }
|
||||||
|
void SetTransponder(int transponderP) { transponderM = transponderP; }
|
||||||
|
};
|
||||||
|
|
||||||
|
// --- cSatipFrontends --------------------------------------------------------
|
||||||
|
|
||||||
|
class cSatipFrontends : public cList<cSatipFrontend> {
|
||||||
|
public:
|
||||||
|
bool Matches(int deviceIdP, int transponderP);
|
||||||
|
bool Assign(int deviceIdP, int transponderP);
|
||||||
|
bool Attach(int deviceIdP, int transponderP);
|
||||||
|
bool Detach(int deviceIdP, int transponderP);
|
||||||
|
};
|
||||||
|
|
||||||
// --- cSatipServer -----------------------------------------------------------
|
// --- cSatipServer -----------------------------------------------------------
|
||||||
|
|
||||||
class cSatipServer : public cListObject {
|
class cSatipServer : public cListObject {
|
||||||
private:
|
private:
|
||||||
enum eSatipModule {
|
enum eSatipFrontend {
|
||||||
eSatipModuleDVBS2 = 0,
|
eSatipFrontendDVBS2 = 0,
|
||||||
eSatipModuleDVBT,
|
eSatipFrontendDVBT,
|
||||||
eSatipModuleDVBT2,
|
eSatipFrontendDVBT2,
|
||||||
eSatipModuleDVBC,
|
eSatipFrontendDVBC,
|
||||||
eSatipModuleDVBC2,
|
eSatipFrontendDVBC2,
|
||||||
eSatipModuleCount
|
eSatipFrontendCount
|
||||||
|
};
|
||||||
|
enum {
|
||||||
|
eSatipMaxSourceFilters = 16
|
||||||
};
|
};
|
||||||
cString addressM;
|
cString addressM;
|
||||||
cString modelM;
|
cString modelM;
|
||||||
|
cString filtersM;
|
||||||
cString descriptionM;
|
cString descriptionM;
|
||||||
int modelCountM[eSatipModuleCount];
|
cString quirksM;
|
||||||
int modelTypeM;
|
cSatipFrontends frontendsM[eSatipFrontendCount];
|
||||||
|
int sourceFiltersM[eSatipMaxSourceFilters];
|
||||||
|
int portM;
|
||||||
int quirkM;
|
int quirkM;
|
||||||
int useCountM;
|
bool hasCiM;
|
||||||
int transponderM;
|
bool activeM;
|
||||||
time_t createdM;
|
time_t createdM;
|
||||||
cTimeMs lastSeenM;
|
cTimeMs lastSeenM;
|
||||||
|
bool IsValidSource(int sourceP);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
enum eSatipQuirk {
|
enum eSatipQuirk {
|
||||||
@@ -37,35 +78,36 @@ 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
|
||||||
};
|
};
|
||||||
enum eSatipModelType {
|
cSatipServer(const char *addressP, const int portP, const char *modelP, const char *filtersP, const char *descriptionP, const int quirkP);
|
||||||
eSatipModelTypeNone = 0x00,
|
|
||||||
eSatipModelTypeDVBS2 = 0x01,
|
|
||||||
eSatipModelTypeDVBT = 0x02,
|
|
||||||
eSatipModelTypeDVBT2 = 0x04,
|
|
||||||
eSatipModelTypeDVBC = 0x08,
|
|
||||||
eSatipModelTypeDVBC2 = 0x10,
|
|
||||||
eSatipModelTypeMask = 0xFF
|
|
||||||
};
|
|
||||||
cSatipServer(const char *addressP, const char *modelP, const char *descriptionP);
|
|
||||||
virtual ~cSatipServer();
|
virtual ~cSatipServer();
|
||||||
virtual int Compare(const cListObject &listObjectP) const;
|
virtual int Compare(const cListObject &listObjectP) const;
|
||||||
void Use(bool onOffP);
|
bool Assign(int deviceIdP, int sourceP, int systemP, int transponderP);
|
||||||
void SetTransponder(const int transponderP) { transponderM = transponderP; }
|
bool Matches(int sourceP);
|
||||||
int Transponder(void) { return transponderM; }
|
bool Matches(int deviceIdP, int sourceP, int systemP, int transponderP);
|
||||||
bool Used(void) { return !!useCountM; }
|
void Attach(int deviceIdP, int transponderP);
|
||||||
const char *Address() { return *addressM; }
|
void Detach(int deviceIdP, int transponderP);
|
||||||
|
int GetModulesDVBS2(void);
|
||||||
|
int GetModulesDVBT(void);
|
||||||
|
int GetModulesDVBT2(void);
|
||||||
|
int GetModulesDVBC(void);
|
||||||
|
int GetModulesDVBC2(void);
|
||||||
|
void Activate(bool onOffP) { activeM = onOffP; }
|
||||||
|
const char *Address(void) { return *addressM; }
|
||||||
const char *Model(void) { return *modelM; }
|
const char *Model(void) { return *modelM; }
|
||||||
const char *Description() { return *descriptionM; }
|
const char *Filters(void) { return *filtersM; }
|
||||||
|
const char *Description(void) { return *descriptionM; }
|
||||||
|
const char *Quirks(void) { return *quirksM; }
|
||||||
|
int Port(void) { return portM; }
|
||||||
bool Quirk(int quirkP) { return ((quirkP & eSatipQuirkMask) & quirkM); }
|
bool Quirk(int quirkP) { return ((quirkP & eSatipQuirkMask) & quirkM); }
|
||||||
int ModelType(void) { return modelTypeM; }
|
bool HasQuirk(void) { return (quirkM != eSatipQuirkNone); }
|
||||||
bool Match(int modelP) { return ((modelP & eSatipModelTypeMask) & modelTypeM); }
|
bool HasCI(void) { return hasCiM; }
|
||||||
int Cable() { return Match(eSatipModelTypeDVBC) ? modelCountM[eSatipModuleDVBC] : 0; }
|
bool IsActive(void) { return activeM; }
|
||||||
int Cable2() { return Match(eSatipModelTypeDVBC2) ? modelCountM[eSatipModuleDVBC2] : 0; }
|
|
||||||
int Satellite() { return Match(eSatipModelTypeDVBS2) ? modelCountM[eSatipModuleDVBS2] : 0; }
|
|
||||||
int Terrestrial() { return Match(eSatipModelTypeDVBT) ? modelCountM[eSatipModuleDVBT] : 0; }
|
|
||||||
int Terrestrial2() { return Match(eSatipModelTypeDVBT2) ? modelCountM[eSatipModuleDVBT2] : 0; }
|
|
||||||
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; }
|
||||||
@@ -76,12 +118,18 @@ public:
|
|||||||
class cSatipServers : public cList<cSatipServer> {
|
class cSatipServers : public cList<cSatipServer> {
|
||||||
public:
|
public:
|
||||||
cSatipServer *Find(cSatipServer *serverP);
|
cSatipServer *Find(cSatipServer *serverP);
|
||||||
cSatipServer *Find(int sourceP, int transponderP, int systemP);
|
cSatipServer *Find(int sourceP);
|
||||||
void SetTransponder(cSatipServer *serverP, bool transponderP);
|
cSatipServer *Assign(int deviceIdP, int sourceP, int transponderP, int systemP);
|
||||||
cSatipServer *Update(cSatipServer *serverP);
|
cSatipServer *Update(cSatipServer *serverP);
|
||||||
void Use(cSatipServer *serverP, bool onOffP);
|
void Activate(cSatipServer *serverP, bool onOffP);
|
||||||
|
void Attach(cSatipServer *serverP, int deviceIdP, int transponderP);
|
||||||
|
void Detach(cSatipServer *serverP, int deviceIdP, int transponderP);
|
||||||
|
bool IsQuirk(cSatipServer *serverP, int quirkP);
|
||||||
|
bool HasCI(cSatipServer *serverP);
|
||||||
void Cleanup(uint64_t intervalMsP = 0);
|
void Cleanup(uint64_t intervalMsP = 0);
|
||||||
|
cString GetAddress(cSatipServer *serverP);
|
||||||
cString GetString(cSatipServer *serverP);
|
cString GetString(cSatipServer *serverP);
|
||||||
|
int GetPort(cSatipServer *serverP);
|
||||||
cString List(void);
|
cString List(void);
|
||||||
int NumProvidedSystems(void);
|
int NumProvidedSystems(void);
|
||||||
};
|
};
|
||||||
|
|||||||
82
setup.c
82
setup.c
@@ -86,23 +86,29 @@ 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;
|
||||||
|
cString ciExtensionM;
|
||||||
uint64_t createdM;
|
uint64_t createdM;
|
||||||
void Setup(void);
|
void Setup(void);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
cSatipServerInfo(cSatipServer *serverP);
|
explicit cSatipServerInfo(cSatipServer *serverP);
|
||||||
virtual ~cSatipServerInfo();
|
virtual ~cSatipServerInfo();
|
||||||
virtual eOSState ProcessKey(eKeys keyP);
|
virtual eOSState ProcessKey(eKeys keyP);
|
||||||
};
|
};
|
||||||
|
|
||||||
cSatipServerInfo::cSatipServerInfo(cSatipServer *serverP)
|
cSatipServerInfo::cSatipServerInfo(cSatipServer *serverP)
|
||||||
: cOsdMenu(tr("SAT>IP Server"), 20),
|
: cOsdMenu(tr("SAT>IP Server"), 20),
|
||||||
|
serverM(serverP),
|
||||||
|
activeM(serverP && serverP->IsActive()),
|
||||||
addressM(serverP ? serverP->Address() : "---"),
|
addressM(serverP ? serverP->Address() : "---"),
|
||||||
modelM(serverP ? serverP->Model() : "---"),
|
modelM(serverP ? serverP->Model() : "---"),
|
||||||
descriptionM(serverP ? serverP->Description() : "---"),
|
descriptionM(serverP ? serverP->Description() : "---"),
|
||||||
|
ciExtensionM(serverP && serverP->HasCI() ? trVDR("yes") : trVDR("no")),
|
||||||
createdM(serverP ? serverP->Created() : 0)
|
createdM(serverP ? serverP->Created() : 0)
|
||||||
{
|
{
|
||||||
SetMenuCategory(mcSetupPlugins);
|
SetMenuCategory(mcSetupPlugins);
|
||||||
@@ -116,14 +122,17 @@ cSatipServerInfo::~cSatipServerInfo()
|
|||||||
|
|
||||||
void cSatipServerInfo::Setup(void)
|
void cSatipServerInfo::Setup(void)
|
||||||
{
|
{
|
||||||
|
Add(new cMenuEditBoolItem(trVDR("Active"), &activeM));
|
||||||
Add(new cOsdItem(cString::sprintf("%s:\t%s", tr("Address"), *addressM), osUnknown, false));
|
Add(new cOsdItem(cString::sprintf("%s:\t%s", tr("Address"), *addressM), osUnknown, false));
|
||||||
Add(new cOsdItem(cString::sprintf("%s:\t%s", tr("Model"), *modelM), osUnknown, false));
|
Add(new cOsdItem(cString::sprintf("%s:\t%s", tr("Model"), *modelM), osUnknown, false));
|
||||||
Add(new cOsdItem(cString::sprintf("%s:\t%s", tr("Description"), *descriptionM), osUnknown, false));
|
Add(new cOsdItem(cString::sprintf("%s:\t%s", tr("Description"), *descriptionM), osUnknown, false));
|
||||||
|
Add(new cOsdItem(cString::sprintf("%s:\t%s", tr("CI extension"), *ciExtensionM), osUnknown, false));
|
||||||
Add(new cOsdItem(cString::sprintf("%s:\t%s", tr("Creation date"), *DayDateTime(createdM)), osUnknown, false));
|
Add(new cOsdItem(cString::sprintf("%s:\t%s", tr("Creation date"), *DayDateTime(createdM)), osUnknown, false));
|
||||||
}
|
}
|
||||||
|
|
||||||
eOSState cSatipServerInfo::ProcessKey(eKeys keyP)
|
eOSState cSatipServerInfo::ProcessKey(eKeys keyP)
|
||||||
{
|
{
|
||||||
|
int oldActive = activeM;
|
||||||
eOSState state = cOsdMenu::ProcessKey(keyP);
|
eOSState state = cOsdMenu::ProcessKey(keyP);
|
||||||
|
|
||||||
if (state == osUnknown) {
|
if (state == osUnknown) {
|
||||||
@@ -132,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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -142,7 +157,7 @@ private:
|
|||||||
cSatipServer *serverM;
|
cSatipServer *serverM;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
cSatipServerItem(cSatipServer *serverP);
|
explicit cSatipServerItem(cSatipServer *serverP);
|
||||||
cSatipServer *Server(void) { return serverM; }
|
cSatipServer *Server(void) { return serverM; }
|
||||||
virtual void SetMenuItem(cSkinDisplayMenu *displayMenuP, int indexP, bool currentP, bool selectableP);
|
virtual void SetMenuItem(cSkinDisplayMenu *displayMenuP, int indexP, bool currentP, bool selectableP);
|
||||||
};
|
};
|
||||||
@@ -152,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() ? "+" : "-", 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)
|
||||||
@@ -327,8 +342,11 @@ eOSState cSatipMenuInfo::ProcessKey(eKeys keyP)
|
|||||||
// --- cSatipPluginSetup ------------------------------------------------------
|
// --- cSatipPluginSetup ------------------------------------------------------
|
||||||
|
|
||||||
cSatipPluginSetup::cSatipPluginSetup()
|
cSatipPluginSetup::cSatipPluginSetup()
|
||||||
: deviceCountM(0),
|
: detachedModeM(SatipConfig.GetDetachedMode()),
|
||||||
|
deviceCountM(0),
|
||||||
operatingModeM(SatipConfig.GetOperatingMode()),
|
operatingModeM(SatipConfig.GetOperatingMode()),
|
||||||
|
transportModeM(SatipConfig.GetTransportMode()),
|
||||||
|
ciExtensionM(SatipConfig.GetCIExtension()),
|
||||||
eitScanM(SatipConfig.GetEITScan()),
|
eitScanM(SatipConfig.GetEITScan()),
|
||||||
numDisabledSourcesM(SatipConfig.GetDisabledSourcesCount()),
|
numDisabledSourcesM(SatipConfig.GetDisabledSourcesCount()),
|
||||||
numDisabledFiltersM(SatipConfig.GetDisabledFiltersCount())
|
numDisabledFiltersM(SatipConfig.GetDisabledFiltersCount())
|
||||||
@@ -338,6 +356,13 @@ 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)
|
||||||
|
cicamsM[i] = SatipConfig.GetCICAM(i);
|
||||||
|
for (unsigned int i = 0; i < ELEMENTS(ca_systems_table); ++i)
|
||||||
|
cicamTextsM[i] = ca_systems_table[i].description;
|
||||||
if (numDisabledSourcesM > MAX_DISABLED_SOURCES_COUNT)
|
if (numDisabledSourcesM > MAX_DISABLED_SOURCES_COUNT)
|
||||||
numDisabledSourcesM = MAX_DISABLED_SOURCES_COUNT;
|
numDisabledSourcesM = MAX_DISABLED_SOURCES_COUNT;
|
||||||
for (int i = 0; i < MAX_DISABLED_SOURCES_COUNT; ++i)
|
for (int i = 0; i < MAX_DISABLED_SOURCES_COUNT; ++i)
|
||||||
@@ -364,6 +389,14 @@ void cSatipPluginSetup::Setup(void)
|
|||||||
helpM.Append(tr("Define the used operating mode for all SAT>IP devices:\n\noff - devices are disabled\nlow - devices are working at the lowest priority\nnormal - devices are working within normal parameters\nhigh - devices are working at the highest priority"));
|
helpM.Append(tr("Define the used operating mode for all SAT>IP devices:\n\noff - devices are disabled\nlow - devices are working at the lowest priority\nnormal - devices are working within normal parameters\nhigh - devices are working at the highest priority"));
|
||||||
|
|
||||||
if (operatingModeM) {
|
if (operatingModeM) {
|
||||||
|
Add(new cMenuEditBoolItem(tr("Enable CI extension"), &ciExtensionM));
|
||||||
|
helpM.Append(tr("Define whether a CI extension shall be used.\n\nThis setting enables integrated CI/CAM handling found in some SAT>IP hardware (e.g. Digital Devices OctopusNet)."));
|
||||||
|
|
||||||
|
for (unsigned int i = 0; ciExtensionM && i < ELEMENTS(cicamsM); ++i) {
|
||||||
|
Add(new cMenuEditStraItem(*cString::sprintf(" %s #%d", tr("CI/CAM"), i + 1), &cicamsM[i], ELEMENTS(cicamTextsM), cicamTextsM));
|
||||||
|
helpM.Append(tr("Define a desired CAM type for the CI slot.\n\nThe '---' option lets SAT>IP hardware do the auto-selection."));
|
||||||
|
}
|
||||||
|
|
||||||
Add(new cMenuEditBoolItem(tr("Enable EPG scanning"), &eitScanM));
|
Add(new cMenuEditBoolItem(tr("Enable EPG scanning"), &eitScanM));
|
||||||
helpM.Append(tr("Define whether the EPG background scanning shall be used.\n\nThis setting disables the automatic EIT scanning functionality for all SAT>IP devices."));
|
helpM.Append(tr("Define whether the EPG background scanning shall be used.\n\nThis setting disables the automatic EIT scanning functionality for all SAT>IP devices."));
|
||||||
|
|
||||||
@@ -383,15 +416,20 @@ 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("");
|
||||||
|
|
||||||
|
detachedModeM = SatipConfig.GetDetachedMode();
|
||||||
|
if (!detachedModeM) {
|
||||||
cSatipServers *servers = cSatipDiscover::GetInstance()->GetServers();
|
cSatipServers *servers = cSatipDiscover::GetInstance()->GetServers();
|
||||||
deviceCountM = servers->Count();
|
deviceCountM = servers->Count();
|
||||||
for (cSatipServer *s = servers->First(); s; s = servers->Next(s)) {
|
for (cSatipServer *s = servers->First(); s; s = servers->Next(s)) {
|
||||||
Add(new cSatipServerItem(s));
|
Add(new cSatipServerItem(s));
|
||||||
helpM.Append("");
|
helpM.Append("");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
SetCurrent(Get(current));
|
SetCurrent(Get(current));
|
||||||
Display();
|
Display();
|
||||||
@@ -440,14 +478,17 @@ eOSState cSatipPluginSetup::ProcessKey(eKeys keyP)
|
|||||||
{
|
{
|
||||||
bool hadSubMenu = HasSubMenu();
|
bool hadSubMenu = HasSubMenu();
|
||||||
int oldOperatingMode = operatingModeM;
|
int oldOperatingMode = operatingModeM;
|
||||||
|
int oldCiExtension = ciExtensionM;
|
||||||
int oldNumDisabledSources = numDisabledSourcesM;
|
int oldNumDisabledSources = numDisabledSourcesM;
|
||||||
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) {
|
||||||
@@ -463,7 +504,7 @@ eOSState cSatipPluginSetup::ProcessKey(eKeys keyP)
|
|||||||
if ((keyP == kNone) && (cSatipDiscover::GetInstance()->GetServers()->Count() != deviceCountM))
|
if ((keyP == kNone) && (cSatipDiscover::GetInstance()->GetServers()->Count() != deviceCountM))
|
||||||
Setup();
|
Setup();
|
||||||
|
|
||||||
if ((keyP != kNone) && ((numDisabledSourcesM != oldNumDisabledSources) || (numDisabledFiltersM != oldNumDisabledFilters) || (operatingModeM != oldOperatingMode))) {
|
if ((keyP != kNone) && ((numDisabledSourcesM != oldNumDisabledSources) || (numDisabledFiltersM != oldNumDisabledFilters) || (operatingModeM != oldOperatingMode) || (ciExtensionM != oldCiExtension) || (detachedModeM != SatipConfig.GetDetachedMode()))) {
|
||||||
while ((numDisabledSourcesM < oldNumDisabledSources) && (oldNumDisabledSources > 0))
|
while ((numDisabledSourcesM < oldNumDisabledSources) && (oldNumDisabledSources > 0))
|
||||||
disabledSourcesM[--oldNumDisabledSources] = cSource::stNone;
|
disabledSourcesM[--oldNumDisabledSources] = cSource::stNone;
|
||||||
while ((numDisabledFiltersM < oldNumDisabledFilters) && (oldNumDisabledFilters > 0))
|
while ((numDisabledFiltersM < oldNumDisabledFilters) && (oldNumDisabledFilters > 0))
|
||||||
@@ -474,6 +515,22 @@ eOSState cSatipPluginSetup::ProcessKey(eKeys keyP)
|
|||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void cSatipPluginSetup::StoreCicams(const char *nameP, int *cicamsP)
|
||||||
|
{
|
||||||
|
cString buffer = "";
|
||||||
|
int n = 0;
|
||||||
|
for (int i = 0; i < MAX_CICAM_COUNT; ++i) {
|
||||||
|
if (cicamsP[i] < 0)
|
||||||
|
break;
|
||||||
|
if (n++ > 0)
|
||||||
|
buffer = cString::sprintf("%s %d", *buffer, cicamsP[i]);
|
||||||
|
else
|
||||||
|
buffer = cString::sprintf("%d", cicamsP[i]);
|
||||||
|
}
|
||||||
|
debug3("%s (%s, %s)", __PRETTY_FUNCTION__, nameP, *buffer);
|
||||||
|
SetupStore(nameP, *buffer);
|
||||||
|
}
|
||||||
|
|
||||||
void cSatipPluginSetup::StoreSources(const char *nameP, int *sourcesP)
|
void cSatipPluginSetup::StoreSources(const char *nameP, int *sourcesP)
|
||||||
{
|
{
|
||||||
cString buffer = "";
|
cString buffer = "";
|
||||||
@@ -486,7 +543,7 @@ void cSatipPluginSetup::StoreSources(const char *nameP, int *sourcesP)
|
|||||||
else
|
else
|
||||||
buffer = cString::sprintf("%s", *cSource::ToString(sourcesP[i]));
|
buffer = cString::sprintf("%s", *cSource::ToString(sourcesP[i]));
|
||||||
}
|
}
|
||||||
debug1("%s (%s, %s)", __PRETTY_FUNCTION__, nameP, *buffer);
|
debug3("%s (%s, %s)", __PRETTY_FUNCTION__, nameP, *buffer);
|
||||||
SetupStore(nameP, *buffer);
|
SetupStore(nameP, *buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -502,7 +559,7 @@ void cSatipPluginSetup::StoreFilters(const char *nameP, int *valuesP)
|
|||||||
else
|
else
|
||||||
buffer = cString::sprintf("%d", valuesP[i]);
|
buffer = cString::sprintf("%d", valuesP[i]);
|
||||||
}
|
}
|
||||||
debug1("%s (%s, %s)", __PRETTY_FUNCTION__, nameP, *buffer);
|
debug3("%s (%s, %s)", __PRETTY_FUNCTION__, nameP, *buffer);
|
||||||
SetupStore(nameP, *buffer);
|
SetupStore(nameP, *buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -510,12 +567,19 @@ 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("EnableEITScan", eitScanM);
|
SetupStore("EnableEITScan", eitScanM);
|
||||||
|
StoreCicams("CICAM", cicamsM);
|
||||||
StoreSources("DisabledSources", disabledSourcesM);
|
StoreSources("DisabledSources", disabledSourcesM);
|
||||||
StoreFilters("DisabledFilters", disabledFilterIndexesM);
|
StoreFilters("DisabledFilters", disabledFilterIndexesM);
|
||||||
// Update global config
|
// Update global config
|
||||||
SatipConfig.SetOperatingMode(operatingModeM);
|
SatipConfig.SetOperatingMode(operatingModeM);
|
||||||
|
SatipConfig.SetTransportMode(transportModeM);
|
||||||
|
SatipConfig.SetCIExtension(ciExtensionM);
|
||||||
SatipConfig.SetEITScan(eitScanM);
|
SatipConfig.SetEITScan(eitScanM);
|
||||||
|
for (int i = 0; i < MAX_CICAM_COUNT; ++i)
|
||||||
|
SatipConfig.SetCICAM(i, cicamsM[i]);
|
||||||
for (int i = 0; i < MAX_DISABLED_SOURCES_COUNT; ++i)
|
for (int i = 0; i < MAX_DISABLED_SOURCES_COUNT; ++i)
|
||||||
SatipConfig.SetDisabledSources(i, disabledSourcesM[i]);
|
SatipConfig.SetDisabledSources(i, disabledSourcesM[i]);
|
||||||
for (int i = 0; i < SECTION_FILTER_TABLE_SIZE; ++i)
|
for (int i = 0; i < SECTION_FILTER_TABLE_SIZE; ++i)
|
||||||
|
|||||||
7
setup.h
7
setup.h
@@ -15,9 +15,15 @@
|
|||||||
class cSatipPluginSetup : public cMenuSetupPage
|
class cSatipPluginSetup : public cMenuSetupPage
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
bool detachedModeM;
|
||||||
int deviceCountM;
|
int deviceCountM;
|
||||||
int operatingModeM;
|
int operatingModeM;
|
||||||
|
int transportModeM;
|
||||||
const char *operatingModeTextsM[cSatipConfig::eOperatingModeCount];
|
const char *operatingModeTextsM[cSatipConfig::eOperatingModeCount];
|
||||||
|
const char *transportModeTextsM[cSatipConfig::eTransportModeCount];
|
||||||
|
int ciExtensionM;
|
||||||
|
int cicamsM[MAX_CICAM_COUNT];
|
||||||
|
const char *cicamTextsM[CA_SYSTEMS_TABLE_SIZE];
|
||||||
int eitScanM;
|
int eitScanM;
|
||||||
int numDisabledSourcesM;
|
int numDisabledSourcesM;
|
||||||
int disabledSourcesM[MAX_DISABLED_SOURCES_COUNT];
|
int disabledSourcesM[MAX_DISABLED_SOURCES_COUNT];
|
||||||
@@ -31,6 +37,7 @@ private:
|
|||||||
eOSState ShowDeviceStatus(void);
|
eOSState ShowDeviceStatus(void);
|
||||||
eOSState ShowInfo(void);
|
eOSState ShowInfo(void);
|
||||||
void Setup(void);
|
void Setup(void);
|
||||||
|
void StoreCicams(const char *nameP, int *cicamsP);
|
||||||
void StoreSources(const char *nameP, int *sourcesP);
|
void StoreSources(const char *nameP, int *sourcesP);
|
||||||
void StoreFilters(const char *nameP, int *valuesP);
|
void StoreFilters(const char *nameP, int *valuesP);
|
||||||
|
|
||||||
|
|||||||
172
socket.c
172
socket.c
@@ -21,7 +21,11 @@
|
|||||||
|
|
||||||
cSatipSocket::cSatipSocket()
|
cSatipSocket::cSatipSocket()
|
||||||
: socketPortM(0),
|
: socketPortM(0),
|
||||||
socketDescM(-1)
|
socketDescM(-1),
|
||||||
|
isMulticastM(false),
|
||||||
|
useSsmM(false),
|
||||||
|
streamAddrM(htonl(INADDR_ANY)),
|
||||||
|
sourceAddrM(htonl(INADDR_ANY))
|
||||||
{
|
{
|
||||||
debug1("%s", __PRETTY_FUNCTION__);
|
debug1("%s", __PRETTY_FUNCTION__);
|
||||||
memset(&sockAddrM, 0, sizeof(sockAddrM));
|
memset(&sockAddrM, 0, sizeof(sockAddrM));
|
||||||
@@ -34,10 +38,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 +57,19 @@ 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__
|
||||||
// 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 +81,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 sockerPort=%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 +135,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,21 +255,41 @@ 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, "recvmsg()", return -1);
|
ERROR_IF_RET(len < 0 && errno != EAGAIN && errno != EWOULDBLOCK, "recvmsg()", return -1);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int cSatipSocket::ReadMulti(unsigned char *bufferAddrP, unsigned int *elementRecvSizeP, unsigned int elementCountP, unsigned int elementBufferSizeP)
|
int cSatipSocket::ReadMulti(unsigned char *bufferAddrP, unsigned int *elementRecvSizeP, unsigned int elementCountP, unsigned int elementBufferSizeP)
|
||||||
{
|
{
|
||||||
debug16("%s (, , %d, %d)", __PRETTY_FUNCTION__, elementCountP, elementBufferSizeP);
|
debug16("%s (, , %d, %d)", __PRETTY_FUNCTION__, elementCountP, elementBufferSizeP);
|
||||||
|
int count = -1;
|
||||||
// Error out if socket not initialized
|
// Error out if socket not initialized
|
||||||
if (socketDescM <= 0) {
|
if (socketDescM <= 0) {
|
||||||
error("%s Invalid socket", __PRETTY_FUNCTION__);
|
error("%s Invalid socket", __PRETTY_FUNCTION__);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
if (!bufferAddrP || !elementRecvSizeP || !elementCountP || !elementBufferSizeP) {
|
||||||
|
error("%s Invalid parameter(s)", __PRETTY_FUNCTION__);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
#if defined(__GLIBC_PREREQ) && __GLIBC_PREREQ(2,12)
|
||||||
// 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];
|
||||||
@@ -153,12 +302,21 @@ int cSatipSocket::ReadMulti(unsigned char *bufferAddrP, unsigned int *elementRec
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Read data from socket as a set
|
// Read data from socket as a set
|
||||||
int count = -1;
|
|
||||||
if (socketDescM && bufferAddrP && elementRecvSizeP && (elementCountP > 0) && (elementBufferSizeP > 0))
|
|
||||||
count = (int)recvmmsg(socketDescM, mmsgh, elementCountP, MSG_DONTWAIT, NULL);
|
count = (int)recvmmsg(socketDescM, mmsgh, elementCountP, MSG_DONTWAIT, NULL);
|
||||||
ERROR_IF_RET(count < 0 && errno != EAGAIN && errno != EWOULDBLOCK, "recvmmsg()", return -1);
|
ERROR_IF_RET(count < 0 && errno != EAGAIN && errno != EWOULDBLOCK, "recvmmsg()", return -1);
|
||||||
for (int i = 0; i < count; ++i)
|
for (int i = 0; i < count; ++i)
|
||||||
elementRecvSizeP[i] = mmsgh[i].msg_len;
|
elementRecvSizeP[i] = mmsgh[i].msg_len;
|
||||||
|
#else
|
||||||
|
count = 0;
|
||||||
|
while (count < (int)elementCountP) {
|
||||||
|
int len = Read(bufferAddrP + count * elementBufferSizeP, elementBufferSizeP);
|
||||||
|
if (len < 0)
|
||||||
|
return -1;
|
||||||
|
else if (len == 0)
|
||||||
|
break;
|
||||||
|
elementRecvSizeP[count++] = len;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
debug16("%s Received %d packets size[0]=%d", __PRETTY_FUNCTION__, count, elementRecvSizeP[0]);
|
debug16("%s Received %d packets size[0]=%d", __PRETTY_FUNCTION__, count, elementRecvSizeP[0]);
|
||||||
|
|
||||||
return count;
|
return count;
|
||||||
|
|||||||
11
socket.h
11
socket.h
@@ -15,14 +15,23 @@ 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;
|
||||||
|
bool CheckAddress(const char *addrP, in_addr_t *inAddrP);
|
||||||
|
bool Join(void);
|
||||||
|
bool Leave(void);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
cSatipSocket();
|
cSatipSocket();
|
||||||
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);
|
||||||
|
|||||||
190
tuner.c
190
tuner.c
@@ -25,8 +25,10 @@ cSatipTuner::cSatipTuner(cSatipDeviceIf &deviceP, unsigned int packetLenP)
|
|||||||
rtcpM(*this),
|
rtcpM(*this),
|
||||||
streamAddrM(""),
|
streamAddrM(""),
|
||||||
streamParamM(""),
|
streamParamM(""),
|
||||||
currentServerM(NULL),
|
tnrParamM(""),
|
||||||
nextServerM(NULL),
|
streamPortM(SATIP_DEFAULT_RTSP_PORT),
|
||||||
|
currentServerM(NULL, deviceP.GetId(), 0),
|
||||||
|
nextServerM(NULL, deviceP.GetId(), 0),
|
||||||
mutexM(),
|
mutexM(),
|
||||||
reConnectM(),
|
reConnectM(),
|
||||||
keepAliveM(),
|
keepAliveM(),
|
||||||
@@ -40,7 +42,9 @@ cSatipTuner::cSatipTuner(cSatipDeviceIf &deviceP, unsigned int packetLenP)
|
|||||||
hasLockM(false),
|
hasLockM(false),
|
||||||
signalStrengthM(-1),
|
signalStrengthM(-1),
|
||||||
signalQualityM(-1),
|
signalQualityM(-1),
|
||||||
|
frontendIdM(-1),
|
||||||
streamIdM(-1),
|
streamIdM(-1),
|
||||||
|
pmtPidM(-1),
|
||||||
addPidsM(),
|
addPidsM(),
|
||||||
delPidsM(),
|
delPidsM(),
|
||||||
pidsM()
|
pidsM()
|
||||||
@@ -48,12 +52,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);
|
||||||
@@ -89,6 +97,10 @@ cSatipTuner::~cSatipTuner()
|
|||||||
void cSatipTuner::Action(void)
|
void cSatipTuner::Action(void)
|
||||||
{
|
{
|
||||||
debug1("%s Entering [device %d]", __PRETTY_FUNCTION__, deviceIdM);
|
debug1("%s Entering [device %d]", __PRETTY_FUNCTION__, deviceIdM);
|
||||||
|
|
||||||
|
bool lastIdleStatus = false;
|
||||||
|
cTimeMs idleCheck(eIdleCheckTimeoutMs);
|
||||||
|
cTimeMs tuning(eTuningTimeoutMs);
|
||||||
reConnectM.Set(eConnectTimeoutMs);
|
reConnectM.Set(eConnectTimeoutMs);
|
||||||
// Do the thread loop
|
// Do the thread loop
|
||||||
while (Running()) {
|
while (Running()) {
|
||||||
@@ -105,6 +117,7 @@ void cSatipTuner::Action(void)
|
|||||||
case tsSet:
|
case tsSet:
|
||||||
debug4("%s: tsSet [device %d]", __PRETTY_FUNCTION__, deviceIdM);
|
debug4("%s: tsSet [device %d]", __PRETTY_FUNCTION__, deviceIdM);
|
||||||
if (Connect()) {
|
if (Connect()) {
|
||||||
|
tuning.Set(eTuningTimeoutMs);
|
||||||
RequestState(tsTuned, smInternal);
|
RequestState(tsTuned, smInternal);
|
||||||
UpdatePids(true);
|
UpdatePids(true);
|
||||||
}
|
}
|
||||||
@@ -114,10 +127,12 @@ void cSatipTuner::Action(void)
|
|||||||
case tsTuned:
|
case tsTuned:
|
||||||
debug4("%s: tsTuned [device %d]", __PRETTY_FUNCTION__, deviceIdM);
|
debug4("%s: tsTuned [device %d]", __PRETTY_FUNCTION__, deviceIdM);
|
||||||
reConnectM.Set(eConnectTimeoutMs);
|
reConnectM.Set(eConnectTimeoutMs);
|
||||||
|
idleCheck.Set(eIdleCheckTimeoutMs);
|
||||||
|
lastIdleStatus = false;
|
||||||
// Read reception statistics via DESCRIBE and RTCP
|
// Read reception statistics via DESCRIBE and RTCP
|
||||||
if (hasLockM || ReadReceptionStatus()) {
|
if (hasLockM || ReadReceptionStatus()) {
|
||||||
// Quirk for devices without valid reception data
|
// Quirk for devices without valid reception data
|
||||||
if (currentServerM && currentServerM->Quirk(cSatipServer::eSatipQuirkForceLock)) {
|
if (currentServerM.IsQuirk(cSatipServer::eSatipQuirkForceLock)) {
|
||||||
hasLockM = true;
|
hasLockM = true;
|
||||||
signalStrengthM = eDefaultSignalStrength;
|
signalStrengthM = eDefaultSignalStrength;
|
||||||
signalQualityM = eDefaultSignalQuality;
|
signalQualityM = eDefaultSignalQuality;
|
||||||
@@ -125,6 +140,10 @@ void cSatipTuner::Action(void)
|
|||||||
if (hasLockM)
|
if (hasLockM)
|
||||||
RequestState(tsLocked, smInternal);
|
RequestState(tsLocked, smInternal);
|
||||||
}
|
}
|
||||||
|
else if (tuning.TimedOut()) {
|
||||||
|
error("Tuning timeout - retuning [device %d]", deviceIdM);
|
||||||
|
RequestState(tsSet, smInternal);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case tsLocked:
|
case tsLocked:
|
||||||
debug4("%s: tsLocked [device %d]", __PRETTY_FUNCTION__, deviceIdM);
|
debug4("%s: tsLocked [device %d]", __PRETTY_FUNCTION__, deviceIdM);
|
||||||
@@ -143,6 +162,16 @@ void cSatipTuner::Action(void)
|
|||||||
RequestState(tsSet, smInternal);
|
RequestState(tsSet, smInternal);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if (idleCheck.TimedOut()) {
|
||||||
|
bool currentIdleStatus = deviceM->IsIdle();
|
||||||
|
if (lastIdleStatus && currentIdleStatus) {
|
||||||
|
info("Idle timeout - releasing [device %d]", deviceIdM);
|
||||||
|
RequestState(tsRelease, smInternal);
|
||||||
|
}
|
||||||
|
lastIdleStatus = currentIdleStatus;
|
||||||
|
idleCheck.Set(eIdleCheckTimeoutMs);
|
||||||
|
break;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
error("Unknown tuner status %d [device %d]", currentStateM, deviceIdM);
|
error("Unknown tuner status %d [device %d]", currentStateM, deviceIdM);
|
||||||
@@ -182,12 +211,11 @@ 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);
|
||||||
//if (pidsM.Size())
|
|
||||||
// uri = cString::sprintf("%s&pids=%s", *uri, *pidsM.ListPids());
|
|
||||||
debug1("%s Retuning [device %d]", __PRETTY_FUNCTION__, deviceIdM);
|
debug1("%s Retuning [device %d]", __PRETTY_FUNCTION__, deviceIdM);
|
||||||
if (rtspM.Play(*uri)) {
|
if (rtspM.Play(*uri)) {
|
||||||
keepAliveM.Set(timeoutM);
|
keepAliveM.Set(timeoutM);
|
||||||
@@ -196,20 +224,20 @@ bool cSatipTuner::Connect(void)
|
|||||||
}
|
}
|
||||||
else if (rtspM.Options(*connectionUri)) {
|
else if (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 (rtspM.Setup(*uri, rtpM.Port(), rtcpM.Port(), useTcp)) {
|
||||||
keepAliveM.Set(timeoutM);
|
keepAliveM.Set(timeoutM);
|
||||||
if (nextServerM) {
|
if (nextServerM.IsValid()) {
|
||||||
cSatipDiscover::GetInstance()->UseServer(nextServerM, true);
|
|
||||||
currentServerM = nextServerM;
|
currentServerM = nextServerM;
|
||||||
nextServerM = NULL;
|
nextServerM.Reset();
|
||||||
}
|
}
|
||||||
|
currentServerM.Attach();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
rtspM.Reset();
|
rtspM.Reset();
|
||||||
streamIdM = -1;
|
streamIdM = -1;
|
||||||
error("Connect failed [device %d]", deviceIdM);
|
error("Connect failed [device %d]", deviceIdM);
|
||||||
@@ -224,8 +252,10 @@ 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
|
||||||
|
rtspM.Reset();
|
||||||
streamIdM = -1;
|
streamIdM = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -233,11 +263,12 @@ bool cSatipTuner::Disconnect(void)
|
|||||||
hasLockM = false;
|
hasLockM = false;
|
||||||
signalStrengthM = -1;
|
signalStrengthM = -1;
|
||||||
signalQualityM = -1;
|
signalQualityM = -1;
|
||||||
|
frontendIdM = -1;
|
||||||
|
|
||||||
if (currentServerM)
|
currentServerM.Detach();
|
||||||
cSatipDiscover::GetInstance()->UseServer(currentServerM, false);
|
|
||||||
statusUpdateM.Set(0);
|
statusUpdateM.Set(0);
|
||||||
timeoutM = eMinKeepAliveIntervalMs;
|
timeoutM = eMinKeepAliveIntervalMs;
|
||||||
|
pmtPidM = -1;
|
||||||
addPidsM.Clear();
|
addPidsM.Clear();
|
||||||
delPidsM.Clear();
|
delPidsM.Clear();
|
||||||
|
|
||||||
@@ -266,6 +297,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);
|
||||||
@@ -283,6 +319,9 @@ void cSatipTuner::ProcessApplicationData(u_char *bufferP, int lengthP)
|
|||||||
if (c) {
|
if (c) {
|
||||||
int value;
|
int value;
|
||||||
|
|
||||||
|
// feID:
|
||||||
|
frontendIdM = atoi(c + 7);
|
||||||
|
|
||||||
// level:
|
// level:
|
||||||
// Numerical value between 0 and 255
|
// Numerical value between 0 and 255
|
||||||
// An incoming L-band satellite signal of
|
// An incoming L-band satellite signal of
|
||||||
@@ -290,7 +329,7 @@ void cSatipTuner::ProcessApplicationData(u_char *bufferP, int lengthP)
|
|||||||
// -65dBm corresponds to 32
|
// -65dBm corresponds to 32
|
||||||
// No signal corresponds to 0
|
// No signal corresponds to 0
|
||||||
c = strstr(c, ",");
|
c = strstr(c, ",");
|
||||||
value = atoi(++c);
|
value = min(atoi(++c), 255);
|
||||||
// Scale value to 0-100
|
// Scale value to 0-100
|
||||||
signalStrengthM = (value >= 0) ? (value * 100 / 255) : -1;
|
signalStrengthM = (value >= 0) ? (value * 100 / 255) : -1;
|
||||||
|
|
||||||
@@ -308,7 +347,7 @@ void cSatipTuner::ProcessApplicationData(u_char *bufferP, int lengthP)
|
|||||||
// -a BER lower than 2x10-4 after Viterbi for DVB-S
|
// -a BER lower than 2x10-4 after Viterbi for DVB-S
|
||||||
// -a PER lower than 10-7 for DVB-S2
|
// -a PER lower than 10-7 for DVB-S2
|
||||||
c = strstr(c, ",");
|
c = strstr(c, ",");
|
||||||
value = atoi(++c);
|
value = min(atoi(++c), 15);
|
||||||
// Scale value to 0-100
|
// Scale value to 0-100
|
||||||
signalQualityM = (hasLockM && (value >= 0)) ? (value * 100 / 15) : 0;
|
signalQualityM = (hasLockM && (value >= 0)) ? (value * 100 / 15) : 0;
|
||||||
}
|
}
|
||||||
@@ -316,6 +355,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);
|
||||||
@@ -328,27 +372,72 @@ void cSatipTuner::SetSessionTimeout(const char *sessionP, int timeoutP)
|
|||||||
cMutexLock MutexLock(&mutexM);
|
cMutexLock MutexLock(&mutexM);
|
||||||
debug1("%s (%s, %d) [device %d]", __PRETTY_FUNCTION__, sessionP, timeoutP, deviceIdM);
|
debug1("%s (%s, %d) [device %d]", __PRETTY_FUNCTION__, sessionP, timeoutP, deviceIdM);
|
||||||
sessionM = sessionP;
|
sessionM = sessionP;
|
||||||
if (nextServerM && nextServerM->Quirk(cSatipServer::eSatipQuirkSessionId) && !isempty(*sessionM) && startswith(*sessionM, "0"))
|
if (nextServerM.IsQuirk(cSatipServer::eSatipQuirkSessionId) && !isempty(*sessionM) && startswith(*sessionM, "0"))
|
||||||
rtspM.SetSession(SkipZeroes(*sessionM));
|
rtspM.SetSession(SkipZeroes(*sessionM));
|
||||||
timeoutM = (timeoutP > eMinKeepAliveIntervalMs) ? timeoutP : eMinKeepAliveIntervalMs;
|
timeoutM = (timeoutP > eMinKeepAliveIntervalMs) ? timeoutP : eMinKeepAliveIntervalMs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
rtpM.Close();
|
||||||
|
if (rtpPortP >= 0) {
|
||||||
|
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);
|
||||||
|
rtcpM.Close();
|
||||||
|
if (rtcpPortP >= 0) {
|
||||||
|
if (multicast)
|
||||||
|
rtcpM.OpenMulticast(rtpPortP, streamAddrP, sourceAddrP);
|
||||||
|
else
|
||||||
|
rtcpM.Open(rtpPortP);
|
||||||
|
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);
|
||||||
return deviceIdM;
|
return deviceIdM;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool cSatipTuner::SetSource(cSatipServer *serverP, const char *parameterP, const int indexP)
|
bool cSatipTuner::SetSource(cSatipServer *serverP, const int transponderP, const char *parameterP, const int indexP)
|
||||||
{
|
{
|
||||||
debug1("%s (%s, %d) [device %d]", __PRETTY_FUNCTION__, parameterP, indexP, deviceIdM);
|
debug1("%s (%d, %s, %d) [device %d]", __PRETTY_FUNCTION__, transponderP, parameterP, indexP, deviceIdM);
|
||||||
cMutexLock MutexLock(&mutexM);
|
cMutexLock MutexLock(&mutexM);
|
||||||
if (serverP) {
|
if (serverP) {
|
||||||
nextServerM = cSatipDiscover::GetInstance()->GetServer(serverP);
|
nextServerM.Set(serverP, transponderP);
|
||||||
if (nextServerM && !isempty(nextServerM->Address()) && !isempty(parameterP)) {
|
if (!isempty(*nextServerM.GetAddress()) && !isempty(parameterP)) {
|
||||||
// Update stream address and parameter
|
// Update stream address and parameter
|
||||||
streamAddrM = rtspM.RtspUnescapeString(nextServerM->Address());
|
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);
|
||||||
}
|
}
|
||||||
@@ -375,8 +464,7 @@ bool cSatipTuner::SetPid(int pidP, int typeP, bool onP)
|
|||||||
delPidsM.AddPid(pidP);
|
delPidsM.AddPid(pidP);
|
||||||
addPidsM.RemovePid(pidP);
|
addPidsM.RemovePid(pidP);
|
||||||
}
|
}
|
||||||
debug9("%s (%d, %d, %d) pids=%s [device %d]", __PRETTY_FUNCTION__, pidP, typeP, onP, *pidsM.ListPids(), deviceIdM);
|
debug12("%s (%d, %d, %d) pids=%s [device %d]", __PRETTY_FUNCTION__, pidP, typeP, onP, *pidsM.ListPids(), deviceIdM);
|
||||||
pidUpdateCacheM.Set(ePidUpdateIntervalMs);
|
|
||||||
sleepM.Signal();
|
sleepM.Signal();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@@ -388,8 +476,9 @@ 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 usedummy = !!(currentServerM && currentServerM->Quirk(cSatipServer::eSatipQuirkPlayPids));
|
bool useci = (SatipConfig.GetCIExtension() && currentServerM.HasCI());
|
||||||
|
bool usedummy = currentServerM.IsQuirk(cSatipServer::eSatipQuirkPlayPids);
|
||||||
if (forceP || usedummy) {
|
if (forceP || usedummy) {
|
||||||
if (pidsM.Size())
|
if (pidsM.Size())
|
||||||
uri = cString::sprintf("%s?pids=%s", *uri, *pidsM.ListPids());
|
uri = cString::sprintf("%s?pids=%s", *uri, *pidsM.ListPids());
|
||||||
@@ -402,6 +491,33 @@ bool cSatipTuner::UpdatePids(bool forceP)
|
|||||||
if (delPidsM.Size())
|
if (delPidsM.Size())
|
||||||
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 (currentServerM.IsQuirk(cSatipServer::eSatipQuirkCiXpmt)) {
|
||||||
|
// CI extension parameters:
|
||||||
|
// - x_pmt : specifies the PMT of the service you want the CI to decode
|
||||||
|
// - x_ci : specfies which CI slot (1..n) to use
|
||||||
|
// value 0 releases the CI slot
|
||||||
|
// CI slot released automatically if the stream is released,
|
||||||
|
// but not when used retuning to another channel
|
||||||
|
int pid = deviceM->GetPmtPid();
|
||||||
|
if ((pid > 0) && (pid != pmtPidM)) {
|
||||||
|
int slot = deviceM->GetCISlot();
|
||||||
|
uri = cString::sprintf("%s&x_pmt=%d", *uri, pid);
|
||||||
|
if (slot > 0)
|
||||||
|
uri = cString::sprintf("%s&x_ci=%d", *uri, slot);
|
||||||
|
}
|
||||||
|
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);
|
||||||
if (!rtspM.Play(*uri))
|
if (!rtspM.Play(*uri))
|
||||||
return false;
|
return false;
|
||||||
addPidsM.Clear();
|
addPidsM.Clear();
|
||||||
@@ -420,7 +536,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;
|
||||||
}
|
}
|
||||||
@@ -437,7 +553,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;
|
||||||
}
|
}
|
||||||
@@ -539,6 +655,12 @@ const char *cSatipTuner::TunerStateString(eTunerState stateP)
|
|||||||
return "---";
|
return "---";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int cSatipTuner::FrontendId(void)
|
||||||
|
{
|
||||||
|
debug16("%s [device %d]", __PRETTY_FUNCTION__, deviceIdM);
|
||||||
|
return frontendIdM;
|
||||||
|
}
|
||||||
|
|
||||||
int cSatipTuner::SignalStrength(void)
|
int cSatipTuner::SignalStrength(void)
|
||||||
{
|
{
|
||||||
debug16("%s [device %d]", __PRETTY_FUNCTION__, deviceIdM);
|
debug16("%s [device %d]", __PRETTY_FUNCTION__, deviceIdM);
|
||||||
@@ -560,11 +682,11 @@ bool cSatipTuner::HasLock(void)
|
|||||||
cString cSatipTuner::GetSignalStatus(void)
|
cString cSatipTuner::GetSignalStatus(void)
|
||||||
{
|
{
|
||||||
debug16("%s [device %d]", __PRETTY_FUNCTION__, deviceIdM);
|
debug16("%s [device %d]", __PRETTY_FUNCTION__, deviceIdM);
|
||||||
return cString::sprintf("lock=%d strength=%d quality=%d", HasLock(), SignalStrength(), SignalQuality());
|
return cString::sprintf("lock=%d strength=%d quality=%d frontend=%d", HasLock(), SignalStrength(), SignalQuality(), FrontendId());
|
||||||
}
|
}
|
||||||
|
|
||||||
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";
|
||||||
}
|
}
|
||||||
|
|||||||
61
tuner.h
61
tuner.h
@@ -12,6 +12,7 @@
|
|||||||
#include <vdr/tools.h>
|
#include <vdr/tools.h>
|
||||||
|
|
||||||
#include "deviceif.h"
|
#include "deviceif.h"
|
||||||
|
#include "discover.h"
|
||||||
#include "rtp.h"
|
#include "rtp.h"
|
||||||
#include "rtcp.h"
|
#include "rtcp.h"
|
||||||
#include "rtsp.h"
|
#include "rtsp.h"
|
||||||
@@ -20,14 +21,6 @@
|
|||||||
|
|
||||||
class cSatipPid : public cVector<int> {
|
class cSatipPid : public cVector<int> {
|
||||||
private:
|
private:
|
||||||
int PidIndex(const int &pidP)
|
|
||||||
{
|
|
||||||
for (int i = 0; i < Size(); ++i) {
|
|
||||||
if (pidP == At(i))
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
static int PidCompare(const void *aPidP, const void *bPidP)
|
static int PidCompare(const void *aPidP, const void *bPidP)
|
||||||
{
|
{
|
||||||
return (*(int*)aPidP - *(int*)bPidP);
|
return (*(int*)aPidP - *(int*)bPidP);
|
||||||
@@ -36,19 +29,14 @@ private:
|
|||||||
public:
|
public:
|
||||||
void RemovePid(const int &pidP)
|
void RemovePid(const int &pidP)
|
||||||
{
|
{
|
||||||
int i = PidIndex(pidP);
|
if (RemoveElement(pidP))
|
||||||
if (i >= 0) {
|
|
||||||
Remove(i);
|
|
||||||
Sort(PidCompare);
|
Sort(PidCompare);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
void AddPid(int pidP)
|
void AddPid(int pidP)
|
||||||
{
|
{
|
||||||
if (PidIndex(pidP) < 0) {
|
if (AppendUnique(pidP))
|
||||||
Append(pidP);
|
|
||||||
Sort(PidCompare);
|
Sort(PidCompare);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
cString ListPids(void)
|
cString ListPids(void)
|
||||||
{
|
{
|
||||||
cString list = "";
|
cString list = "";
|
||||||
@@ -61,6 +49,30 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class cSatipTunerServer
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
cSatipServer *serverM;
|
||||||
|
int deviceIdM;
|
||||||
|
int transponderM;
|
||||||
|
|
||||||
|
public:
|
||||||
|
cSatipTunerServer(cSatipServer *serverP, const int deviceIdP, const int transponderP) : serverM(serverP), deviceIdM(deviceIdP), transponderM(transponderP) {}
|
||||||
|
~cSatipTunerServer() {}
|
||||||
|
cSatipTunerServer(const cSatipTunerServer &objP) { serverM = NULL; deviceIdM = -1; transponderM = 0; }
|
||||||
|
cSatipTunerServer& operator= (const cSatipTunerServer &objP) { serverM = objP.serverM; deviceIdM = objP.deviceIdM; transponderM = objP.transponderM; return *this; }
|
||||||
|
bool IsValid(void) { return !!serverM; }
|
||||||
|
bool IsQuirk(int quirkP) { return (serverM && cSatipDiscover::GetInstance()->IsServerQuirk(serverM, quirkP)); }
|
||||||
|
bool HasCI(void) { return (serverM && cSatipDiscover::GetInstance()->HasServerCI(serverM)); }
|
||||||
|
void Attach(void) { if (serverM) cSatipDiscover::GetInstance()->AttachServer(serverM, deviceIdM, transponderM); }
|
||||||
|
void Detach(void) { if (serverM) cSatipDiscover::GetInstance()->DetachServer(serverM, deviceIdM, transponderM); }
|
||||||
|
void Set(cSatipServer *serverP, const int transponderP) { serverM = serverP; transponderM = transponderP; }
|
||||||
|
void Reset(void) { serverM = NULL; transponderM = 0; }
|
||||||
|
cString GetAddress(void) { return serverM ? cSatipDiscover::GetInstance()->GetServerAddress(serverM) : ""; }
|
||||||
|
int GetPort(void) { return serverM ? cSatipDiscover::GetInstance()->GetServerPort(serverM) : SATIP_DEFAULT_RTSP_PORT; }
|
||||||
|
cString GetInfo(void) { return cString::sprintf("server=%s deviceid=%d transponder=%d", serverM ? "assigned" : "null", deviceIdM, transponderM); }
|
||||||
|
};
|
||||||
|
|
||||||
class cSatipTuner : public cThread, public cSatipTunerStatistics, public cSatipTunerIf
|
class cSatipTuner : public cThread, public cSatipTunerStatistics, public cSatipTunerIf
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
@@ -68,10 +80,12 @@ private:
|
|||||||
eDummyPid = 100,
|
eDummyPid = 100,
|
||||||
eDefaultSignalStrength = 15,
|
eDefaultSignalStrength = 15,
|
||||||
eDefaultSignalQuality = 224,
|
eDefaultSignalQuality = 224,
|
||||||
eSleepTimeoutMs = 1000, // in milliseconds
|
eSleepTimeoutMs = 250, // in milliseconds
|
||||||
eStatusUpdateTimeoutMs = 1000, // in milliseconds
|
eStatusUpdateTimeoutMs = 1000, // in milliseconds
|
||||||
ePidUpdateIntervalMs = 250, // in milliseconds
|
ePidUpdateIntervalMs = 250, // in milliseconds
|
||||||
eConnectTimeoutMs = 5000, // in milliseconds
|
eConnectTimeoutMs = 5000, // in milliseconds
|
||||||
|
eIdleCheckTimeoutMs = 15000, // in milliseconds
|
||||||
|
eTuningTimeoutMs = 20000, // in milliseconds
|
||||||
eMinKeepAliveIntervalMs = 30000 // in milliseconds
|
eMinKeepAliveIntervalMs = 30000 // in milliseconds
|
||||||
};
|
};
|
||||||
enum eTunerState { tsIdle, tsRelease, tsSet, tsTuned, tsLocked };
|
enum eTunerState { tsIdle, tsRelease, tsSet, tsTuned, tsLocked };
|
||||||
@@ -85,8 +99,10 @@ private:
|
|||||||
cSatipRtcp rtcpM;
|
cSatipRtcp rtcpM;
|
||||||
cString streamAddrM;
|
cString streamAddrM;
|
||||||
cString streamParamM;
|
cString streamParamM;
|
||||||
cSatipServer *currentServerM;
|
cString tnrParamM;
|
||||||
cSatipServer *nextServerM;
|
int streamPortM;
|
||||||
|
cSatipTunerServer currentServerM;
|
||||||
|
cSatipTunerServer nextServerM;
|
||||||
cMutex mutexM;
|
cMutex mutexM;
|
||||||
cTimeMs reConnectM;
|
cTimeMs reConnectM;
|
||||||
cTimeMs keepAliveM;
|
cTimeMs keepAliveM;
|
||||||
@@ -100,7 +116,9 @@ private:
|
|||||||
bool hasLockM;
|
bool hasLockM;
|
||||||
int signalStrengthM;
|
int signalStrengthM;
|
||||||
int signalQualityM;
|
int signalQualityM;
|
||||||
|
int frontendIdM;
|
||||||
int streamIdM;
|
int streamIdM;
|
||||||
|
int pmtPidM;
|
||||||
cSatipPid addPidsM;
|
cSatipPid addPidsM;
|
||||||
cSatipPid delPidsM;
|
cSatipPid delPidsM;
|
||||||
cSatipPid pidsM;
|
cSatipPid pidsM;
|
||||||
@@ -115,6 +133,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);
|
||||||
@@ -123,10 +142,11 @@ public:
|
|||||||
cSatipTuner(cSatipDeviceIf &deviceP, unsigned int packetLenP);
|
cSatipTuner(cSatipDeviceIf &deviceP, unsigned int packetLenP);
|
||||||
virtual ~cSatipTuner();
|
virtual ~cSatipTuner();
|
||||||
bool IsTuned(void) const { return (currentStateM >= tsTuned); }
|
bool IsTuned(void) const { return (currentStateM >= tsTuned); }
|
||||||
bool SetSource(cSatipServer *serverP, const char *parameterP, const int indexP);
|
bool SetSource(cSatipServer *serverP, const int transponderP, const char *parameterP, const int indexP);
|
||||||
bool SetPid(int pidP, int typeP, bool onP);
|
bool SetPid(int pidP, int typeP, bool onP);
|
||||||
bool Open(void);
|
bool Open(void);
|
||||||
bool Close(void);
|
bool Close(void);
|
||||||
|
int FrontendId(void);
|
||||||
int SignalStrength(void);
|
int SignalStrength(void);
|
||||||
int SignalQuality(void);
|
int SignalQuality(void);
|
||||||
bool HasLock(void);
|
bool HasLock(void);
|
||||||
@@ -137,8 +157,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);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -12,14 +12,17 @@ class cSatipTunerIf {
|
|||||||
public:
|
public:
|
||||||
cSatipTunerIf() {}
|
cSatipTunerIf() {}
|
||||||
virtual ~cSatipTunerIf() {}
|
virtual ~cSatipTunerIf() {}
|
||||||
virtual void ProcessVideoData(u_char *bufferP, int lenghtP) = 0;
|
virtual void ProcessVideoData(u_char *bufferP, int lengthP) = 0;
|
||||||
virtual void ProcessApplicationData(u_char *bufferP, int lenghtP) = 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:
|
||||||
cSatipTunerIf(const cSatipTunerIf&);
|
explicit cSatipTunerIf(const cSatipTunerIf&);
|
||||||
cSatipTunerIf& operator=(const cSatipTunerIf&);
|
cSatipTunerIf& operator=(const cSatipTunerIf&);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user