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

77 Commits

Author SHA1 Message Date
Rolf Ahrenberg
6c4c8a10b7 Set the default device count to two. 2015-04-26 12:49:40 +03:00
Rolf Ahrenberg
8b43cdc634 Added initial support for detaching and attaching SAT>IP servers. 2015-04-12 21:25:41 +03:00
Rolf Ahrenberg
fe010ab72c Added a more flexible OPER command in the SVDRP interface. 2015-04-09 21:36:13 +03:00
Rolf Ahrenberg
7bdc152f76 Prepared for a release. 2015-04-03 20:37:29 +03:00
Rolf Ahrenberg
bd6774ba28 Relaxed the server cleanup timeout. 2015-03-26 00:28:17 +02:00
Rolf Ahrenberg
fbf7977853 Added a memory guard for cSatipMemoryBuffer(). 2015-03-26 00:23:55 +02:00
Rolf Ahrenberg
19a6a4a5ee Simplified GetTransponderUrlParameters(). 2015-03-22 23:44:15 +02:00
Rolf Ahrenberg
7b683dba8d Implemented cSatipMemoryBuffer(). 2015-03-22 20:06:47 +02:00
Rolf Ahrenberg
942d3a936e Fixed CURL buffer size for discovery. 2015-03-22 17:33:08 +02:00
Rolf Ahrenberg
748ea15d1d Updated against SAT>IP protocol specification version 1.2.2. 2015-03-22 16:47:02 +02:00
Rolf Ahrenberg
1d75da403a Simplified GetTransponderUrlParameters(). 2015-03-22 16:33:48 +02:00
Rolf Ahrenberg
4d8263e8fd Improved RTSP error checking. 2015-03-18 22:59:38 +02:00
Rolf Ahrenberg
7019b719a5 Fixed a memory leak in TinyXML implementation (Thanks to Oliver Endriss). 2015-03-18 20:55:10 +02:00
Rolf Ahrenberg
39249ca2d5 Fixed generic error macros. 2015-03-08 15:53:54 +02:00
Rolf Ahrenberg
68e0d1474e Got rid of SATIP_DEBUG. 2015-03-07 17:50:48 +02:00
Rolf Ahrenberg
ad5c221e44 Fixed wrong indenting. 2015-03-04 19:43:01 +02:00
Rolf Ahrenberg
826e53e8ea Fixed the discovery tracing level. 2015-03-03 19:09:51 +02:00
Rolf Ahrenberg
f4dd02a9aa Robustify the server discovery. 2015-03-02 20:08:21 +02:00
Rolf Ahrenberg
8184a785b7 Updated README. 2015-02-20 21:15:55 +02:00
Rolf Ahrenberg
1b4094696a Updated HISTORY. 2015-02-20 20:53:20 +02:00
Rolf Ahrenberg
4139e87f4a Disable socket flushing. 2015-02-20 20:51:31 +02:00
Rolf Ahrenberg
7196c9403b Updated the APIVERSNUM requirement. 2015-02-20 20:47:58 +02:00
Rolf Ahrenberg
e1c896c1a6 Added a missing linefeed. 2015-02-17 21:16:30 +02:00
Rolf Ahrenberg
6b63ad145f Fixed the frontend assignment. 2015-02-16 19:42:18 +02:00
Rolf Ahrenberg
84dfc6701e Refactored the frontend attaching/detaching signaling. 2015-02-16 17:59:27 +02:00
Rolf Ahrenberg
653d9d659b Updated README. 2015-02-16 16:49:51 +02:00
Rolf Ahrenberg
26cd34f965 Updated version to 2.2.0. 2015-02-08 22:41:01 +02:00
Rolf Ahrenberg
df258d127f Reverted the force locking quirk for Triax TSS 400. 2015-01-27 21:31:39 +02:00
Rolf Ahrenberg
3e4b1c0383 Updated the server info message to show used quirks. 2015-01-27 17:19:06 +02:00
Rolf Ahrenberg
73ed299ed9 Fixed to nag about any malfunctioning firmware only once. 2015-01-26 00:24:07 +02:00
Rolf Ahrenberg
37e151b3e3 Added the force locking quirk for Triax TSS 400. 2015-01-25 23:47:56 +02:00
Rolf Ahrenberg
b1aad3fb80 Updated the version number. 2015-01-24 17:21:04 +02:00
Rolf Ahrenberg
a87dfc43f7 Refactored the frontend handling. 2015-01-24 17:16:09 +02:00
Rolf Ahrenberg
26be862d89 Refactored some errno handling. 2015-01-24 16:20:13 +02:00
Rolf Ahrenberg
ab2a47e3e7 Got rid of scan-build warnings. 2015-01-22 21:37:33 +02:00
Rolf Ahrenberg
3d1efe7a80 Fixed freeing some memory. 2015-01-21 22:40:24 +02:00
Rolf Ahrenberg
c9898bfbfd Added support for showing the frontend id. 2015-01-20 00:35:46 +02:00
Rolf Ahrenberg
46bfc805e6 Removed SATIP_XCI. 2015-01-18 15:08:57 +02:00
Rolf Ahrenberg
30925337cb Updated Spanish and Catalan translations (Thanks to Gabriel Bonich). 2015-01-18 00:13:29 +02:00
Rolf Ahrenberg
63e47ad24a Reworded the README. 2015-01-17 20:02:18 +02:00
Rolf Ahrenberg
14123e160f Fixed the server parsing multiple times. 2015-01-17 19:42:21 +02:00
Rolf Ahrenberg
278d0478cf Added a command-line option to disable all the SAT>IP server quirks. 2015-01-17 17:29:21 +02:00
Rolf Ahrenberg
9989c36eee Delayed the server parameter parsing. 2015-01-17 16:47:19 +02:00
Rolf Ahrenberg
d2064f0c04 Added an option to disable sources via sources.conf. 2015-01-17 01:39:32 +02:00
Rolf Ahrenberg
714d3ed902 Increased the max number of disabled sources. 2015-01-17 00:45:30 +02:00
Rolf Ahrenberg
b466d6836e Added NULL checks for cSatipServer parameters. 2015-01-17 00:00:59 +02:00
Rolf Ahrenberg
184ddf2a53 Fixed a wrong parameter type. 2015-01-16 00:08:48 +02:00
Rolf Ahrenberg
65a2158051 Fixed some whitespaces. 2015-01-15 23:38:02 +02:00
Rolf Ahrenberg
e833ca6fdd Added a separate trace mode for pids. 2015-01-15 20:03:35 +02:00
Rolf Ahrenberg
c9abfddf11 Changed SATIP_USE_SINGLE_MODEL_SERVERS_ONLY into a command-line switch. 2015-01-15 19:27:02 +02:00
Rolf Ahrenberg
fb7a7fe3a2 Fixed parsing of the setup values. 2015-01-15 00:12:55 +02:00
Rolf Ahrenberg
3b9269e9de Added a separate trace mode for server discovery. 2015-01-14 22:59:56 +02:00
Rolf Ahrenberg
09e6c272cd Refactored cSatipPid for upcoming API changes. 2015-01-14 20:51:16 +02:00
Rolf Ahrenberg
266aadb999 Modified the model detection a bit more readable. 2015-01-14 20:34:12 +02:00
Rolf Ahrenberg
aed5a7820a Fixed 'length' typos. 2015-01-14 17:58:13 +02:00
Rolf Ahrenberg
bcb11b6257 Added a compile-time option to split any mixed model server into several single ones. 2015-01-13 21:45:14 +02:00
Rolf Ahrenberg
21261f8042 Clamp signal quality and level values. 2015-01-12 23:58:30 +02:00
Rolf Ahrenberg
2f11ad7a98 Added server parameter exanples. 2015-01-12 23:51:38 +02:00
Rolf Ahrenberg
83a0233780 Updated German translation (Thanks to Frank Neumann). 2015-01-12 13:09:09 +02:00
Rolf Ahrenberg
6f3715eb8b Merge pull request #5 from CvH/patch-1
Fixed a typo in firmware version.
2015-01-12 09:22:43 +02:00
CvH
92991cd144 fixed typo at fw version 2015-01-11 22:52:40 +01:00
Rolf Ahrenberg
304addbc00 Added missing CI/CAM translations. 2015-01-11 23:49:12 +02:00
Rolf Ahrenberg
26ff10ce1e Added configurable CI slots. 2015-01-11 16:34:32 +02:00
Rolf Ahrenberg
e654b3bbd2 Updated version number. 2015-01-11 16:33:42 +02:00
Rolf Ahrenberg
acea8748a4 Added SATIP_XCI variable for enabling CI support. 2015-01-10 18:30:07 +02:00
Rolf Ahrenberg
755f1049bb Reduced tuner sleep timeout to get better performance for pid updates. 2015-01-10 14:14:30 +02:00
Rolf Ahrenberg
2f6315280f Tweaked setting the pid update cache timer. 2015-01-09 19:56:43 +02:00
Rolf Ahrenberg
695dd53bfc Added initial support for x_ci parameter. 2015-01-09 16:38:02 +02:00
Rolf Ahrenberg
5fef77518e Changed the PMT debugging into a separate trace mode. 2015-01-09 02:06:20 +02:00
Rolf Ahrenberg
791767f02b Documented CI extension parameters. 2015-01-07 17:45:48 +02:00
Rolf Ahrenberg
0d52649dbd Added the missing translation item. 2015-01-06 21:41:52 +02:00
Rolf Ahrenberg
0c03c1b8d4 Added a CI extension item into the device info menu. 2015-01-06 19:46:56 +02:00
Rolf Ahrenberg
db59aa9c29 Added support for Digital Devices CI extension. 2015-01-06 15:53:31 +02:00
Rolf Ahrenberg
0fd559ce79 Added a fallback for older glibc libraries. 2015-01-05 20:24:45 +02:00
Rolf Ahrenberg
e10ce57210 Removed the unnecessary config directory definition. 2015-01-05 20:15:04 +02:00
Rolf Ahrenberg
c7f4b265d5 Fixed the server teardown. 2015-01-05 20:12:15 +02:00
Rolf Ahrenberg
35c0f25c38 Updated the command-line help and README. 2015-01-05 20:09:45 +02:00
34 changed files with 1400 additions and 478 deletions

49
HISTORY
View File

@@ -88,3 +88,52 @@ 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.

View File

@@ -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)

44
README
View File

@@ -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,24 @@ 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>|<model>|<description>;...'
vdr -P 'satip -s 192.168.0.1|DVBS2-2,DVBT2-2|Octo1'
vdr -P 'satip -s 192.168.0.1|DVBS2-4|Octo1;192.168.0.2|DVBT2-4|Octo2'
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 +70,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 +88,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".
@@ -113,12 +132,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

View File

@@ -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;
}

View File

@@ -13,8 +13,6 @@
#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_MAX_DEVICES MAXDEVICES #define SATIP_MAX_DEVICES MAXDEVICES
#define SATIP_BUFFER_SIZE KILOBYTE(1024) #define SATIP_BUFFER_SIZE KILOBYTE(1024)
@@ -29,12 +27,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) \
@@ -47,15 +48,15 @@
esyslog("curl_easy_perform() [%s,%d] failed: %s (%d)", __FILE__, __LINE__, curl_easy_strerror(res), res); \ esyslog("curl_easy_perform() [%s,%d] failed: %s (%d)", __FILE__, __LINE__, curl_easy_strerror(res), res); \
} }
#define ERROR_IF_FUNC(exp, errstr, func, ret) \ #define ERROR_IF_FUNC(exp, errstr, func, ret) \
do { \ do { \
if (exp) { \ if (exp) { \
char tmp[64]; \ char tmp[64]; \
esyslog("[%s,%d]: "errstr": %s", __FILE__, __LINE__, \ esyslog("[%s,%d]: "errstr": %s", __FILE__, __LINE__, \
strerror_r(errno, tmp, sizeof(tmp))); \ strerror_r(errno, tmp, sizeof(tmp))); \
func; \ func; \
ret; \ ret; \
} \ } \
} while (0) } while (0)
@@ -81,7 +82,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 +147,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

View File

@@ -14,56 +14,66 @@ 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),
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");
}

View File

@@ -16,11 +16,15 @@ 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;
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 {
@@ -31,24 +35,24 @@ public:
eOperatingModeCount eOperatingModeCount
}; };
enum eTraceMode { enum eTraceMode {
eTraceModeNormal = 0x0000, eTraceModeNormal = 0x0000,
eTraceModeDebug1 = 0x0001, eTraceModeDebug1 = 0x0001,
eTraceModeDebug2 = 0x0002, eTraceModeDebug2 = 0x0002,
eTraceModeDebug3 = 0x0004, eTraceModeDebug3 = 0x0004,
eTraceModeDebug4 = 0x0008, eTraceModeDebug4 = 0x0008,
eTraceModeDebug5 = 0x0010, eTraceModeDebug5 = 0x0010,
eTraceModeDebug6 = 0x0020, eTraceModeDebug6 = 0x0020,
eTraceModeDebug7 = 0x0040, eTraceModeDebug7 = 0x0040,
eTraceModeDebug8 = 0x0080, eTraceModeDebug8 = 0x0080,
eTraceModeDebug9 = 0x0100, eTraceModeDebug9 = 0x0100,
eTraceModeDebug10 = 0x0200, eTraceModeDebug10 = 0x0200,
eTraceModeDebug11 = 0x0400, eTraceModeDebug11 = 0x0400,
eTraceModeDebug12 = 0x0800, eTraceModeDebug12 = 0x0800,
eTraceModeDebug13 = 0x1000, eTraceModeDebug13 = 0x1000,
eTraceModeDebug14 = 0x2000, eTraceModeDebug14 = 0x2000,
eTraceModeDebug15 = 0x4000, eTraceModeDebug15 = 0x4000,
eTraceModeDebug16 = 0x8000, eTraceModeDebug16 = 0x8000,
eTraceModeMask = 0xFFFF eTraceModeMask = 0xFFFF
}; };
cSatipConfig(); cSatipConfig();
unsigned int GetOperatingMode(void) const { return operatingModeM; } unsigned int GetOperatingMode(void) const { return operatingModeM; }
@@ -59,9 +63,13 @@ 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; } 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;
@@ -69,9 +77,13 @@ public:
void SetOperatingMode(unsigned int operatingModeP) { operatingModeM = operatingModeP; } void SetOperatingMode(unsigned int operatingModeP) { operatingModeM = operatingModeP; }
void SetTraceMode(unsigned int modeP) { traceModeM = (modeP & eTraceModeMask); } void SetTraceMode(unsigned int modeP) { traceModeM = (modeP & eTraceModeMask); }
void SetCIExtension(unsigned int onOffP) { ciExtensionM = onOffP; }
void 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 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);
}; };

View File

@@ -217,7 +217,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 +330,19 @@ 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);
return true; return true;
} }
return false; return false;
@@ -345,7 +350,7 @@ 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->pid, 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);
@@ -357,7 +362,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 +376,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 +411,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 +433,33 @@ 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;
}
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 +503,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 +517,6 @@ bool cSatipDevice::GetTSPacket(uchar *&dataP)
return true; return true;
} }
} }
#endif
dataP = GetData(); dataP = GetData();
return true; return true;
} }

View File

@@ -108,6 +108,8 @@ 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);
}; };
#endif // __SATIP_DEVICE_H #endif // __SATIP_DEVICE_H

View File

@@ -14,6 +14,8 @@ 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;
private: private:
cSatipDeviceIf(const cSatipDeviceIf&); cSatipDeviceIf(const cSatipDeviceIf&);

View File

@@ -47,43 +47,14 @@ 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::DataCallback(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->dataBufferM.Add(ptrP, len);
const char *desc = NULL, *model = NULL, *addr = NULL;
#ifdef USE_TINYXML
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);
}
return len; return len;
} }
@@ -120,6 +91,7 @@ int cSatipDiscover::DebugCallback(CURL *handleP, curl_infotype typeP, char *data
cSatipDiscover::cSatipDiscover() cSatipDiscover::cSatipDiscover()
: cThread("SATIP discover"), : cThread("SATIP discover"),
mutexM(), mutexM(),
dataBufferM(),
msearchM(*this), msearchM(*this),
probeUrlListM(), probeUrlListM(),
handleM(curl_easy_init()), handleM(curl_easy_init()),
@@ -170,7 +142,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 +167,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;
@@ -204,7 +177,7 @@ void cSatipDiscover::Fetch(const char *urlP)
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_DEBUGDATA, this); SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_DEBUGDATA, this);
// Set callback // Set callback
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEFUNCTION, cSatipDiscover::WriteCallback); 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 +197,75 @@ 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);
dataBufferM.Reset();
}
else
error("Discovery detected invalid status code: %ld", rc); error("Discovery detected invalid status code: %ld", rc);
} }
} }
void cSatipDiscover::ParseDeviceInfo(const char *addrP)
{
debug1("%s (%s)", __PRETTY_FUNCTION__, addrP);
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, model, desc);
}
void cSatipDiscover::AddServer(const char *addrP, const char *modelP, const char * descP) void cSatipDiscover::AddServer(const char *addrP, const char *modelP, const char * descP)
{ {
debug1("%s (%s, %s, %s)", __PRETTY_FUNCTION__, addrP, modelP, descP); debug1("%s (%s, %s, %s)", __PRETTY_FUNCTION__, addrP, modelP, descP);
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;
if (!serversM.Update(tmp)) { char *s, *p = strdup(modelP);
info("Adding server '%s|%s|%s'", tmp->Address(), tmp->Model(), tmp->Description()); char *r = strtok_r(p, ",", &s);
serversM.Add(tmp); while (r) {
r = skipspace(r);
cString desc = cString::sprintf("%s #%d", !isempty(descP) ? descP : "MyBrokenHardware", n++);
cSatipServer *tmp = new cSatipServer(addrP, r, desc);
if (!serversM.Update(tmp)) {
info("Adding server '%s|%s|%s' CI: %s Quirks: %s", tmp->Address(), tmp->Model(), tmp->Description(), tmp->HasCI() ? "yes" : "no", tmp->HasQuirk() ? tmp->Quirks() : "none");
serversM.Add(tmp);
}
else
DELETENULL(tmp);
r = strtok_r(NULL, ",", &s);
}
FREE_POINTER(p);
}
else {
cSatipServer *tmp = new cSatipServer(addrP, modelP, descP);
if (!serversM.Update(tmp)) {
info("Adding server '%s|%s|%s' CI: %s Quirks: %s", tmp->Address(), tmp->Model(), tmp->Description(), tmp->HasCI() ? "yes" : "no", tmp->HasQuirk() ? tmp->Quirks() : "none");
serversM.Add(tmp);
}
else
DELETENULL(tmp);
} }
else
DELETENULL(tmp);
} }
int cSatipDiscover::GetServerCount(void) int cSatipDiscover::GetServerCount(void)
@@ -250,11 +275,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 +317,39 @@ cString cSatipDiscover::GetServerList(void)
return serversM.List(); return serversM.List();
} }
void cSatipDiscover::SetTransponder(cSatipServer *serverP, int transponderP) void cSatipDiscover::AttachServer(cSatipServer *serverP, int deviceIdP, int transponderP)
{ {
debug16("%s (, %d)", __PRETTY_FUNCTION__, transponderP); debug16("%s (, %d, %d)", __PRETTY_FUNCTION__, deviceIdP, transponderP);
cMutexLock MutexLock(&mutexM); cMutexLock MutexLock(&mutexM);
serversM.SetTransponder(serverP, transponderP); serversM.Attach(serverP, deviceIdP, transponderP);
} }
void cSatipDiscover::UseServer(cSatipServer *serverP, bool onOffP) void cSatipDiscover::DetachServer(cSatipServer *serverP, int deviceIdP, int transponderP)
{ {
debug16("%s (, %d)", __PRETTY_FUNCTION__, onOffP); debug16("%s (, %d, %d)", __PRETTY_FUNCTION__, deviceIdP, transponderP);
cMutexLock MutexLock(&mutexM); cMutexLock MutexLock(&mutexM);
serversM.Use(serverP, onOffP); 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::NumProvidedSystems(void) int cSatipDiscover::NumProvidedSystems(void)

View File

@@ -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"
@@ -39,15 +40,17 @@ class cSatipDiscoverServers : public cList<cSatipDiscoverServer> {
class cSatipDiscover : public cThread, public cSatipDiscoverIf { class cSatipDiscover : public cThread, public cSatipDiscoverIf {
private: private:
enum { enum {
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 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 dataBufferM;
cSatipMsearch msearchM; cSatipMsearch msearchM;
cStringList probeUrlListM; cStringList probeUrlListM;
CURL *handleM; CURL *handleM;
@@ -56,6 +59,7 @@ private:
cSatipServers serversM; cSatipServers serversM;
void Activate(void); void Activate(void);
void Deactivate(void); void Deactivate(void);
void ParseDeviceInfo(const char *addrP);
void AddServer(const char *addrP, const char *modelP, const char *descP); void AddServer(const char *addrP, const char *modelP, const char *descP);
void Fetch(const char *urlP); void Fetch(const char *urlP);
// constructor // constructor
@@ -74,12 +78,16 @@ 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 AttachServer(cSatipServer *serverP, int deviceIdP, int transponderP);
void UseServer(cSatipServer *serverP, bool onOffP); void DetachServer(cSatipServer *serverP, int deviceIdP, int transponderP);
bool IsServerQuirk(cSatipServer *serverP, int quirkP);
bool HasServerCI(cSatipServer *serverP);
cString GetServerAddress(cSatipServer *serverP);
cString GetServerList(void); cString GetServerList(void);
int NumProvidedSystems(void); int NumProvidedSystems(void);

7
log.h
View File

@@ -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

View File

@@ -35,6 +35,7 @@ cSatipMsearch::cSatipMsearch(cSatipDiscoverIf &discoverP)
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,8 +97,6 @@ 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());
} }
} }

28
param.c
View File

@@ -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,32 +158,37 @@ 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);
}
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, "&src=%d", ((src > 0) && (src <= 255)) ? src : 1);
ST(" S *") q += snprintf(q, STBUFLEFT, "&sr=%d", channelP->Srate()); ST(" S *") q += snprintf(q, STBUFLEFT, "&sr=%d", channelP->Srate());
ST("C 1") 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("C T2") q += snprintf(q, STBUFLEFT, "&plp=%d", dtp.StreamId());
ST(" T2") q += snprintf(q, STBUFLEFT, "&t2id=%d", T2SystemId); ST(" T2") q += snprintf(q, STBUFLEFT, "&t2id=%d", dtp.T2SystemId());
ST("C 2") q += snprintf(q, STBUFLEFT, "&c2tft=%d", C2TuningFrequencyType); ST("C 2") q += snprintf(q, STBUFLEFT, "&c2tft=%d", C2TuningFrequencyType);
ST("C 2") q += snprintf(q, STBUFLEFT, "&ds=%d", DataSlice); ST("C 2") q += snprintf(q, STBUFLEFT, "&ds=%d", DataSlice);
ST("C 1") q += PrintUrlString(q, STBUFLEFT, dtp.Inversion(), SatipInversionValues); ST("C 1") q += PrintUrlString(q, STBUFLEFT, dtp.Inversion(), SatipInversionValues);
ST(" T2") q += PrintUrlString(q, STBUFLEFT, SisoMiso, SatipSisoMisoValues); ST(" T2") q += PrintUrlString(q, STBUFLEFT, dtp.SisoMiso(), SatipSisoMisoValues);
ST(" T*") q += PrintUrlString(q, STBUFLEFT, dtp.Bandwidth(), SatipBandwidthValues); ST(" T*") q += PrintUrlString(q, STBUFLEFT, dtp.Bandwidth(), SatipBandwidthValues);
ST("C 2") q += PrintUrlString(q, STBUFLEFT, dtp.Bandwidth(), SatipBandwidthValues); ST("C 2") q += PrintUrlString(q, STBUFLEFT, dtp.Bandwidth(), SatipBandwidthValues);
ST(" T*") q += PrintUrlString(q, STBUFLEFT, dtp.Guard(), SatipGuardValues); ST(" T*") q += PrintUrlString(q, STBUFLEFT, dtp.Guard(), SatipGuardValues);
ST("CST*") q += PrintUrlString(q, STBUFLEFT, dtp.CoderateH(), SatipCodeRateValues); ST("CST*") q += PrintUrlString(q, STBUFLEFT, dtp.CoderateH(), SatipCodeRateValues);
ST(" S 2") q += PrintUrlString(q, STBUFLEFT, Pilot, SatipPilotValues); ST(" S *") q += PrintUrlString(q, STBUFLEFT, dtp.Pilot(), SatipPilotValues);
ST(" S 2") q += PrintUrlString(q, STBUFLEFT, dtp.Modulation(), SatipModulationValues); ST(" S *") q += PrintUrlString(q, STBUFLEFT, dtp.Modulation(), SatipModulationValues);
ST(" T*") 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("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.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) if ((channelP->Rid() % 100) > 0)
q += snprintf(q, STBUFLEFT, "&fe=%d", channelP->Rid()); snprintf(q, STBUFLEFT, "&fe=%d", channelP->Rid() % 100);
#undef ST #undef ST
return buffer; return buffer;
} }

View File

@@ -1,14 +1,14 @@
# VDR plugin language source file. # VDR plugin language source file.
# Copyright (C) 2007-2014 Rolf Ahrenberg # Copyright (C) 2007-2015 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.2.2\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: 2015-04-26 04:26+0300\n"
"PO-Revision-Date: 2014-12-24 12:24+0200\n" "PO-Revision-Date: 2015-04-26 04:26+0300\n"
"Last-Translator: Gabriel Bonich <gbonich@gmail.com>\n" "Last-Translator: Gabriel Bonich <gbonich@gmail.com>\n"
"Language-Team: Catalan <vdr@linuxtv.org>\n" "Language-Team: Catalan <vdr@linuxtv.org>\n"
"Language: ca\n" "Language: ca\n"
@@ -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ó"
@@ -83,7 +86,7 @@ msgid "high"
msgstr "Alt" msgstr "Alt"
msgid "Button$Devices" msgid "Button$Devices"
msgstr "" msgstr "Dispositius"
msgid "Operating mode" msgid "Operating mode"
msgstr "Mode de operació" msgstr "Mode de operació"
@@ -96,13 +99,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 +143,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 +153,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"
@@ -149,7 +179,7 @@ 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 "Active SAT>IP servers:"
msgstr "" msgstr "Activa SAT>IP servers:"
msgid "Help" msgid "Help"
msgstr "Ajuda" msgstr "Ajuda"

View File

@@ -1,14 +1,14 @@
# VDR plugin language source file. # VDR plugin language source file.
# Copyright (C) 2007-2014 Rolf Ahrenberg # Copyright (C) 2007-2015 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-2015
# #
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: vdr-satip 1.0.0\n" "Project-Id-Version: vdr-satip 2.2.2\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: 2015-04-26 04:26+0300\n"
"PO-Revision-Date: 2014-12-24 12:24+0200\n" "PO-Revision-Date: 2015-04-26 04:26+0300\n"
"Last-Translator: Frank Neumann <fnu@yavdr.org>\n" "Last-Translator: Frank Neumann <fnu@yavdr.org>\n"
"Language-Team: German <vdr@linuxtv.org>\n" "Language-Team: German <vdr@linuxtv.org>\n"
"Language: de\n" "Language: de\n"
@@ -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"
@@ -83,7 +86,7 @@ msgid "high"
msgstr "hoch" msgstr "hoch"
msgid "Button$Devices" msgid "Button$Devices"
msgstr "" msgstr "Geräte"
msgid "Operating mode" msgid "Operating mode"
msgstr "Betriebsmodus" msgstr "Betriebsmodus"
@@ -103,6 +106,30 @@ msgstr ""
"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 +138,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 +153,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"
@@ -152,7 +179,7 @@ msgid "Define an ill-behaving filter to be blacklisted."
msgstr "Bestimme einen fehlerhaften Filter der ausgeblendet werden soll." msgstr "Bestimme einen fehlerhaften Filter der ausgeblendet werden soll."
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"

View File

@@ -1,14 +1,14 @@
# VDR plugin language source file. # VDR plugin language source file.
# Copyright (C) 2007-2014 Rolf Ahrenberg # Copyright (C) 2007-2015 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.2.2\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: 2015-04-26 04:26+0300\n"
"PO-Revision-Date: 2014-12-24 12:24+0200\n" "PO-Revision-Date: 2015-04-26 04:26+0300\n"
"Last-Translator: Gabriel Bonich <gbonich@gmail.com>\n" "Last-Translator: Gabriel Bonich <gbonich@gmail.com>\n"
"Language-Team: Spanish <vdr@linuxtv.org>\n" "Language-Team: Spanish <vdr@linuxtv.org>\n"
"Language: es\n" "Language: es\n"
@@ -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"
@@ -83,7 +86,7 @@ msgid "high"
msgstr "Alto" msgstr "Alto"
msgid "Button$Devices" msgid "Button$Devices"
msgstr "" msgstr "Dispositivos"
msgid "Operating mode" msgid "Operating mode"
msgstr "Modo de operación" msgstr "Modo de operación"
@@ -103,6 +106,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 +143,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 +153,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"
@@ -149,7 +179,7 @@ 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 "Active SAT>IP servers:"
msgstr "" msgstr "Activa SAT>IP servers:"
msgid "Help" msgid "Help"
msgstr "Ayuda" msgstr "Ayuda"

View File

@@ -1,14 +1,14 @@
# VDR plugin language source file. # VDR plugin language source file.
# Copyright (C) 2007-2014 Rolf Ahrenberg # Copyright (C) 2007-2015 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
# #
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: vdr-satip 1.0.0\n" "Project-Id-Version: vdr-satip 2.2.2\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: 2015-04-26 04:26+0300\n"
"PO-Revision-Date: 2014-12-24 12:24+0200\n" "PO-Revision-Date: 2015-04-26 04:26+0300\n"
"Last-Translator: Rolf Ahrenberg\n" "Last-Translator: Rolf Ahrenberg\n"
"Language-Team: Finnish <vdr@linuxtv.org>\n" "Language-Team: Finnish <vdr@linuxtv.org>\n"
"Language: fi\n" "Language: fi\n"
@@ -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"
@@ -102,6 +105,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ä"

6
rtcp.c
View File

@@ -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)
@@ -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,6 @@ 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());
} }
} }

2
rtcp.h
View File

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

11
rtp.c
View File

@@ -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,15 +130,12 @@ 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());

2
rtp.h
View File

@@ -25,7 +25,7 @@ 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); cSatipRtp(cSatipTunerIf &tunerP);

201
rtsp.c
View File

@@ -15,9 +15,14 @@
cSatipRtsp::cSatipRtsp(cSatipTunerIf &tunerP) cSatipRtsp::cSatipRtsp(cSatipTunerIf &tunerP)
: tunerM(tunerP), : tunerM(tunerP),
headerBufferM(),
dataBufferM(),
modeM(cmUnicast), modeM(cmUnicast),
handleM(NULL), handleM(NULL),
headerListM(NULL) headerListM(NULL),
errorNoMoreM(""),
errorOutOfRangeM(""),
errorCheckSyntaxM("")
{ {
debug1("%s [device %d]", __PRETTY_FUNCTION__, tunerM.GetId()); debug1("%s [device %d]", __PRETTY_FUNCTION__, tunerM.GetId());
Create(); Create();
@@ -29,46 +34,26 @@ 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; return len;
} }
@@ -216,10 +201,22 @@ 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_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 +250,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 +279,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 +308,15 @@ 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_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 +328,122 @@ 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);
}
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) {
result = true; case 200:
else if (rc != 0) { result = true;
char *url = NULL; break;
SATIP_CURL_EASY_GETINFO(handleM, CURLINFO_EFFECTIVE_URL, &url); case 400:
error("Detected invalid status code %ld: %s [device %d]", rc, url, tunerM.GetId()); // 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());
break;
}
case 503:
// SETUP PLAY
// The message body of the response may contain the "No-More:" parameter followed
// by a space-separated list of the missing ressources: “sessions” "frontends" "pids
if (!isempty(*errorNoMoreM)) {
SATIP_CURL_EASY_GETINFO(handleM, CURLINFO_EFFECTIVE_URL, &url);
error("No more: %s (error code %ld: %s) [device %d]", *errorNoMoreM, rc, url, tunerM.GetId());
break;
}
default:
SATIP_CURL_EASY_GETINFO(handleM, CURLINFO_EFFECTIVE_URL, &url);
error("Detected invalid status code %ld: %s [device %d]", rc, url, tunerM.GetId());
break;
}
if (rcP) 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;

12
rtsp.h
View File

@@ -15,12 +15,13 @@
#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 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 {
@@ -29,12 +30,19 @@ private:
enum eCommunicationMode { cmUnicast, cmMulticast }; enum eCommunicationMode { cmUnicast, cmMulticast };
cSatipTunerIf &tunerM; cSatipTunerIf &tunerM;
cSatipMemoryBuffer headerBufferM;
cSatipMemoryBuffer dataBufferM;
eCommunicationMode modeM; eCommunicationMode modeM;
CURL *handleM; CURL *handleM;
struct curl_slist *headerListM; struct curl_slist *headerListM;
cString errorNoMoreM;
cString errorOutOfRangeM;
cString errorCheckSyntaxM;
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

119
satip.c
View File

@@ -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 < 20200
#error "VDR-2.0.0 API version or greater is required!" #error "VDR-2.2.0 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.2.2" GITVERSION;
static const char DESCRIPTION[] = trNOOP("SAT>IP Devices"); static const char DESCRIPTION[] = trNOOP("SAT>IP Devices");
class cPluginSatip : public cPlugin { class cPluginSatip : public cPlugin {
@@ -35,6 +35,7 @@ private:
unsigned int deviceCountM; unsigned int deviceCountM;
cSatipDiscoverServers *serversM; cSatipDiscoverServers *serversM;
void ParseServer(const char *paramP); void ParseServer(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 +62,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 +82,12 @@ 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"
" -t <mode>, --trace=<mode> set the tracing mode\n"
" -s <ipaddr>|<model>|<desc>, --server=<ipaddr1>|<model1>|<desc1>;<ipaddr2>|<model2>|<desc2>\n" " -s <ipaddr>|<model>|<desc>, --server=<ipaddr1>|<model1>|<desc1>;<ipaddr2>|<model2>|<desc2>\n"
" define hard-coded SAT>IP server(s)\n"; " define hard-coded SAT>IP server(s)\n"
" -D, --detach set the detached mode on\n"
" -S, --single set the single model server mode on\n"
" -n, --noquirks disable all the server quirks\n";
} }
bool cPluginSatip::ProcessArgs(int argc, char *argv[]) bool cPluginSatip::ProcessArgs(int argc, char *argv[])
@@ -90,14 +95,18 @@ bool cPluginSatip::ProcessArgs(int argc, char *argv[])
debug1("%s", __PRETTY_FUNCTION__); debug1("%s", __PRETTY_FUNCTION__);
// Implement command line argument processing here if applicable. // Implement command line argument processing here if applicable.
static const struct option long_options[] = { static const struct option long_options[] = {
{ "devices", required_argument, NULL, 'd' }, { "devices", required_argument, NULL, 'd' },
{ "trace", required_argument, NULL, 't' }, { "trace", required_argument, NULL, 't' },
{ "server", required_argument, NULL, 's' }, { "server", required_argument, NULL, 's' },
{ NULL, no_argument, NULL, 0 } { "detach", no_argument, NULL, 'D' },
{ "single", no_argument, NULL, 'S' },
{ "noquirks", no_argument, NULL, 'n' },
{ NULL, no_argument, NULL, 0 }
}; };
cString server;
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: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 +115,24 @@ 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; break;
default: default:
return false; return false;
} }
} }
// this must be done after all parameters are parsed
if (!isempty(*server))
ParseServer(*server);
return true; return true;
} }
@@ -121,7 +142,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,7 +217,7 @@ 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);
@@ -232,13 +252,32 @@ void cPluginSatip::ParseServer(const char *paramP)
++n; ++n;
r = strtok_r(NULL, ";", &s); r = strtok_r(NULL, ";", &s);
} }
FREE_POINTER(p);
}
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 +285,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 +299,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 +314,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,7 +336,7 @@ 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)
@@ -321,8 +371,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 +443,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 +474,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));

366
server.c
View File

@@ -12,77 +12,140 @@
#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 char *modelP, const char *descriptionP)
: addressM(addressP), : addressM((addressP && *addressP) ? addressP : "0.0.0.0"),
modelM(modelP), modelM((modelP && *modelP) ? modelP : "DVBS-1"),
descriptionM(descriptionP), descriptionM(!isempty(descriptionP) ? descriptionP : "MyBrokenHardware"),
modelTypeM(eSatipModelTypeNone), quirksM(""),
quirkM(eSatipQuirkNone), quirkM(eSatipQuirkNone),
useCountM(0), hasCiM(false),
transponderM(0),
createdM(time(NULL)), createdM(time(NULL)),
lastSeenM(0) lastSeenM(0)
{ {
memset(modelCountM, 0, sizeof(modelCountM)); if (!SatipConfig.GetDisableServerQuirks()) {
if (isempty(*modelM))
modelM = "DVBS-1";
if (!isempty(*descriptionM)) {
// 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 ?
if (strstr(*descriptionM, "GSSBOX") || // Grundig Sat Systems GSS.box DSI 400 if (strstr(*descriptionM, "GSSBOX") || // Grundig Sat Systems GSS.box DSI 400
strstr(*descriptionM, "DIGIBIT") || // Telestar Digibit R1 strstr(*descriptionM, "DIGIBIT") || // Telestar Digibit R1
strstr(*descriptionM, "Triax SatIP Converter") // Triax TSS 400 strstr(*descriptionM, "Triax SatIP Converter") // Triax TSS 400
) ) {
quirkM |= eSatipQuirkSessionId; quirkM |= eSatipQuirkSessionId;
quirksM = cString::sprintf("%s%sSessionId", *quirksM, isempty(*quirksM) ? "" : ",");
}
// These devices contain 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;
quirksM = cString::sprintf("%s%sPlayPids", *quirksM, isempty(*quirksM) ? "" : ",");
}
// These devices contain a frontend locking bug: // These devices contain a frontend locking bug:
if (strstr(*descriptionM, "fritzdvbc")) // Fritz!WLAN Repeater DVB-C if (strstr(*descriptionM, "fritzdvbc") // Fritz!WLAN Repeater DVB-C
) {
quirkM |= eSatipQuirkForceLock; quirkM |= eSatipQuirkForceLock;
if (quirkM != eSatipQuirkNone) quirksM = cString::sprintf("%s%sForceLock", *quirksM, isempty(*quirksM) ? "" : ",");
info("Malfunctioning '%s' server detected! Please, fix the firmware.", *descriptionM); }
} debug3("%s description=%s quirks=%s", __PRETTY_FUNCTION__, *descriptionM, *quirksM);
}
// These devices support the X_PMT protocol extension
if (strstr(*descriptionM, "OctopusNet")) // Digital Devices OctopusNet
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);
} }
@@ -96,15 +159,105 @@ 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::Assign(int deviceIdP, int sourceP, int systemP, int transponderP)
{ {
if (onOffP) bool result = false;
++useCountM; if (cSource::IsType(sourceP, 'S'))
else result = frontendsM[eSatipFrontendDVBS2].Assign(deviceIdP, transponderP);
--useCountM; else if (cSource::IsType(sourceP, 'T')) {
if (systemP)
result = frontendsM[eSatipFrontendDVBT2].Assign(deviceIdP, transponderP);
else
result = frontendsM[eSatipFrontendDVBT].Assign(deviceIdP, transponderP) || frontendsM[eSatipFrontendDVBT2].Assign(deviceIdP, transponderP);
}
else if (cSource::IsType(sourceP, 'C')) {
if (systemP)
result = frontendsM[eSatipFrontendDVBC2].Assign(deviceIdP, transponderP);
else
result = frontendsM[eSatipFrontendDVBC].Assign(deviceIdP, transponderP) || frontendsM[eSatipFrontendDVBC2].Assign(deviceIdP, transponderP);
}
return result;
}
bool cSatipServer::Matches(int 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 (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 +265,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->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->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 +304,50 @@ cSatipServer *cSatipServers::Update(cSatipServer *serverP)
return NULL; return NULL;
} }
void cSatipServers::Use(cSatipServer *serverP, bool onOffP) void cSatipServers::Attach(cSatipServer *serverP, int deviceIdP, int transponderP)
{ {
for (cSatipServer *s = First(); s; s = Next(s)) { for (cSatipServer *s = First(); s; s = Next(s)) {
if (s == serverP) { if (s == serverP) {
s->Use(onOffP); s->Attach(deviceIdP, transponderP);
break; 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 +358,18 @@ 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;
}
cString cSatipServers::GetString(cSatipServer *serverP) cString cSatipServers::GetString(cSatipServer *serverP)
{ {
cString list = ""; cString list = "";
@@ -213,13 +395,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;
} }

112
server.h
View File

@@ -8,26 +8,59 @@
#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
}; };
cString addressM; cString addressM;
cString modelM; cString modelM;
cString descriptionM; cString descriptionM;
int modelCountM[eSatipModuleCount]; cString quirksM;
int modelTypeM; cSatipFrontends frontendsM[eSatipFrontendCount];
int quirkM; int quirkM;
int useCountM; bool hasCiM;
int transponderM;
time_t createdM; time_t createdM;
cTimeMs lastSeenM; cTimeMs lastSeenM;
@@ -39,36 +72,29 @@ public:
eSatipQuirkForceLock = 0x04, eSatipQuirkForceLock = 0x04,
eSatipQuirkMask = 0x0F eSatipQuirkMask = 0x0F
}; };
enum eSatipModelType {
eSatipModelTypeNone = 0x00,
eSatipModelTypeDVBS2 = 0x01,
eSatipModelTypeDVBT = 0x02,
eSatipModelTypeDVBT2 = 0x04,
eSatipModelTypeDVBC = 0x08,
eSatipModelTypeDVBC2 = 0x10,
eSatipModelTypeMask = 0xFF
};
cSatipServer(const char *addressP, const char *modelP, const char *descriptionP); 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);
const char *Model(void) { return *modelM; } int GetModulesDVBS2(void);
const char *Description() { return *descriptionM; } int GetModulesDVBT(void);
bool Quirk(int quirkP) { return ((quirkP & eSatipQuirkMask) & quirkM); } int GetModulesDVBT2(void);
int ModelType(void) { return modelTypeM; } int GetModulesDVBC(void);
bool Match(int modelP) { return ((modelP & eSatipModelTypeMask) & modelTypeM); } int GetModulesDVBC2(void);
int Cable() { return Match(eSatipModelTypeDVBC) ? modelCountM[eSatipModuleDVBC] : 0; } const char *Address(void) { return *addressM; }
int Cable2() { return Match(eSatipModelTypeDVBC2) ? modelCountM[eSatipModuleDVBC2] : 0; } const char *Model(void) { return *modelM; }
int Satellite() { return Match(eSatipModelTypeDVBS2) ? modelCountM[eSatipModuleDVBS2] : 0; } const char *Description(void) { return *descriptionM; }
int Terrestrial() { return Match(eSatipModelTypeDVBT) ? modelCountM[eSatipModuleDVBT] : 0; } const char *Quirks(void) { return *quirksM; }
int Terrestrial2() { return Match(eSatipModelTypeDVBT2) ? modelCountM[eSatipModuleDVBT2] : 0; } bool Quirk(int quirkP) { return ((quirkP & eSatipQuirkMask) & quirkM); }
void Update(void) { lastSeenM.Set(); } bool HasQuirk(void) { return (quirkM != eSatipQuirkNone); }
uint64_t LastSeen(void) { return lastSeenM.Elapsed(); } bool HasCI(void) { return hasCiM; }
time_t Created(void) { return createdM; } void Update(void) { lastSeenM.Set(); }
uint64_t LastSeen(void) { return lastSeenM.Elapsed(); }
time_t Created(void) { return createdM; }
}; };
// --- cSatipServers ---------------------------------------------------------- // --- cSatipServers ----------------------------------------------------------
@@ -76,11 +102,15 @@ 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 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);
cString List(void); cString List(void);
int NumProvidedSystems(void); int NumProvidedSystems(void);

62
setup.c
View File

@@ -89,6 +89,7 @@ private:
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);
@@ -103,6 +104,7 @@ cSatipServerInfo::cSatipServerInfo(cSatipServer *serverP)
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);
@@ -119,6 +121,7 @@ void cSatipServerInfo::Setup(void)
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));
} }
@@ -327,8 +330,10 @@ eOSState cSatipMenuInfo::ProcessKey(eKeys keyP)
// --- cSatipPluginSetup ------------------------------------------------------ // --- cSatipPluginSetup ------------------------------------------------------
cSatipPluginSetup::cSatipPluginSetup() cSatipPluginSetup::cSatipPluginSetup()
: deviceCountM(0), : detachedModeM(SatipConfig.GetDetachedMode()),
deviceCountM(0),
operatingModeM(SatipConfig.GetOperatingMode()), operatingModeM(SatipConfig.GetOperatingMode()),
ciExtensionM(SatipConfig.GetCIExtension()),
eitScanM(SatipConfig.GetEITScan()), eitScanM(SatipConfig.GetEITScan()),
numDisabledSourcesM(SatipConfig.GetDisabledSourcesCount()), numDisabledSourcesM(SatipConfig.GetDisabledSourcesCount()),
numDisabledFiltersM(SatipConfig.GetDisabledFiltersCount()) numDisabledFiltersM(SatipConfig.GetDisabledFiltersCount())
@@ -338,6 +343,10 @@ 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");
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 +373,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."));
@@ -386,12 +403,15 @@ void cSatipPluginSetup::Setup(void)
Add(new cOsdItem(tr("Active SAT>IP servers:"), osUnknown, false)); Add(new cOsdItem(tr("Active SAT>IP servers:"), osUnknown, false));
helpM.Append(""); helpM.Append("");
cSatipServers *servers = cSatipDiscover::GetInstance()->GetServers(); detachedModeM = SatipConfig.GetDetachedMode();
deviceCountM = servers->Count(); if (!detachedModeM) {
for (cSatipServer *s = servers->First(); s; s = servers->Next(s)) { cSatipServers *servers = cSatipDiscover::GetInstance()->GetServers();
Add(new cSatipServerItem(s)); deviceCountM = servers->Count();
helpM.Append(""); for (cSatipServer *s = servers->First(); s; s = servers->Next(s)) {
} Add(new cSatipServerItem(s));
helpM.Append("");
}
}
SetCurrent(Get(current)); SetCurrent(Get(current));
Display(); Display();
@@ -440,6 +460,7 @@ 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);
@@ -463,7 +484,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 +495,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 +523,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 +539,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 +547,17 @@ void cSatipPluginSetup::Store(void)
{ {
// Store values into setup.conf // Store values into setup.conf
SetupStore("OperatingMode", operatingModeM); SetupStore("OperatingMode", operatingModeM);
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.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)

View File

@@ -15,9 +15,13 @@
class cSatipPluginSetup : public cMenuSetupPage class cSatipPluginSetup : public cMenuSetupPage
{ {
private: private:
bool detachedModeM;
int deviceCountM; int deviceCountM;
int operatingModeM; int operatingModeM;
const char *operatingModeTextsM[cSatipConfig::eOperatingModeCount]; const char *operatingModeTextsM[cSatipConfig::eOperatingModeCount];
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 +35,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);

View File

@@ -129,18 +129,24 @@ int cSatipSocket::Read(unsigned char *bufferAddrP, unsigned int bufferLenP)
if (len > 0) if (len > 0)
return len; 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 +159,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; count = (int)recvmmsg(socketDescM, mmsgh, elementCountP, MSG_DONTWAIT, NULL);
if (socketDescM && bufferAddrP && elementRecvSizeP && (elementCountP > 0) && (elementBufferSizeP > 0))
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;

77
tuner.c
View File

@@ -25,8 +25,8 @@ cSatipTuner::cSatipTuner(cSatipDeviceIf &deviceP, unsigned int packetLenP)
rtcpM(*this), rtcpM(*this),
streamAddrM(""), streamAddrM(""),
streamParamM(""), streamParamM(""),
currentServerM(NULL), currentServerM(NULL, deviceP.GetId(), 0),
nextServerM(NULL), nextServerM(NULL, deviceP.GetId(), 0),
mutexM(), mutexM(),
reConnectM(), reConnectM(),
keepAliveM(), keepAliveM(),
@@ -40,7 +40,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()
@@ -117,7 +119,7 @@ void cSatipTuner::Action(void)
// 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;
@@ -186,8 +188,6 @@ bool cSatipTuner::Connect(void)
// 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);
@@ -197,15 +197,15 @@ 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);
// 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())) {
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;
} }
} }
@@ -226,6 +226,8 @@ bool cSatipTuner::Disconnect(void)
if (!isempty(*streamAddrM) && (streamIdM >= 0)) { if (!isempty(*streamAddrM) && (streamIdM >= 0)) {
cString uri = cString::sprintf("rtsp://%s/stream=%d", *streamAddrM, streamIdM); cString uri = cString::sprintf("rtsp://%s/stream=%d", *streamAddrM, streamIdM);
rtspM.Teardown(*uri); rtspM.Teardown(*uri);
// some devices requires a teardown for TCP connection also
rtspM.Reset();
streamIdM = -1; streamIdM = -1;
} }
@@ -233,11 +235,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();
@@ -283,6 +286,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 +296,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 +314,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;
} }
@@ -328,7 +334,7 @@ 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;
} }
@@ -339,15 +345,15 @@ int cSatipTuner::GetId(void)
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);
// Reconnect // Reconnect
RequestState(tsSet, smExternal); RequestState(tsSet, smExternal);
@@ -375,8 +381,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;
@@ -389,7 +394,8 @@ bool cSatipTuner::UpdatePids(bool forceP)
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("rtsp://%s/stream=%d", *streamAddrM, 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 +408,23 @@ 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) {
// 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;
}
pidUpdateCacheM.Set(ePidUpdateIntervalMs);
if (!rtspM.Play(*uri)) if (!rtspM.Play(*uri))
return false; return false;
addPidsM.Clear(); addPidsM.Clear();
@@ -539,6 +562,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,7 +589,7 @@ 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)

52
tuner.h
View File

@@ -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,18 +29,13 @@ 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)
{ {
@@ -61,6 +49,29 @@ 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) : ""; }
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,7 +79,7 @@ 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
@@ -85,8 +96,8 @@ private:
cSatipRtcp rtcpM; cSatipRtcp rtcpM;
cString streamAddrM; cString streamAddrM;
cString streamParamM; cString streamParamM;
cSatipServer *currentServerM; cSatipTunerServer currentServerM;
cSatipServer *nextServerM; cSatipTunerServer nextServerM;
cMutex mutexM; cMutex mutexM;
cTimeMs reConnectM; cTimeMs reConnectM;
cTimeMs keepAliveM; cTimeMs keepAliveM;
@@ -100,7 +111,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;
@@ -123,10 +136,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);

View File

@@ -12,8 +12,8 @@ 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 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 int GetId(void) = 0; virtual int GetId(void) = 0;