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

73 Commits

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

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

37
HISTORY
View File

@@ -156,3 +156,40 @@ VDR Plugin 'satip' Revision History
- Added multicast and RTP-over-TCP support.
- Added support for activating/deactivating server on-the-fly.
- Extended command-line parameters for setting server quirks.
2017-08-15: Version 2.2.5
- Added Polish translation (Thanks to Tomasz Nowak).
- Updated Catalan and Spanish translations (Thanks to Gabriel Bonich).
- Added support for KATHREIN SatIP Server (Thanks to kavanu).
- Added support for FRITZ!Box 6490 Cable (Thanks to 9000h).
- Updated FRITZ!WLAN Repeater DVB-C detection for the latest firmware (Thanks to 9000h).
- Added GCC7 compatibility (Thanks to Sascha Kuehndel).
===================================
VDR Plugin 'satip' Revision History
===================================
2016-12-18: Version 2.3.0
- Updated for vdr-2.3.1.
- Updated German translation (Thanks to Frank Neumann).
- Fixed Panasonic CXW804 support (Thanks to Tobias Grimm).
- Fixed C++11 support (Thanks to Tobias Grimm).
- Fixed server assigment with source validation (Thanks to Patrick Boettcher).
- Added configurable RTP/RTCP ports (Thanks to chriszero).
- Added support for X-SATIP-RTSP-Port header.
- Added multicast and RTP-over-TCP support.
- Added support for activating/deactivating server on-the-fly.
- Extended command-line parameters for setting server quirks.
2017-08-15: Version 2.3.1
- Updated for vdr-2.3.7 (Thanks to Klaus Schmidinger).
- Added Polish translation (Thanks to Tomasz Nowak).
- Updated Catalan and Spanish translations (Thanks to Gabriel Bonich).
- Added support for KATHREIN SatIP Server (Thanks to kavanu).
- Added support for FRITZ!Box 6490 Cable (Thanks to 9000h).
- Updated FRITZ!WLAN Repeater DVB-C detection for the latest firmware (Thanks to 9000h).
- Added GCC7 compatibility (Thanks to Sascha Kuehndel).

View File

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

15
README
View File

@@ -52,7 +52,7 @@ separated list of "<ipaddress>|<model>|<description>" entries. The model
consists of a DVB system (DVBS2,DVBT2,DVBT,DVBC) and number of available
frontends separated by a hyphen:
vdr -P 'satip -s <ipaddress>[:<port>]|<model>[:<filter>]|<description>[:<quirk>];...'
vdr -P 'satip -s [<srcaddress>@]<ipaddress>[:<port>]|<model>[:<filter>]|<description>[:<quirk>];...'
vdr -P 'satip -s 192.168.0.1|DVBS2-2,DVBT2-2|OctopusNet'
vdr -P 'satip -s 192.168.0.1|DVBS2-4|OctopusNet;192.168.0.2|DVBT2-4|minisatip:0x18'
vdr -P 'satip -s 192.168.0.1:554|DVBS2-2:S19.2E|OctopusNet;192.168.0.2:8554|DVBS2-4:S19.2E,S1W|minisatip'
@@ -159,6 +159,19 @@ Notes:
from their webpage: http://www.inverto.tv/support/
An update to a newer firmware should be offered afterwards.
- If you are experiencing glitches in the video stream, one possible
reason can be buffer overflows in RTP receive sockets. You can verify
this by checking "receive buffer errors" counter by running "netstat -s"
command. If the counter increases every time a video glitch happens,
you should try to tweak the RTP receive buffer size with the "--rcvbuf"
(-r) plugin parameter.
A good starting point for the buffer size is to double the operating
system default value until errors disappear or the maximum value is
reached. You can check these values in Linux by checking the kernel
parameters:
$ cat /proc/sys/net/core/rmem_default
$ cat /proc/sys/net/core/rmem_max
Acknowledgements:
- Big thanks to Digital Devices GmbH for providing the Octopus Net

View File

@@ -22,7 +22,8 @@ cSatipConfig::cSatipConfig(void)
transportModeM(eTransportModeUnicast),
detachedModeM(false),
disableServerQuirksM(false),
useSingleModelServersM(false)
useSingleModelServersM(false),
rtpRcvBufSizeM(0)
{
for (unsigned int i = 0; i < ELEMENTS(cicamsM); ++i)
cicamsM[i] = 0;

View File

@@ -28,6 +28,7 @@ private:
int cicamsM[MAX_CICAM_COUNT];
int disabledSourcesM[MAX_DISABLED_SOURCES_COUNT];
int disabledFiltersM[SECTION_FILTER_TABLE_SIZE];
size_t rtpRcvBufSizeM;
public:
enum eOperatingMode {
@@ -89,6 +90,7 @@ public:
int GetDisabledFilters(unsigned int indexP) const;
unsigned int GetPortRangeStart(void) const { return portRangeStartM; }
unsigned int GetPortRangeStop(void) const { return portRangeStopM; }
size_t GetRtpRcvBufSize(void) const { return rtpRcvBufSizeM; }
void SetOperatingMode(unsigned int operatingModeP) { operatingModeM = operatingModeP; }
void SetTraceMode(unsigned int modeP) { traceModeM = (modeP & eTraceModeMask); }
@@ -104,6 +106,7 @@ public:
void SetDisabledFilters(unsigned int indexP, int numberP);
void SetPortRangeStart(unsigned int rangeStartP) { portRangeStartM = rangeStartP; }
void SetPortRangeStop(unsigned int rangeStopP) { portRangeStopM = rangeStopP; }
void SetRtpRcvBufSize(size_t sizeP) { rtpRcvBufSizeM = sizeP; }
};
extern cSatipConfig SatipConfig;

91
detectsatip.py Executable file
View File

@@ -0,0 +1,91 @@
#!/usr/bin/env python2
# -*- coding: utf-8 -*-
""" Simple tool to detect SAT>IP devices as JSON.
"""
import json
import socket
import sys
import xml.etree.ElementTree as ET
import requests
SSDP_BIND = '0.0.0.0'
SSDP_ADDR = '239.255.255.250'
SSDP_PORT = 1900
SSDP_MX = 1
SSDP_ST = 'urn:ses-com:device:SatIPServer:1'
SSDP_REQUEST = 'M-SEARCH * HTTP/1.1\r\n' + \
'HOST: %s:%d\r\n' % (SSDP_ADDR, SSDP_PORT) + \
'MAN: "ssdp:discover"\r\n' + \
'MX: %d\r\n' % (SSDP_MX, ) + \
'ST: %s\r\n' % (SSDP_ST, ) + \
'\r\n'
def parse_satip_xml(data):
""" Parse SAT>IP XML data.
Args:
data (str): XML input data..
Returns:
dict: Parsed SAT>IP device name and frontend information.
"""
result = {'name': '', 'frontends': {}}
if data:
root = ET.fromstring(data)
name = root.find('.//*/{urn:schemas-upnp-org:device-1-0}friendlyName')
result['name'] = name.text
satipcap = root.find('.//*/{urn:ses-com:satip}X_SATIPCAP')
caps = {}
for system in satipcap.text.split(","):
cap = system.split("-")
if cap:
count = int(cap[1])
if cap[0] in caps:
count = count + caps[cap[0]]
caps[cap[0]] = count
result['frontends'] = caps
return result
def detect_satip_devices():
""" Detect available SAT>IP devices by sending a broadcast message.
Returns:
list: Found SAT>IP devices.
"""
urls = []
devices = []
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.setblocking(0)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
try:
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1)
except BaseException:
pass
sock.settimeout(1)
sock.bind((SSDP_BIND, SSDP_PORT))
sock.sendto(SSDP_REQUEST, (SSDP_ADDR, SSDP_PORT))
try:
while 1:
data = sock.recv(1024)
if data:
for row in data.split('\r\n'):
if 'LOCATION:' in row:
url = row.replace('LOCATION:', '').strip()
if url in urls:
continue
urls.append(url)
info = requests.get(url, timeout=2)
devices.append(parse_satip_xml(info.text))
else:
break
except BaseException:
pass
sock.close()
return devices
if __name__ == '__main__':
json.dump(detect_satip_devices(), fp=sys.stdout, sort_keys=True, indent=2)

View File

@@ -15,14 +15,17 @@
static cSatipDevice * SatipDevicesS[SATIP_MAX_DEVICES] = { NULL };
cMutex cSatipDevice::mutexS = cMutex();
cSatipDevice::cSatipDevice(unsigned int indexP)
: deviceIndexM(indexP),
isPacketDeliveredM(false),
bytesDeliveredM(0),
isOpenDvrM(false),
checkTsBufferM(false),
deviceNameM(*cString::sprintf("%s %d", *DeviceType(), deviceIndexM)),
channelM(),
createdM(0),
mutexM()
tunedM()
{
unsigned int bufsize = (unsigned int)SATIP_BUFFER_SIZE;
bufsize -= (bufsize % TS_SIZE);
@@ -42,6 +45,8 @@ cSatipDevice::cSatipDevice(unsigned int indexP)
cSatipDevice::~cSatipDevice()
{
debug1("%s [device %u]", __PRETTY_FUNCTION__, deviceIndexM);
// Release immediately any pending conditional wait
tunedM.Broadcast();
// Stop section handler
StopSectionHandler();
DELETE_POINTER(pSectionFilterHandlerM);
@@ -103,12 +108,8 @@ cString cSatipDevice::GetSatipStatus(void)
bool live = (device == cDevice::ActualDevice());
bool lock = device->HasLock();
const cChannel *channel = device->GetCurrentlyTunedTransponder();
#if defined(APIVERSNUM) && APIVERSNUM >= 20301
LOCK_TIMERS_READ;
for (const cTimer *timer = Timers->First(); timer; timer = Timers->Next(timer)) {
#else
for (cTimer *timer = Timers.First(); timer; timer = Timers.Next(timer)) {
#endif
if (timer->Recording()) {
cRecordControl *control = cRecordControls::GetRecordControl(timer);
if (control && control->Device() == device)
@@ -137,20 +138,14 @@ cString cSatipDevice::GetSatipStatus(void)
cString cSatipDevice::GetGeneralInformation(void)
{
debug16("%s [device %u]", __PRETTY_FUNCTION__, deviceIndexM);
#if defined(APIVERSNUM) && APIVERSNUM >= 20301
LOCK_CHANNELS_READ;
#endif
return cString::sprintf("SAT>IP device: %d\nCardIndex: %d\nStream: %s\nSignal: %s\nStream bitrate: %s\n%sChannel: %s\n",
deviceIndexM, CardIndex(),
pTunerM ? *pTunerM->GetInformation() : "",
pTunerM ? *pTunerM->GetSignalStatus() : "",
pTunerM ? *pTunerM->GetTunerStatistic() : "",
*GetBufferStatistic(),
#if defined(APIVERSNUM) && APIVERSNUM >= 20301
*Channels->GetByNumber(cDevice::CurrentChannel())->ToText());
#else
*Channels.GetByNumber(cDevice::CurrentChannel())->ToText());
#endif
}
cString cSatipDevice::GetPidsInformation(void)
@@ -221,6 +216,21 @@ bool cSatipDevice::AvoidRecording(void) const
return SatipConfig.IsOperatingModeLow();
}
bool cSatipDevice::SignalStats(int &Valid, double *Strength, double *Cnr, double *BerPre, double *BerPost, double *Per, int *Status) const
{
debug16("%s [device %u]", __PRETTY_FUNCTION__, deviceIndexM);
Valid = DTV_STAT_VALID_NONE;
if (Strength && pTunerM) {
*Strength = pTunerM->SignalStrengthDBm();
Valid |= DTV_STAT_VALID_STRENGTH;
}
if (Status) {
*Status = HasLock() ? (DTV_STAT_HAS_SIGNAL | DTV_STAT_HAS_CARRIER | DTV_STAT_HAS_VITERBI | DTV_STAT_HAS_SYNC | DTV_STAT_HAS_LOCK) : DTV_STAT_HAS_NONE;
Valid |= DTV_STAT_VALID_STATUS;
}
return Valid != DTV_STAT_VALID_NONE;
}
int cSatipDevice::SignalStrength(void) const
{
debug16("%s [device %u]", __PRETTY_FUNCTION__, deviceIndexM);
@@ -339,6 +349,7 @@ bool cSatipDevice::MaySwitchTransponder(const cChannel *channelP) const
bool cSatipDevice::SetChannelDevice(const cChannel *channelP, bool liveViewP)
{
cMutexLock MutexLock(&mutexS); // Global lock to prevent any simultaneous zapping
debug9("%s (%d, %d) [device %u]", __PRETTY_FUNCTION__, channelP ? channelP->Number() : -1, liveViewP, deviceIndexM);
if (channelP) {
cDvbTransponderParameters dtp(channelP->Parameters());
@@ -356,6 +367,8 @@ bool cSatipDevice::SetChannelDevice(const cChannel *channelP, bool liveViewP)
if (pTunerM && pTunerM->SetSource(server, channelP->Transponder(), *params, deviceIndexM)) {
channelM = *channelP;
deviceNameM = cString::sprintf("%s %d %s", *DeviceType(), deviceIndexM, *cSatipDiscover::GetInstance()->GetServerString(server));
// Wait for actual channel tuning to prevent simultaneous frontend allocation failures
tunedM.TimedWait(mutexS, eTuningTimeoutMs);
return true;
}
}
@@ -367,6 +380,13 @@ bool cSatipDevice::SetChannelDevice(const cChannel *channelP, bool liveViewP)
return false;
}
void cSatipDevice::SetChannelTuned(void)
{
debug9("%s () [device %u]", __PRETTY_FUNCTION__, deviceIndexM);
// Release immediately any pending conditional wait
tunedM.Broadcast();
}
bool cSatipDevice::SetPid(cPidHandle *handleP, int typeP, bool onP)
{
debug12("%s (%d, %d, %d) [device %u]", __PRETTY_FUNCTION__, handleP ? handleP->pid : -1, typeP, onP, deviceIndexM);
@@ -405,7 +425,7 @@ void cSatipDevice::CloseFilter(int handleP)
bool cSatipDevice::OpenDvr(void)
{
debug9("%s [device %u]", __PRETTY_FUNCTION__, deviceIndexM);
isPacketDeliveredM = false;
bytesDeliveredM = 0;
tsBufferM->Clear();
if (pTunerM)
pTunerM->Open();
@@ -491,13 +511,17 @@ bool cSatipDevice::IsIdle(void)
return !Receiving();
}
uchar *cSatipDevice::GetData(int *availableP)
uchar *cSatipDevice::GetData(int *availableP, bool checkTsBuffer)
{
debug16("%s [device %u]", __PRETTY_FUNCTION__, deviceIndexM);
if (isOpenDvrM && tsBufferM) {
int count = 0;
if (isPacketDeliveredM)
SkipData(TS_SIZE);
if (bytesDeliveredM) {
tsBufferM->Del(bytesDeliveredM);
bytesDeliveredM = 0;
}
if (checkTsBuffer && tsBufferM->Available() < TS_SIZE)
return NULL;
uchar *p = tsBufferM->Get(count);
if (p && count >= TS_SIZE) {
if (*p != TS_SYNC_BYTE) {
@@ -511,7 +535,7 @@ uchar *cSatipDevice::GetData(int *availableP)
info("Skipped %d bytes to sync on TS packet", count);
return NULL;
}
isPacketDeliveredM = true;
bytesDeliveredM = TS_SIZE;
if (availableP)
*availableP = count;
// Update pid statistics
@@ -525,8 +549,7 @@ uchar *cSatipDevice::GetData(int *availableP)
void cSatipDevice::SkipData(int countP)
{
debug16("%s [device %u]", __PRETTY_FUNCTION__, deviceIndexM);
tsBufferM->Del(countP);
isPacketDeliveredM = false;
bytesDeliveredM = countP;
// Update buffer statistics
AddBufferStatistic(countP, tsBufferM->Available());
}
@@ -540,11 +563,12 @@ bool cSatipDevice::GetTSPacket(uchar *&dataP)
if (cCamSlot *cs = CamSlot()) {
if (cs->WantsTsData()) {
int available;
dataP = GetData(&available);
if (dataP) {
dataP = cs->Decrypt(dataP, available);
SkipData(available);
}
dataP = GetData(&available, checkTsBufferM);
if (!dataP)
available = 0;
dataP = cs->Decrypt(dataP, available);
SkipData(available);
checkTsBufferM = dataP != NULL;
return true;
}
}

View File

@@ -18,7 +18,7 @@
class cSatipDevice : public cDevice, public cSatipPidStatistics, public cSatipBufferStatistics, public cSatipDeviceIf {
// static ones
public:
static unsigned int deviceCount;
static cMutex mutexS;
static bool Initialize(unsigned int DeviceCount);
static void Shutdown(void);
static unsigned int Count(void);
@@ -28,18 +28,20 @@ public:
// private parts
private:
enum {
eReadyTimeoutMs = 2000 // in milliseconds
eReadyTimeoutMs = 2000, // in milliseconds
eTuningTimeoutMs = 1000 // in milliseconds
};
unsigned int deviceIndexM;
bool isPacketDeliveredM;
int bytesDeliveredM;
bool isOpenDvrM;
bool checkTsBufferM;
cString deviceNameM;
cChannel channelM;
cRingBufferLinear *tsBufferM;
cSatipTuner *pTunerM;
cSatipSectionFilterHandler *pSectionFilterHandlerM;
cTimeMs createdM;
cMutex mutexM;
cCondVar tunedM;
// constructor & destructor
public:
@@ -63,6 +65,7 @@ public:
virtual cString DeviceType(void) const;
virtual cString DeviceName(void) const;
virtual bool AvoidRecording(void) const;
virtual bool SignalStats(int &Valid, double *Strength = NULL, double *Cnr = NULL, double *BerPre = NULL, double *BerPost = NULL, double *Per = NULL, int *Status = NULL) const;
virtual int SignalStrength(void) const;
virtual int SignalQuality(void) const;
@@ -82,7 +85,7 @@ protected:
// for recording
private:
uchar *GetData(int *availableP = NULL);
uchar *GetData(int *availableP = NULL, bool checkTsBuffer = false);
void SkipData(int countP);
protected:
@@ -98,7 +101,7 @@ public:
// for transponder lock
public:
virtual bool HasLock(int timeoutMsP) const;
virtual bool HasLock(int timeoutMsP = 0) const;
// for common interface
public:
@@ -107,6 +110,7 @@ public:
// for internal device interface
public:
virtual void WriteData(u_char *bufferP, int lengthP);
virtual void SetChannelTuned(void);
virtual int GetId(void);
virtual int GetPmtPid(void);
virtual int GetCISlot(void);

View File

@@ -13,6 +13,7 @@ public:
cSatipDeviceIf() {}
virtual ~cSatipDeviceIf() {}
virtual void WriteData(u_char *bufferP, int lengthP) = 0;
virtual void SetChannelTuned(void) = 0;
virtual int GetId(void) = 0;
virtual int GetPmtPid(void) = 0;
virtual int GetCISlot(void) = 0;

View File

@@ -30,10 +30,10 @@ bool cSatipDiscover::Initialize(cSatipDiscoverServers *serversP)
{
debug1("%s", __PRETTY_FUNCTION__);
if (instanceS) {
if (serversP) {
for (cSatipDiscoverServer *s = serversP->First(); s; s = serversP->Next(s))
instanceS->AddServer(s->IpAddress(), s->IpPort(), s->Model(), s->Filters(), s->Description(), s->Quirk());
}
if (serversP) {
for (cSatipDiscoverServer *s = serversP->First(); s; s = serversP->Next(s))
instanceS->AddServer(s->SrcAddress(), s->IpAddress(), s->IpPort(), s->Model(), s->Filters(), s->Description(), s->Quirk());
}
else
instanceS->Activate();
}
@@ -271,12 +271,12 @@ void cSatipDiscover::ParseDeviceInfo(const char *addrP, const int portP)
model = modelNode.text().as_string("DVBS2-1");
}
#endif
AddServer(addrP, portP, model, NULL, desc, cSatipServer::eSatipQuirkNone);
AddServer(NULL, addrP, portP, model, NULL, desc, cSatipServer::eSatipQuirkNone);
}
void cSatipDiscover::AddServer(const char *addrP, const int portP, const char *modelP, const char *filtersP, const char *descP, const int quirkP)
void cSatipDiscover::AddServer(const char *srcAddrP, const char *addrP, const int portP, const char *modelP, const char *filtersP, const char *descP, const int quirkP)
{
debug1("%s (%s, %d, %s, %s, %s, %d)", __PRETTY_FUNCTION__, addrP, portP, modelP, filtersP, descP, quirkP);
debug1("%s (%s, %s, %d, %s, %s, %s, %d)", __PRETTY_FUNCTION__, srcAddrP, addrP, portP, modelP, filtersP, descP, quirkP);
cMutexLock MutexLock(&mutexM);
if (SatipConfig.GetUseSingleModelServers() && modelP && !isempty(modelP)) {
int n = 0;
@@ -285,9 +285,9 @@ void cSatipDiscover::AddServer(const char *addrP, const int portP, const char *m
while (r) {
r = skipspace(r);
cString desc = cString::sprintf("%s #%d", !isempty(descP) ? descP : "MyBrokenHardware", n++);
cSatipServer *tmp = new cSatipServer(addrP, portP, r, filtersP, desc, quirkP);
cSatipServer *tmp = new cSatipServer(srcAddrP, addrP, portP, r, filtersP, desc, quirkP);
if (!serversM.Update(tmp)) {
info("Adding server '%s|%s|%s' Filters: %s CI: %s Quirks: %s", tmp->Address(), tmp->Model(), tmp->Description(), !isempty(tmp->Filters()) ? tmp->Filters() : "none", tmp->HasCI() ? "yes" : "no", tmp->HasQuirk() ? tmp->Quirks() : "none");
info("Adding server '%s|%s|%s' Bind: %s Filters: %s CI: %s Quirks: %s", tmp->Address(), tmp->Model(), tmp->Description(), !isempty(tmp->SrcAddress()) ? tmp->SrcAddress() : "default", !isempty(tmp->Filters()) ? tmp->Filters() : "none", tmp->HasCI() ? "yes" : "no", tmp->HasQuirk() ? tmp->Quirks() : "none");
serversM.Add(tmp);
}
else
@@ -297,9 +297,9 @@ void cSatipDiscover::AddServer(const char *addrP, const int portP, const char *m
FREE_POINTER(p);
}
else {
cSatipServer *tmp = new cSatipServer(addrP, portP, modelP, filtersP, descP, quirkP);
cSatipServer *tmp = new cSatipServer(srcAddrP, addrP, portP, modelP, filtersP, descP, quirkP);
if (!serversM.Update(tmp)) {
info("Adding server '%s|%s|%s' Filters: %s CI: %s Quirks: %s", tmp->Address(), tmp->Model(), tmp->Description(), !isempty(tmp->Filters()) ? tmp->Filters() : "none", tmp->HasCI() ? "yes" : "no", tmp->HasQuirk() ? tmp->Quirks() : "none");
info("Adding server '%s|%s|%s' Bind: %s Filters: %s CI: %s Quirks: %s", tmp->Address(), tmp->Model(), tmp->Description(), !isempty(tmp->SrcAddress()) ? tmp->SrcAddress() : "default", !isempty(tmp->Filters()) ? tmp->Filters() : "none", tmp->HasCI() ? "yes" : "no", tmp->HasQuirk() ? tmp->Quirks() : "none");
serversM.Add(tmp);
}
else
@@ -391,6 +391,13 @@ bool cSatipDiscover::HasServerCI(cSatipServer *serverP)
return serversM.HasCI(serverP);
}
cString cSatipDiscover::GetSourceAddress(cSatipServer *serverP)
{
debug16("%s", __PRETTY_FUNCTION__);
cMutexLock MutexLock(&mutexM);
return serversM.GetSrcAddress(serverP);
}
cString cSatipDiscover::GetServerAddress(cSatipServer *serverP)
{
debug16("%s", __PRETTY_FUNCTION__);

View File

@@ -23,17 +23,19 @@ class cSatipDiscoverServer : public cListObject {
private:
int ipPortM;
int quirkM;
cString srcAddressM;
cString ipAddressM;
cString descriptionM;
cString modelM;
cString filtersM;
public:
cSatipDiscoverServer(const char *ipAddressP, const int ipPortP, const char *modelP, const char *filtersP, const char *descriptionP, const int quirkP)
cSatipDiscoverServer(const char *srcAddressP, const char *ipAddressP, const int ipPortP, const char *modelP, const char *filtersP, const char *descriptionP, const int quirkP)
{
ipAddressM = ipAddressP; ipPortM = ipPortP; modelM = modelP; filtersM = filtersP; descriptionM = descriptionP; quirkM = quirkP;
srcAddressM = srcAddressP; ipAddressM = ipAddressP; ipPortM = ipPortP; modelM = modelP; filtersM = filtersP; descriptionM = descriptionP; quirkM = quirkP;
}
int IpPort(void) { return ipPortM; }
int Quirk(void) { return quirkM; }
const char *SrcAddress(void) { return *srcAddressM; }
const char *IpAddress(void) { return *ipAddressM; }
const char *Model(void) { return *modelM; }
const char *Filters(void) { return *filtersM; }
@@ -69,7 +71,7 @@ private:
void Deactivate(void);
int ParseRtspPort(void);
void ParseDeviceInfo(const char *addrP, const int portP);
void AddServer(const char *addrP, const int portP, const char *modelP, const char *filtersP, const char *descP, const int quirkP);
void AddServer(const char *srcAddrP, const char *addrP, const int portP, const char *modelP, const char *filtersP, const char *descP, const int quirkP);
void Fetch(const char *urlP);
// constructor
cSatipDiscover();
@@ -98,6 +100,7 @@ public:
bool IsServerQuirk(cSatipServer *serverP, int quirkP);
bool HasServerCI(cSatipServer *serverP);
cString GetServerAddress(cSatipServer *serverP);
cString GetSourceAddress(cSatipServer *serverP);
int GetServerPort(cSatipServer *serverP);
cString GetServerList(void);
int NumProvidedSystems(void);

View File

@@ -166,6 +166,7 @@ cString GetTransponderUrlParameters(const cChannel *channelP)
if ((channelP->Rid() % 100) > 0)
q += snprintf(q, STBUFLEFT, "&fe=%d", channelP->Rid() % 100);
ST(" S *") q += snprintf(q, STBUFLEFT, "src=%d&", ((src > 0) && (src <= 255)) ? src : 1);
if (freq >= 0L)
q += snprintf(q, STBUFLEFT, "freq=%s", *dtoa(freq, "%lg"));
ST(" S *") q += snprintf(q, STBUFLEFT, "&pol=%c", tolower(dtp.Polarization()));
ST(" S *") q += PrintUrlString(q, STBUFLEFT, dtp.RollOff(), SatipRollOffValues);

View File

@@ -1,14 +1,14 @@
# VDR plugin language source file.
# Copyright (C) 2007-2016 Rolf Ahrenberg
# Copyright (C) 2007-2017 Rolf Ahrenberg
# This file is distributed under the same license as the satip package.
# Gabriel Bonich, 2014-2015
# Gabriel Bonich, 2014-2017
#
msgid ""
msgstr ""
"Project-Id-Version: vdr-satip 2.2.4\n"
"Project-Id-Version: vdr-satip 2.3.1\n"
"Report-Msgid-Bugs-To: <see README>\n"
"POT-Creation-Date: 2016-12-18 12:18+0200\n"
"PO-Revision-Date: 2016-12-18 12:18+0200\n"
"POT-Creation-Date: 2017-08-15 08:15+0300\n"
"PO-Revision-Date: 2017-08-15 08:15+0300\n"
"Last-Translator: Gabriel Bonich <gbonich@gmail.com>\n"
"Language-Team: Catalan <vdr@linuxtv.org>\n"
"Language: ca\n"
@@ -86,13 +86,13 @@ msgid "high"
msgstr "Alt"
msgid "Unicast"
msgstr ""
msgstr "Unicast"
msgid "Multicast"
msgstr ""
msgstr "Multicast"
msgid "RTP-over-TCP"
msgstr ""
msgstr "RTP-per sobre-TCP"
msgid "Button$Devices"
msgstr "Dispositius"
@@ -188,7 +188,7 @@ msgid "Define an ill-behaving filter to be blacklisted."
msgstr "Definir un filtre mal comportar a la llista negra."
msgid "Transport mode"
msgstr ""
msgstr "Tipus de Transmissió"
msgid ""
"Define which transport mode shall be used.\n"

View File

@@ -1,14 +1,14 @@
# VDR plugin language source file.
# Copyright (C) 2007-2016 Rolf Ahrenberg
# Copyright (C) 2007-2017 Rolf Ahrenberg
# This file is distributed under the same license as the satip package.
# Frank Neumann, 2014-2016
# Frank Neumann, 2014-2017
#
msgid ""
msgstr ""
"Project-Id-Version: vdr-satip 2.2.4\n"
"Project-Id-Version: vdr-satip 2.3.1\n"
"Report-Msgid-Bugs-To: <see README>\n"
"POT-Creation-Date: 2016-12-18 12:18+0200\n"
"PO-Revision-Date: 2016-12-18 12:18+0200\n"
"POT-Creation-Date: 2017-08-15 08:15+0300\n"
"PO-Revision-Date: 2017-08-15 08:15+0300\n"
"Last-Translator: Frank Neumann <fnu@yavdr.org>\n"
"Language-Team: German <vdr@linuxtv.org>\n"
"Language: de\n"

View File

@@ -1,14 +1,14 @@
# VDR plugin language source file.
# Copyright (C) 2007-2016 Rolf Ahrenberg
# Copyright (C) 2007-2017 Rolf Ahrenberg
# This file is distributed under the same license as the satip package.
# Gabriel Bonich, 2014-2015
# Gabriel Bonich, 2014-2017
#
msgid ""
msgstr ""
"Project-Id-Version: vdr-satip 2.2.4\n"
"Project-Id-Version: vdr-satip 2.3.1\n"
"Report-Msgid-Bugs-To: <see README>\n"
"POT-Creation-Date: 2016-12-18 12:18+0200\n"
"PO-Revision-Date: 2016-12-18 12:18+0200\n"
"POT-Creation-Date: 2017-08-15 08:15+0300\n"
"PO-Revision-Date: 2017-08-15 08:15+0300\n"
"Last-Translator: Gabriel Bonich <gbonich@gmail.com>\n"
"Language-Team: Spanish <vdr@linuxtv.org>\n"
"Language: es\n"
@@ -86,13 +86,13 @@ msgid "high"
msgstr "Alto"
msgid "Unicast"
msgstr ""
msgstr "Unicast"
msgid "Multicast"
msgstr ""
msgstr "Multicast"
msgid "RTP-over-TCP"
msgstr ""
msgstr "RTP-antes que-TCP"
msgid "Button$Devices"
msgstr "Dispositivos"
@@ -188,7 +188,7 @@ msgid "Define an ill-behaving filter to be blacklisted."
msgstr "Define un filtro para poner en la lista negra."
msgid "Transport mode"
msgstr ""
msgstr "Tipo de Transmisión"
msgid ""
"Define which transport mode shall be used.\n"

View File

@@ -1,14 +1,14 @@
# VDR plugin language source file.
# Copyright (C) 2007-2016 Rolf Ahrenberg
# Copyright (C) 2007-2017 Rolf Ahrenberg
# This file is distributed under the same license as the satip package.
# Rolf Ahrenberg, 2015-2016
# Rolf Ahrenberg, 2015-2017
#
msgid ""
msgstr ""
"Project-Id-Version: vdr-satip 2.2.4\n"
"Project-Id-Version: vdr-satip 2.3.1\n"
"Report-Msgid-Bugs-To: <see README>\n"
"POT-Creation-Date: 2016-12-18 12:18+0200\n"
"PO-Revision-Date: 2016-12-18 12:18+0200\n"
"POT-Creation-Date: 2017-08-15 08:15+0300\n"
"PO-Revision-Date: 2017-08-15 08:15+0300\n"
"Last-Translator: Rolf Ahrenberg\n"
"Language-Team: Finnish <vdr@linuxtv.org>\n"
"Language: fi\n"

206
po/pl_PL.po Normal file
View File

@@ -0,0 +1,206 @@
# VDR plugin language source file.
# Copyright (C) 2007-2017 Rolf Ahrenberg
# This file is distributed under the same license as the vdr-satip package.
# Tomasz Maciej Nowak, 2017
#
msgid ""
msgstr ""
"Project-Id-Version: vdr-satip 2.3.1\n"
"Report-Msgid-Bugs-To: <see README>\n"
"POT-Creation-Date: 2017-08-15 08:15+0300\n"
"PO-Revision-Date: 2017-08-15 08:15+0300\n"
"Last-Translator: Tomasz Maciej Nowak <tomek_n@o2.pl>\n"
"Language-Team: Polish <vdr@linuxtv.org>\n"
"Language: pl_PL\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: Poedit 1.8.11\n"
msgid "PAT (0x00)"
msgstr "PAT (0x00)"
msgid "NIT (0x40)"
msgstr "NIT (0x40)"
msgid "SDT (0x42)"
msgstr "SDT (0x42)"
msgid "EIT (0x4E/0x4F/0x5X/0x6X)"
msgstr "EIT (0x4E/0x4F/0x5X/0x6X)"
msgid "TDT (0x70)"
msgstr "TDT (0x70)"
msgid "SAT>IP information not available!"
msgstr "Informacja o SAT>IP niedostępna!"
msgid "SAT>IP Devices"
msgstr "Urządzenia SAT>IP"
msgid "SAT>IP Server"
msgstr "Serwer SAT>IP"
msgid "Address"
msgstr "Adres"
msgid "Model"
msgstr "Model"
msgid "Description"
msgstr "Opis"
msgid "CI extension"
msgstr "Rozszerzenie CI"
msgid "Creation date"
msgstr "Data produkcji"
msgid "SAT>IP Device Status"
msgstr "Status urządzenia SAT>IP"
msgid "SAT>IP Information"
msgstr "SAT>IP - informacje"
msgid "General"
msgstr "Główne"
msgid "Pids"
msgstr "Pidy"
msgid "Filters"
msgstr "Filtry"
msgid "Bits/bytes"
msgstr "Bity/bajty"
msgid "off"
msgstr "wyłączone"
msgid "low"
msgstr "niski"
msgid "normal"
msgstr "normalny"
msgid "high"
msgstr "wysoki"
msgid "Unicast"
msgstr "Unicast"
msgid "Multicast"
msgstr "Multicast"
msgid "RTP-over-TCP"
msgstr "RTP-over-TCP"
msgid "Button$Devices"
msgstr "Urządzenia"
msgid "Operating mode"
msgstr "Tryb pracy"
msgid ""
"Define the used operating mode for all SAT>IP devices:\n"
"\n"
"off - devices are disabled\n"
"low - devices are working at the lowest priority\n"
"normal - devices are working within normal parameters\n"
"high - devices are working at the highest priority"
msgstr ""
"Określa tryb pracy wszystkich urządzeń SAT>IP:\n"
"\n"
"wyłączone - urządzenia są wyłączone\n"
"niski - urządzenia pracują z najniższym priorytetem\n"
"normalny - urządzenia pracują z normalnymi parametrami\n"
"wysoki - urządzenia pracują z najwyższym priorytetem"
msgid "Enable CI extension"
msgstr "Włącz rozszerzenie CI"
msgid ""
"Define whether a CI extension shall be used.\n"
"\n"
"This setting enables integrated CI/CAM handling found in some SAT>IP hardware (e.g. Digital Devices OctopusNet)."
msgstr ""
"Określa czy korzystać z rozszerzenia CI.\n"
"\n"
"To ustawienie włącza obsługę dostępnego czytnika CI/CAM w niektórych urządzeniach SAT>IP (np. Digital Devices OctopusNet)."
msgid "CI/CAM"
msgstr "CI/CAM"
msgid ""
"Define a desired CAM type for the CI slot.\n"
"\n"
"The '---' option lets SAT>IP hardware do the auto-selection."
msgstr ""
"Określa typ modułu CAM w czytniku CI.\n"
"\n"
"Opcja '---' pozwala urządzeniu SAT>IP automatycznie wybrać typ."
msgid "Enable EPG scanning"
msgstr "Włącz skanowanie EPG"
msgid ""
"Define whether the EPG background scanning shall be used.\n"
"\n"
"This setting disables the automatic EIT scanning functionality for all SAT>IP devices."
msgstr ""
"Określa czy przeprowadzać skanowanie EPG w tle.\n"
"\n"
"To ustawienie wyłącza funkcję automatycznego skanowania EIT dla wszystkich urządzeń SAT>IP."
msgid "Disabled sources"
msgstr "Wyłączone źródła"
msgid "none"
msgstr "brak"
msgid ""
"Define number of sources to be disabled.\n"
"\n"
"SAT>IP servers might not have all satellite positions available and such sources can be blacklisted here."
msgstr ""
"Określa liczbę wyłączonych źródeł.\n"
"\n"
"Serwery SAT>IP mogą nie mieć dostępu do niektórych pozycji satelitarnych, więc tutaj można je wyłączyć."
msgid "Define a source to be blacklisted."
msgstr "Określ źródła do wyłączenia."
msgid "Disabled filters"
msgstr "Wyłączone filtry"
msgid ""
"Define number of section filters to be disabled.\n"
"\n"
"Certain section filters might cause some unwanted behaviour to VDR such as time being falsely synchronized. By blacklisting the filters here, useful section data can be left intact for VDR to process."
msgstr ""
"Określa liczbę wyłączonych filtrów sekcji.\n"
"\n"
"Niektóre filtry sekcji mogą powodować niezamierzone efekty w VDR, takie jak zły czas synchronizacji. Poprzez wyłączenie niektórych filtrów, użyteczne dane sekcji będą dostępne do przetworzenia dla VDR."
msgid "Filter"
msgstr "Filtr"
msgid "Define an ill-behaving filter to be blacklisted."
msgstr "Określa filtry powodujące zakłócenia, które mają być wyłączone."
msgid "Transport mode"
msgstr "Tryb"
msgid ""
"Define which transport mode shall be used.\n"
"\n"
"Unicast, Multicast, RTP-over-TCP"
msgstr ""
"Określa tryb transmisji.\n"
"Unicast, Multicast, RTP-over-TCP."
msgid "Active SAT>IP servers:"
msgstr "Aktywne serwery SAT>IP:"
msgid "Help"
msgstr "Pomoc"

7
rtp.c
View File

@@ -14,7 +14,8 @@
#include "rtp.h"
cSatipRtp::cSatipRtp(cSatipTunerIf &tunerP)
: tunerM(tunerP),
: cSatipSocket(SatipConfig.GetRtpRcvBufSize()),
tunerM(tunerP),
bufferLenM(eRtpPacketReadCount * eMaxUdpPacketSizeB),
bufferM(MALLOC(unsigned char, bufferLenM)),
lastErrorReportM(0),
@@ -45,7 +46,7 @@ void cSatipRtp::Close(void)
sequenceNumberM = -1;
if (packetErrorsM) {
info("Detected %d RTP packet errors [device %d]", packetErrorsM, tunerM.GetId());
info("Detected %d RTP packet error%s [device %d]", packetErrorsM, packetErrorsM == 1 ? "": "s", tunerM.GetId());
packetErrorsM = 0;
lastErrorReportM = time(NULL);
}
@@ -80,7 +81,7 @@ int cSatipRtp::GetHeaderLength(unsigned char *bufferP, unsigned int lengthP)
else if ((sequenceNumberM >= 0) && (((sequenceNumberM + 1) % 0xFFFF) != seq)) {
packetErrorsM++;
if (time(NULL) - lastErrorReportM > eReportIntervalS) {
info("Detected %d RTP packet errors [device %d]", packetErrorsM, tunerM.GetId());
info("Detected %d RTP packet error%s [device %d]", packetErrorsM, packetErrorsM == 1 ? "": "s", tunerM.GetId());
packetErrorsM = 0;
lastErrorReportM = time(NULL);
}

19
rtsp.c
View File

@@ -164,9 +164,6 @@ void cSatipRtsp::Create(void)
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_TIMEOUT_MS, (long)eConnectTimeoutMs);
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_CONNECTTIMEOUT_MS, (long)eConnectTimeoutMs);
// Limit download speed (bytes/s)
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_MAX_RECV_SPEED_LARGE, eMaxDownloadSpeedMBits * 131072L);
// Set user-agent
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_USERAGENT, *cString::sprintf("vdr-%s/%s (device %d)", PLUGIN_NAME_I18N, VERSION, tunerM.GetId()));
}
@@ -193,6 +190,22 @@ void cSatipRtsp::Reset(void)
Create();
}
bool cSatipRtsp::SetInterface(const char *bindAddrP)
{
debug1("%s (%s) [device %d]", __PRETTY_FUNCTION__, bindAddrP, tunerM.GetId());
bool result = true;
CURLcode res = CURLE_OK;
if (handleM && !isempty(bindAddrP)) {
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_INTERFACE, *cString::sprintf("host!%s", bindAddrP));
}
else {
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_INTERFACE, NULL);
}
return result;
}
bool cSatipRtsp::Options(const char *uriP)
{
debug1("%s (%s) [device %d]", __PRETTY_FUNCTION__, uriP, tunerM.GetId());

2
rtsp.h
View File

@@ -27,7 +27,6 @@ private:
enum {
eConnectTimeoutMs = 1500, // in milliseconds
eMaxDownloadSpeedMBits = 20, // in megabits per second
};
cSatipTunerIf &tunerM;
@@ -59,6 +58,7 @@ public:
cString GetActiveMode(void);
cString RtspUnescapeString(const char *strP);
void Reset(void);
bool SetInterface(const char *bindAddrP);
bool Options(const char *uriP);
bool Setup(const char *uriP, int rtpPortP, int rtcpPortP, bool useTcpP);
bool SetSession(const char *sessionP);

30
satip.c
View File

@@ -5,6 +5,7 @@
*
*/
#include <ctype.h>
#include <getopt.h>
#include <vdr/plugin.h>
#include "common.h"
@@ -19,15 +20,15 @@
#warning "CURL version >= 7.36.0 is recommended"
#endif
#if defined(APIVERSNUM) && APIVERSNUM < 20200
#error "VDR-2.2.0 API version or greater is required!"
#if defined(APIVERSNUM) && APIVERSNUM < 20307
#error "VDR-2.3.7 API version or greater is required!"
#endif
#ifndef GITVERSION
#define GITVERSION ""
#endif
const char VERSION[] = "2.2.4" GITVERSION;
const char VERSION[] = "2.3.1" GITVERSION;
static const char DESCRIPTION[] = trNOOP("SAT>IP Devices");
class cPluginSatip : public cPlugin {
@@ -90,7 +91,8 @@ const char *cPluginSatip::CommandLineHelp(void)
" -S, --single set the single model server mode on\n"
" -n, --noquirks disable autodetection of the server quirks\n"
" -p, --portrange=<start>-<end> set a range of ports used for the RT[C]P server\n"
" a minimum of 2 ports per device is required.\n";
" a minimum of 2 ports per device is required.\n"
" -r, --rcvbuf override the size of the RTP receive buffer in bytes\n";
}
bool cPluginSatip::ProcessArgs(int argc, char *argv[])
@@ -102,6 +104,7 @@ bool cPluginSatip::ProcessArgs(int argc, char *argv[])
{ "trace", required_argument, NULL, 't' },
{ "server", required_argument, NULL, 's' },
{ "portrange",required_argument, NULL, 'p' },
{ "rcvbuf", required_argument, NULL, 'r' },
{ "detach", no_argument, NULL, 'D' },
{ "single", no_argument, NULL, 'S' },
{ "noquirks", no_argument, NULL, 'n' },
@@ -111,7 +114,7 @@ bool cPluginSatip::ProcessArgs(int argc, char *argv[])
cString server;
cString portrange;
int c;
while ((c = getopt_long(argc, argv, "d:t:s:p:DSn", long_options, NULL)) != -1) {
while ((c = getopt_long(argc, argv, "d:t:s:p:r:DSn", long_options, NULL)) != -1) {
switch (c) {
case 'd':
deviceCountM = strtol(optarg, NULL, 0);
@@ -134,6 +137,9 @@ bool cPluginSatip::ProcessArgs(int argc, char *argv[])
case 'p':
portrange = optarg;
break;
case 'r':
SatipConfig.SetRtpRcvBufSize(strtol(optarg, NULL, 0));
break;
default:
return false;
}
@@ -232,7 +238,7 @@ void cPluginSatip::ParseServer(const char *paramP)
while (r) {
r = skipspace(r);
debug3("%s server[%d]=%s", __PRETTY_FUNCTION__, n, r);
cString serverAddr, serverModel, serverFilters, serverDescription;
cString sourceAddr, serverAddr, serverModel, serverFilters, serverDescription;
int serverQuirk = cSatipServer::eSatipQuirkNone;
int serverPort = SATIP_DEFAULT_RTSP_PORT;
int n2 = 0;
@@ -243,8 +249,14 @@ void cPluginSatip::ParseServer(const char *paramP)
switch (n2++) {
case 0:
{
char *r3 = strchr(r2, '@');
if (r3) {
*r3 = 0;
sourceAddr = r2;
r2 = r3 + 1;
}
serverAddr = r2;
char *r3 = strchr(r2, ':');
r3 = strchr(r2, ':');
if (r3) {
serverPort = strtol(r3 + 1, NULL, 0);
serverAddr = serverAddr.Truncate(r3 - r2);
@@ -277,10 +289,10 @@ void cPluginSatip::ParseServer(const char *paramP)
r2 = strtok_r(NULL, "|", &s2);
}
if (*serverAddr && *serverModel && *serverDescription) {
debug1("%s ipaddr=%s port=%d model=%s (%s) desc=%s (%d)", __PRETTY_FUNCTION__, *serverAddr, serverPort, *serverModel, *serverFilters, *serverDescription, serverQuirk);
debug1("%s srcaddr=%s ipaddr=%s port=%d model=%s (%s) desc=%s (%d)", __PRETTY_FUNCTION__, *sourceAddr, *serverAddr, serverPort, *serverModel, *serverFilters, *serverDescription, serverQuirk);
if (!serversM)
serversM = new cSatipDiscoverServers();
serversM->Add(new cSatipDiscoverServer(*serverAddr, serverPort, *serverModel, *serverFilters, *serverDescription, serverQuirk));
serversM->Add(new cSatipDiscoverServer(*sourceAddr, *serverAddr, serverPort, *serverModel, *serverFilters, *serverDescription, serverQuirk));
}
++n;
r = strtok_r(NULL, ";", &s);

View File

@@ -102,8 +102,11 @@ int cSatipSectionFilter::Filter(void)
if (doneqM && !neq)
return 0;
if (ringBufferM && (secLenM > 0))
ringBufferM->Put(new cFrame(secBufM, secLenM));
if (ringBufferM && (secLenM > 0)) {
cFrame* section = new cFrame(secBufM, secLenM);
if (!ringBufferM->Put(section))
DELETE_POINTER(section);
}
}
return 0;
}
@@ -126,7 +129,7 @@ int cSatipSectionFilter::CopyDump(const uint8_t *bufP, uint8_t lenP)
if (tsFeedpM + lenP > eDmxMaxSectionFeedSize)
lenP = (uint8_t)(eDmxMaxSectionFeedSize - tsFeedpM);
if (lenP <= 0)
if (lenP == 0)
return 0;
memcpy(secBufBaseM + tsFeedpM, bufP, lenP);
@@ -141,7 +144,7 @@ int cSatipSectionFilter::CopyDump(const uint8_t *bufP, uint8_t lenP)
for (n = 0; secBufpM + 2 < limit; ++n) {
uint16_t seclen = GetLength(secBufM);
if ((seclen <= 0) || (seclen > eDmxMaxSectionSize) || ((seclen + secBufpM) > limit))
if ((seclen > eDmxMaxSectionSize) || ((seclen + secBufpM) > limit))
return 0;
secLenM = seclen;
if (pusiSeenM)
@@ -209,27 +212,28 @@ void cSatipSectionFilter::Process(const uint8_t* dataP)
}
}
bool cSatipSectionFilter::Send(void)
void cSatipSectionFilter::Send(void)
{
bool result = false;
cFrame *section = ringBufferM->Get();
if (section) {
uchar *data = section->Data();
int count = section->Count();
if (data && (count > 0) && (socketM[1] >= 0) && (socketM[0] >= 0)) {
ssize_t len = send(socketM[1], data, count, MSG_EOR);
ERROR_IF(len < 0 && errno != EAGAIN, "send()");
if (len > 0) {
ringBufferM->Drop(section);
result = !!ringBufferM->Available();
if (send(socketM[1], data, count, MSG_EOR) > 0) {
// Update statistics
AddSectionStatistic(len, 1);
AddSectionStatistic(count, 1);
}
else if (errno != EAGAIN)
error("failed to send section data (%i bytes) [device=%d]", count, deviceIndexM);
}
ringBufferM->Drop(section);
}
return result;
}
int cSatipSectionFilter::Available(void) const
{
return ringBufferM->Available();
}
cSatipSectionFilterHandler::cSatipSectionFilterHandler(int deviceIndexP, unsigned int bufferLenP)
: cThread(cString::sprintf("SATIP#%d section handler", deviceIndexP)),
@@ -267,54 +271,73 @@ cSatipSectionFilterHandler::~cSatipSectionFilterHandler()
Delete(i);
}
void cSatipSectionFilterHandler::SendAll(void)
{
cMutexLock MutexLock(&mutexM);
bool pendingData;
do {
pendingData = false;
// zero polling structures
memset(pollFdsM, 0, sizeof(pollFdsM));
// assemble all handlers to poll (use -1 to ignore handlers)
for (unsigned int i = 0; i < eMaxSecFilterCount; ++i) {
if (filtersM[i] && filtersM[i]->Available() != 0) {
pollFdsM[i].fd = filtersM[i]->GetFd();
pollFdsM[i].events = POLLOUT;
pendingData = true;
}
else
pollFdsM[i].fd = -1;
}
// exit if there isn't any pending data or we time out
if (!pendingData || poll(pollFdsM, eMaxSecFilterCount, eSecFilterSendTimeoutMs) <= 0)
return;
// send data (if available)
for (unsigned int i = 0; i < eMaxSecFilterCount && pendingData; ++i) {
if (pollFdsM[i].revents & POLLOUT)
filtersM[i]->Send();
}
} while (pendingData);
}
void cSatipSectionFilterHandler::Action(void)
{
debug1("%s Entering [device %d]", __PRETTY_FUNCTION__, deviceIndexM);
bool processed = false;
// Do the thread loop
while (Running()) {
// Send demuxed section packets through all filters
bool retry = false;
mutexM.Lock();
for (unsigned int i = 0; i < eMaxSecFilterCount; ++i) {
if (filtersM[i] && filtersM[i]->Send())
retry = true;
}
mutexM.Unlock();
if (retry)
continue;
// Read one TS packet
if (ringBufferM) {
int len = 0;
if (processed) {
ringBufferM->Del(TS_SIZE);
processed = false;
}
uchar *p = ringBufferM->Get(len);
if (p && (len >= TS_SIZE)) {
if (*p != TS_SYNC_BYTE) {
for (int i = 1; i < len; ++i) {
if (p[i] == TS_SYNC_BYTE) {
len = i;
break;
uchar *p = NULL;
int len = 0;
// Process all pending TS packets
while ((p = ringBufferM->Get(len)) != NULL) {
if (p && (len >= TS_SIZE)) {
if (*p != TS_SYNC_BYTE) {
for (int i = 1; i < len; ++i) {
if (p[i] == TS_SYNC_BYTE) {
len = i;
break;
}
}
}
ringBufferM->Del(len);
debug1("%s Skipped %d bytes to sync on TS packet [device %d]", __PRETTY_FUNCTION__, len, deviceIndexM);
continue;
}
// Process TS packet through all filters
mutexM.Lock();
for (unsigned int i = 0; i < eMaxSecFilterCount; ++i) {
if (filtersM[i])
filtersM[i]->Process(p);
}
mutexM.Unlock();
processed = true;
continue;
}
}
cCondWait::SleepMs(10); // to avoid busy loop and reduce cpu load
ringBufferM->Del(len);
debug1("%s Skipped %d bytes to sync on TS packet [device %d]", __PRETTY_FUNCTION__, len, deviceIndexM);
continue;
}
// Process TS packet through all filters
mutexM.Lock();
for (unsigned int i = 0; i < eMaxSecFilterCount; ++i) {
if (filtersM[i])
filtersM[i]->Process(p);
}
mutexM.Unlock();
ringBufferM->Del(TS_SIZE);
}
}
// Send demuxed section packets through all filters
SendAll();
}
debug1("%s Exiting [device %d]", __PRETTY_FUNCTION__, deviceIndexM);
}

View File

@@ -8,6 +8,7 @@
#ifndef __SATIP_SECTIONFILTER_H
#define __SATIP_SECTIONFILTER_H
#include <poll.h>
#include <vdr/device.h>
#include "common.h"
@@ -55,23 +56,27 @@ public:
cSatipSectionFilter(int deviceIndexP, uint16_t pidP, uint8_t tidP, uint8_t maskP);
virtual ~cSatipSectionFilter();
void Process(const uint8_t* dataP);
bool Send(void);
void Send(void);
int GetFd(void) { return socketM[0]; }
uint16_t GetPid(void) const { return pidM; }
int Available(void) const;
};
class cSatipSectionFilterHandler : public cThread {
private:
enum {
eMaxSecFilterCount = 32
eMaxSecFilterCount = 32,
eSecFilterSendTimeoutMs = 10
};
cRingBufferLinear *ringBufferM;
cMutex mutexM;
int deviceIndexM;
cSatipSectionFilter *filtersM[eMaxSecFilterCount];
struct pollfd pollFdsM[eMaxSecFilterCount];
bool Delete(unsigned int indexP);
bool IsBlackListed(u_short pidP, u_char tidP, u_char maskP) const;
void SendAll(void);
protected:
virtual void Action(void);

View File

@@ -80,8 +80,9 @@ bool cSatipFrontends::Detach(int deviceIdP, int transponderP)
// --- cSatipServer -----------------------------------------------------------
cSatipServer::cSatipServer(const char *addressP, const int portP, const char *modelP, const char *filtersP, const char *descriptionP, const int quirkP)
: addressM((addressP && *addressP) ? addressP : "0.0.0.0"),
cSatipServer::cSatipServer(const char *srcAddressP, const char *addressP, const int portP, const char *modelP, const char *filtersP, const char *descriptionP, const int quirkP)
: srcAddressM((srcAddressP && *srcAddressP) ? srcAddressP : ""),
addressM((addressP && *addressP) ? addressP : "0.0.0.0"),
modelM((modelP && *modelP) ? modelP : "DVBS-1"),
filtersM((filtersP && *filtersP) ? filtersP : ""),
descriptionM(!isempty(descriptionP) ? descriptionP : "MyBrokenHardware"),
@@ -116,42 +117,43 @@ cSatipServer::cSatipServer(const char *addressP, const int portP, const char *mo
// These devices contain a session id bug:
// Inverto Airscreen Server IDL 400 ?
// Elgato EyeTV Netstream 4Sat ?
if (strstr(*descriptionM, "GSSBOX") || // Grundig Sat Systems GSS.box DSI 400
strstr(*descriptionM, "DIGIBIT") || // Telestar Digibit R1
strstr(*descriptionM, "Triax SatIP Converter") // Triax TSS 400
if (strstr(*descriptionM, "GSSBOX") || // Grundig Sat Systems GSS.box DSI 400
strstr(*descriptionM, "DIGIBIT") || // Telestar Digibit R1
strstr(*descriptionM, "Triax SatIP Converter") // Triax TSS 400
)
quirkM |= eSatipQuirkSessionId;
// These devices contain support for RTP over TCP:
if (strstr(*descriptionM, "minisatip") || // minisatip server
strstr(*descriptionM, "DVBViewer") || // DVBViewer Media Server
strstr(*descriptionM, "GSSBOX") || // Grundig Sat Systems GSS.box DSI 400
strstr(*descriptionM, "DIGIBIT") || // Telestar Digibit R1
strstr(*descriptionM, "Triax SatIP Converter") // Triax TSS 400
if (strstr(*descriptionM, "minisatip") || // minisatip server
strstr(*descriptionM, "DVBViewer") // DVBViewer Media Server
)
quirkM |= eSatipQuirkRtpOverTcp;
// These devices contain a play (add/delpids) parameter bug:
if (strstr(*descriptionM, "fritzdvbc") // Fritz!WLAN Repeater DVB-C
if (strstr(*descriptionM, "FRITZ!Box 6490 Cable") || // FRITZ!Box 6490 Cable
strstr(*descriptionM, "FRITZ!WLAN Repeater DVB-C") || // FRITZ!WLAN Repeater DVB-C
strstr(*descriptionM, "fritzdvbc") // FRITZ!WLAN Repeater DVB-C (old firmware)
)
quirkM |= eSatipQuirkPlayPids;
// These devices contain a frontend locking bug:
if (strstr(*descriptionM, "fritzdvbc") || // Fritz!WLAN Repeater DVB-C
strstr(*descriptionM, "Schwaiger Sat>IP Server") // Schwaiger MS41IP
if (strstr(*descriptionM, "FRITZ!Box 6490 Cable") || // FRITZ!Box 6490 Cable
strstr(*descriptionM, "FRITZ!WLAN Repeater DVB-C") || // FRITZ!WLAN Repeater DVB-C
strstr(*descriptionM, "fritzdvbc") || // FRITZ!WLAN Repeater DVB-C (old firmware)
strstr(*descriptionM, "Schwaiger Sat>IP Server") // Schwaiger MS41IP
)
quirkM |= eSatipQuirkForceLock;
// These devices support the X_PMT protocol extension
if (strstr(*descriptionM, "OctopusNet") || // Digital Devices OctopusNet
strstr(*descriptionM, "minisatip") // minisatip server
if (strstr(*descriptionM, "OctopusNet") || // Digital Devices OctopusNet
strstr(*descriptionM, "minisatip") // minisatip server
)
quirkM |= eSatipQuirkCiXpmt;
// These devices support the TNR protocol extension
if (strstr(*descriptionM, "DVBViewer") // DVBViewer Media Server
if (strstr(*descriptionM, "DVBViewer") // DVBViewer Media Server
)
quirkM |= eSatipQuirkCiTnr;
// These devices don't support auto-detection of pilot tones
if (strstr(*descriptionM, "GSSBOX") || // Grundig Sat Systems GSS.box DSI 400
strstr(*descriptionM, "DIGIBIT") || // Telestar Digibit R1
strstr(*descriptionM, "Triax SatIP Converter") // Triax TSS 400
// Kathrein ExIP 414/E
if (strstr(*descriptionM, "GSSBOX") || // Grundig Sat Systems GSS.box DSI 400
strstr(*descriptionM, "DIGIBIT") || // Telestar Digibit R1
strstr(*descriptionM, "Triax SatIP Converter") || // Triax TSS 400
strstr(*descriptionM, "KATHREIN SatIP Server") // Kathrein ExIP 414/E
)
quirkM |= eSatipQuirkForcePilot;
}
@@ -446,6 +448,18 @@ void cSatipServers::Cleanup(uint64_t intervalMsP)
}
}
cString cSatipServers::GetSrcAddress(cSatipServer *serverP)
{
cString address = "";
for (cSatipServer *s = First(); s; s = Next(s)) {
if (s == serverP) {
address = s->SrcAddress();
break;
}
}
return address;
}
cString cSatipServers::GetAddress(cSatipServer *serverP)
{
cString address = "";
@@ -486,7 +500,10 @@ cString cSatipServers::List(void)
{
cString list = "";
for (cSatipServer *s = First(); s; s = Next(s))
list = cString::sprintf("%s%c %s|%s|%s\n", *list, s->IsActive() ? '+' : '-', s->Address(), s->Model(), s->Description());
if (isempty(s->SrcAddress()))
list = cString::sprintf("%s%c %s|%s|%s\n", *list, s->IsActive() ? '+' : '-', s->Address(), s->Model(), s->Description());
else
list = cString::sprintf("%s%c %s@%s|%s|%s\n", *list, s->IsActive() ? '+' : '-', s->SrcAddress(), s->Address(), s->Model(), s->Description());
return list;
}

View File

@@ -57,6 +57,7 @@ private:
enum {
eSatipMaxSourceFilters = 16
};
cString srcAddressM;
cString addressM;
cString modelM;
cString filtersM;
@@ -84,7 +85,7 @@ public:
eSatipQuirkForcePilot = 0x40,
eSatipQuirkMask = 0xFF
};
cSatipServer(const char *addressP, const int portP, const char *modelP, const char *filtersP, const char *descriptionP, const int quirkP);
cSatipServer(const char *srcAddressP, const char *addressP, const int portP, const char *modelP, const char *filtersP, const char *descriptionP, const int quirkP);
virtual ~cSatipServer();
virtual int Compare(const cListObject &listObjectP) const;
bool Assign(int deviceIdP, int sourceP, int systemP, int transponderP);
@@ -98,6 +99,7 @@ public:
int GetModulesDVBC(void);
int GetModulesDVBC2(void);
void Activate(bool onOffP) { activeM = onOffP; }
const char *SrcAddress(void) { return *srcAddressM; }
const char *Address(void) { return *addressM; }
const char *Model(void) { return *modelM; }
const char *Filters(void) { return *filtersM; }
@@ -128,6 +130,7 @@ public:
bool HasCI(cSatipServer *serverP);
void Cleanup(uint64_t intervalMsP = 0);
cString GetAddress(cSatipServer *serverP);
cString GetSrcAddress(cSatipServer *serverP);
cString GetString(cSatipServer *serverP);
int GetPort(cSatipServer *serverP);
cString List(void);

View File

@@ -105,7 +105,7 @@ cSatipServerInfo::cSatipServerInfo(cSatipServer *serverP)
: cOsdMenu(tr("SAT>IP Server"), 20),
serverM(serverP),
activeM(serverP && serverP->IsActive()),
addressM(serverP ? serverP->Address() : "---"),
addressM(serverP ? (isempty(serverP->SrcAddress()) ? serverP->Address() : *cString::sprintf("%s@%s", serverP->SrcAddress(), serverP->Address())) : "---"),
modelM(serverP ? serverP->Model() : "---"),
descriptionM(serverP ? serverP->Description() : "---"),
ciExtensionM(serverP && serverP->HasCI() ? trVDR("yes") : trVDR("no")),
@@ -167,7 +167,7 @@ cSatipServerItem::cSatipServerItem(cSatipServer *serverP)
{
SetSelectable(true);
// Must begin with a '#' character!
SetText(*cString::sprintf("%s %s (%s)\t%s", serverM->IsActive() ? "+" : "-", serverM->Address(), serverM->Model(), serverM->Description()));
SetText(*cString::sprintf("%s %s (%s)\t%s", serverM->IsActive() ? "+" : "-", isempty(serverM->SrcAddress()) ? serverM->Address() : *cString::sprintf("%s@%s", serverM->SrcAddress(), serverM->Address()), serverM->Model(), serverM->Description()));
}
void cSatipServerItem::SetMenuItem(cSkinDisplayMenu *displayMenuP, int indexP, bool currentP, bool selectableP)

View File

@@ -19,13 +19,35 @@
#include "log.h"
#include "socket.h"
#if defined(__GLIBC__)
#if defined(__GLIBC_PREREQ)
#if !__GLIBC_PREREQ(2,12)
#define __SATIP_DISABLE_RECVMMSG__
#endif
#endif
#endif
cSatipSocket::cSatipSocket()
: socketPortM(0),
socketDescM(-1),
isMulticastM(false),
useSsmM(false),
streamAddrM(htonl(INADDR_ANY)),
sourceAddrM(htonl(INADDR_ANY))
sourceAddrM(htonl(INADDR_ANY)),
rcvBufSizeM(0)
{
debug1("%s", __PRETTY_FUNCTION__);
memset(&sockAddrM, 0, sizeof(sockAddrM));
}
cSatipSocket::cSatipSocket(size_t rcvBufSizeP)
: socketPortM(0),
socketDescM(-1),
isMulticastM(false),
useSsmM(false),
streamAddrM(htonl(INADDR_ANY)),
sourceAddrM(htonl(INADDR_ANY)),
rcvBufSizeM(rcvBufSizeP)
{
debug1("%s", __PRETTY_FUNCTION__);
memset(&sockAddrM, 0, sizeof(sockAddrM));
@@ -70,6 +92,11 @@ bool cSatipSocket::Open(const int portP, const bool reuseP)
ERROR_IF_FUNC(setsockopt(socketDescM, SOL_IP, IP_PKTINFO, &yes, sizeof(yes)) < 0,
"setsockopt(IP_PKTINFO)", Close(), return false);
#endif // __FreeBSD__
// Tweak receive buffer size if requested
if (rcvBufSizeM > 0) {
ERROR_IF_FUNC(setsockopt(socketDescM, SOL_SOCKET, SO_RCVBUF, &rcvBufSizeM, sizeof(rcvBufSizeM)) < 0,
"setsockopt(SO_RCVBUF)", Close(), return false);
}
// Bind socket
memset(&sockAddrM, 0, sizeof(sockAddrM));
sockAddrM.sin_family = AF_INET;
@@ -101,7 +128,7 @@ bool cSatipSocket::OpenMulticast(const int portP, const char *streamAddrP, const
void cSatipSocket::Close(void)
{
debug1("%s sockerPort=%d", __PRETTY_FUNCTION__, socketPortM);
debug1("%s socketPort=%d", __PRETTY_FUNCTION__, socketPortM);
// Check if socket exists
if (socketDescM >= 0) {
Leave();
@@ -289,7 +316,7 @@ int cSatipSocket::ReadMulti(unsigned char *bufferAddrP, unsigned int *elementRec
error("%s Invalid parameter(s)", __PRETTY_FUNCTION__);
return -1;
}
#if defined(__GLIBC_PREREQ) && __GLIBC_PREREQ(2,12)
#ifndef __SATIP_DISABLE_RECVMMSG__
// Initialize iov and msgh structures
struct mmsghdr mmsgh[elementCountP];
struct iovec iov[elementCountP];

View File

@@ -19,12 +19,15 @@ private:
bool useSsmM;
in_addr_t streamAddrM;
in_addr_t sourceAddrM;
size_t rcvBufSizeM;
bool CheckAddress(const char *addrP, in_addr_t *inAddrP);
bool Join(void);
bool Leave(void);
public:
cSatipSocket();
explicit cSatipSocket(size_t rcvBufSizeP);
virtual ~cSatipSocket();
bool Open(const int portP = 0, const bool reuseP = false);
bool OpenMulticast(const int portP, const char *streamAddrP, const char *sourceAddrP);

25
tuner.c
View File

@@ -40,6 +40,7 @@ cSatipTuner::cSatipTuner(cSatipDeviceIf &deviceP, unsigned int packetLenP)
externalStateM(),
timeoutM(eMinKeepAliveIntervalMs),
hasLockM(false),
signalStrengthDBmM(0.0),
signalStrengthM(-1),
signalQualityM(-1),
frontendIdM(-1),
@@ -126,6 +127,7 @@ void cSatipTuner::Action(void)
break;
case tsTuned:
debug4("%s: tsTuned [device %d]", __PRETTY_FUNCTION__, deviceIdM);
deviceM->SetChannelTuned();
reConnectM.Set(eConnectTimeoutMs);
idleCheck.Set(eIdleCheckTimeoutMs);
lastIdleStatus = false;
@@ -134,6 +136,7 @@ void cSatipTuner::Action(void)
// Quirk for devices without valid reception data
if (currentServerM.IsQuirk(cSatipServer::eSatipQuirkForceLock)) {
hasLockM = true;
signalStrengthDBmM = eDefaultSignalStrengthDBm;
signalStrengthM = eDefaultSignalStrength;
signalQualityM = eDefaultSignalQuality;
}
@@ -222,12 +225,14 @@ bool cSatipTuner::Connect(void)
return true;
}
}
else if (rtspM.Options(*connectionUri)) {
else if (rtspM.SetInterface(nextServerM.IsValid() ? *nextServerM.GetSrcAddress() : NULL) && rtspM.Options(*connectionUri)) {
cString uri = cString::sprintf("%s?%s", *connectionUri, *streamParamM);
bool useTcp = SatipConfig.IsTransportModeRtpOverTcp() && nextServerM.IsValid() && nextServerM.IsQuirk(cSatipServer::eSatipQuirkRtpOverTcp);
// Flush any old content
//rtpM.Flush();
//rtcpM.Flush();
if (useTcp)
debug1("%s Requesting TCP [device %d]", __PRETTY_FUNCTION__, deviceIdM);
if (rtspM.Setup(*uri, rtpM.Port(), rtcpM.Port(), useTcp)) {
keepAliveM.Set(timeoutM);
if (nextServerM.IsValid()) {
@@ -261,6 +266,7 @@ bool cSatipTuner::Disconnect(void)
// Reset signal parameters
hasLockM = false;
signalStrengthDBmM = 0.0;
signalStrengthM = -1;
signalQualityM = -1;
frontendIdM = -1;
@@ -330,8 +336,9 @@ void cSatipTuner::ProcessApplicationData(u_char *bufferP, int lengthP)
// No signal corresponds to 0
c = strstr(c, ",");
value = min(atoi(++c), 255);
signalStrengthDBmM = (value >= 0) ? 40.0 * (value - 32) / 192.0 - 65.0 : 0.0;
// Scale value to 0-100
signalStrengthM = (value >= 0) ? (value * 100 / 255) : -1;
signalStrengthM = (value >= 0) ? value * 100 / 255 : -1;
// lock:
// lock Set to one of the following values:
@@ -385,8 +392,8 @@ void cSatipTuner::SetupTransport(int rtpPortP, int rtcpPortP, const char *stream
// Adapt RTP to any transport media change
if (multicast != rtpM.IsMulticast() || rtpPortP != rtpM.Port()) {
cSatipPoller::GetInstance()->Unregister(rtpM);
rtpM.Close();
if (rtpPortP >= 0) {
rtpM.Close();
if (multicast)
rtpM.OpenMulticast(rtpPortP, streamAddrP, sourceAddrP);
else
@@ -397,12 +404,12 @@ void cSatipTuner::SetupTransport(int rtpPortP, int rtcpPortP, const char *stream
// Adapt RTCP to any transport media change
if (multicast != rtcpM.IsMulticast() || rtcpPortP != rtcpM.Port()) {
cSatipPoller::GetInstance()->Unregister(rtcpM);
rtcpM.Close();
if (rtcpPortP >= 0) {
rtcpM.Close();
if (multicast)
rtcpM.OpenMulticast(rtpPortP, streamAddrP, sourceAddrP);
rtcpM.OpenMulticast(rtcpPortP, streamAddrP, sourceAddrP);
else
rtcpM.Open(rtpPortP);
rtcpM.Open(rtcpPortP);
cSatipPoller::GetInstance()->Register(rtcpM);
}
}
@@ -667,6 +674,12 @@ int cSatipTuner::SignalStrength(void)
return signalStrengthM;
}
double cSatipTuner::SignalStrengthDBm(void)
{
debug16("%s [device %d]", __PRETTY_FUNCTION__, deviceIdM);
return signalStrengthDBmM;
}
int cSatipTuner::SignalQuality(void)
{
debug16("%s [device %d]", __PRETTY_FUNCTION__, deviceIdM);

24
tuner.h
View File

@@ -69,6 +69,7 @@ public:
void Set(cSatipServer *serverP, const int transponderP) { serverM = serverP; transponderM = transponderP; }
void Reset(void) { serverM = NULL; transponderM = 0; }
cString GetAddress(void) { return serverM ? cSatipDiscover::GetInstance()->GetServerAddress(serverM) : ""; }
cString GetSrcAddress(void) { return serverM ? cSatipDiscover::GetInstance()->GetSourceAddress(serverM) : ""; }
int GetPort(void) { return serverM ? cSatipDiscover::GetInstance()->GetServerPort(serverM) : SATIP_DEFAULT_RTSP_PORT; }
cString GetInfo(void) { return cString::sprintf("server=%s deviceid=%d transponder=%d", serverM ? "assigned" : "null", deviceIdM, transponderM); }
};
@@ -77,16 +78,17 @@ class cSatipTuner : public cThread, public cSatipTunerStatistics, public cSatipT
{
private:
enum {
eDummyPid = 100,
eDefaultSignalStrength = 15,
eDefaultSignalQuality = 224,
eSleepTimeoutMs = 250, // in milliseconds
eStatusUpdateTimeoutMs = 1000, // in milliseconds
ePidUpdateIntervalMs = 250, // in milliseconds
eConnectTimeoutMs = 5000, // in milliseconds
eIdleCheckTimeoutMs = 15000, // in milliseconds
eTuningTimeoutMs = 20000, // in milliseconds
eMinKeepAliveIntervalMs = 30000 // in milliseconds
eDummyPid = 100,
eDefaultSignalStrengthDBm = -25,
eDefaultSignalStrength = 224,
eDefaultSignalQuality = 15,
eSleepTimeoutMs = 250, // in milliseconds
eStatusUpdateTimeoutMs = 1000, // in milliseconds
ePidUpdateIntervalMs = 250, // in milliseconds
eConnectTimeoutMs = 5000, // in milliseconds
eIdleCheckTimeoutMs = 15000, // in milliseconds
eTuningTimeoutMs = 20000, // in milliseconds
eMinKeepAliveIntervalMs = 30000 // in milliseconds
};
enum eTunerState { tsIdle, tsRelease, tsSet, tsTuned, tsLocked };
enum eStateMode { smInternal, smExternal };
@@ -114,6 +116,7 @@ private:
cVector<eTunerState> externalStateM;
int timeoutM;
bool hasLockM;
double signalStrengthDBmM;
int signalStrengthM;
int signalQualityM;
int frontendIdM;
@@ -148,6 +151,7 @@ public:
bool Close(void);
int FrontendId(void);
int SignalStrength(void);
double SignalStrengthDBm(void);
int SignalQuality(void);
bool HasLock(void);
cString GetSignalStatus(void);