mirror of
https://github.com/rofafor/vdr-plugin-satip.git
synced 2023-10-10 11:37:42 +00:00
Compare commits
29 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
02a842f95a | ||
|
a76ff4c25a | ||
|
64554ad0cc | ||
|
0a216f1cf9 | ||
|
02296fa8d7 | ||
|
417d4ed8fc | ||
|
1ad0a81d16 | ||
|
27122747a7 | ||
|
ba0b04ba12 | ||
|
55362a2db6 | ||
|
0115ba1725 | ||
|
43b60b1566 | ||
|
df81905821 | ||
|
cc19cff5e9 | ||
|
63d3c4370b | ||
|
a7625c028c | ||
|
17c36fa9d2 | ||
|
826dea4ba8 | ||
|
a3fa5865f3 | ||
|
19e3057f34 | ||
|
b697e435d4 | ||
|
66d7aae89d | ||
|
a4051bf88c | ||
|
98ecd22a27 | ||
|
8130a4b4e5 | ||
|
5254bb7ca2 | ||
|
6c74c10cbb | ||
|
6e6cd42c84 | ||
|
299296bbb1 |
34
HISTORY
34
HISTORY
@ -193,3 +193,37 @@ VDR Plugin 'satip' Revision History
|
||||
- Added support for FRITZ!Box 6490 Cable (Thanks to 9000h).
|
||||
- Updated FRITZ!WLAN Repeater DVB-C detection for the latest firmware (Thanks to 9000h).
|
||||
- Added GCC7 compatibility (Thanks to Sascha Kuehndel).
|
||||
|
||||
|
||||
===================================
|
||||
VDR Plugin 'satip' Revision History
|
||||
===================================
|
||||
|
||||
2018-04-15: Version 2.4.0
|
||||
|
||||
- Updated for vdr-2.4.0.
|
||||
- Removed speed limit.
|
||||
- Fixed transport media changes.
|
||||
- Fixed memory leak in cSatipSectionFilter (Thanks to Alexander Pipelka).
|
||||
- Added more robust section filter handling (Thanks to Alexander Pipelka).
|
||||
- Added a command line parameter for the RTP receive buffer size (Thanks to Stefan Rehm).
|
||||
|
||||
2021-06-01: Version 2.4.1
|
||||
|
||||
- Added an option to enable/disable frontend reuse.
|
||||
- Added a preliminary ATSC support.
|
||||
- Fixed a channel switching logic bug (Thanks to REELcoder).
|
||||
- Added a workaround for detecting Panasonic devices.
|
||||
- Removed quirks from FRITZ!Box 6490 Cable due to new firmware.
|
||||
- Fixed RTP over TCP.
|
||||
- Fixed URL parameter creation (Thanks to Martin Janser).
|
||||
- Added an option to enable/disable frontend reuse.
|
||||
- Added a preliminary ATSC support.
|
||||
- Fixed a channel switching logic bug (Thanks to REELcoder).
|
||||
- Added quirks for Inverto IDL-400s.
|
||||
- Updated German translation (Thanks to Martin Dummer).
|
||||
- Added a quirk for always teardown before play (Thanks to maazl).
|
||||
- Updated for vdr-2.4.3 (Thanks to <Winfried Koehler).
|
||||
- Added timeout for HasLock (Thanks to Winfried Koehler).
|
||||
- Updated detectsatip script for Python 3.
|
||||
- Fixed keepalive interval.
|
||||
|
127
README
127
README
@ -3,9 +3,9 @@ This is an SAT>IP plugin for the Video Disk Recorder (VDR).
|
||||
Written by: Rolf Ahrenberg
|
||||
< R o l f . A h r e n b e r g @ s c i . f i >
|
||||
|
||||
Project's homepage: http://www.saunalahti.fi/~rahrenbe/vdr/satip/
|
||||
Project's homepage: https://github.com/rofafor/vdr-plugin-satip
|
||||
|
||||
Latest version available at: http://www.saunalahti.fi/~rahrenbe/vdr/satip/
|
||||
Latest version available at: https://github.com/rofafor/vdr-plugin-satip/releases
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License version 2 as
|
||||
@ -47,12 +47,38 @@ be received, if there are available SAT>IP tuners.
|
||||
|
||||
The plugin accepts also a "--server" (-s) command-line parameter, that
|
||||
can be used to manually configure static SAT>IP servers if autodetection
|
||||
via UPnP somehow can't be used. The parameter string is a semicolon
|
||||
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:
|
||||
via UPnP somehow can't be used. Multiple service entries can be given
|
||||
separated by a semicolon:
|
||||
|
||||
[<srcaddress>@]<ipaddress>[:<port>]|<model>[:<filter>]|<description>[:<quirk>];...
|
||||
|
||||
- srcaddress (Optional) Source address can be used to define used
|
||||
networking interface on a host, e.g. 127.0.0.1.
|
||||
- ipaddress IP address of SAT>IP server, e.g. 127.0.0.1.
|
||||
- port (Optional) IP port number of SAT>IP server, e.g 443.
|
||||
- model Model defines DVB modulation system (DVBS2,
|
||||
DVBT2, DVBT, DVBC) and number of available
|
||||
frontends separated by a hyphen, e.g. DVBT2-4.
|
||||
- filter (Optional) Filter can be used to limit satellite frontends
|
||||
to certain satellite position, e.g. S19.2E.
|
||||
- description Friendly name of SAT>IP server. This is used
|
||||
for autodetection of quirks.
|
||||
- quirk (Optional) Quirks are non-standard compliant features and
|
||||
bug fixes of SAT>IP server defined by a
|
||||
hexadecimal number. Multiple quirks can be
|
||||
defined by combining values by addition:
|
||||
|
||||
0x01: Fix session id bug
|
||||
0x02: Fix play parameter (addpids/delpids) bug
|
||||
0x04: Fix frontend locking bug
|
||||
0x08: Support for RTP over TCP
|
||||
0x10: Support the X_PMT protocol extension
|
||||
0x20: Support the CI TNR protocol extension
|
||||
0x40: Fix auto-detection of pilot tones bug
|
||||
0x80: Fix re-tuning bug by teardowning a session
|
||||
|
||||
Examples:
|
||||
|
||||
vdr -P 'satip -s [<srcaddress>@]<ipaddress>[:<port>]|<model>[:<filter>]|<description>[:<quirk>];...'
|
||||
vdr -P 'satip -s 192.168.0.1|DVBS2-2,DVBT2-2|OctopusNet'
|
||||
vdr -P 'satip -s 192.168.0.1|DVBS2-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'
|
||||
@ -86,46 +112,50 @@ Valid range: 1 ... 99
|
||||
|
||||
Setup menu:
|
||||
|
||||
- Operating mode = off If you want exclude all SAT>IP devices
|
||||
low from VDR's device handling, set this
|
||||
normal option to "off". Otherwise, if you want
|
||||
high to keep SAT>IP at a low priority when
|
||||
selecting available devices, set this
|
||||
option to "low". Similarly, the "high"
|
||||
value prefers the SAT>IP over the local
|
||||
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
|
||||
from VDR's EIT background scanning, set
|
||||
this option to "no".
|
||||
- Disabled sources = none If your SAT>IP servers don't have certain
|
||||
satellite positions available you can
|
||||
disable them via this option.
|
||||
- Disabled filters = none Certain section filters might cause some
|
||||
unwanted behaviour to VDR such as time
|
||||
being falsely synchronized etc. This option
|
||||
allows creation of blacklists of ill-behaving
|
||||
filters. If this option is set to a non-zero
|
||||
value, the menu page will contain that many
|
||||
"Disable filter" options which allow you
|
||||
to disable the individual section filters.
|
||||
Valid range: "none" = 0 ... 7
|
||||
- Transport mode = unicast If you want to use the non-standard
|
||||
multicast RTP-over-TCP transport mode, set this option
|
||||
rtp-o-tcp accordingly. Otherwise, the transport
|
||||
mode will be RTP-over-UDP via unicast or
|
||||
multicast.
|
||||
- [Red:Scan] Forces network scanning of SAT>IP hardware.
|
||||
- [Yellow:Devices] Opens SAT>IP device status menu.
|
||||
- [Blue:Info] Opens SAT>IP information/statistics menu.
|
||||
- [Ok] Opens information menu of selected SAT>IP
|
||||
device.
|
||||
- Operating mode = off If you want exclude all SAT>IP devices
|
||||
low from VDR's device handling, set this
|
||||
normal option to "off". Otherwise, if you want
|
||||
high to keep SAT>IP at a low priority when
|
||||
selecting available devices, set this
|
||||
option to "low". Similarly, the "high"
|
||||
value prefers the SAT>IP over the local
|
||||
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
|
||||
from VDR's EIT background scanning, set
|
||||
this option to "no".
|
||||
- Disabled sources = none If your SAT>IP servers don't have certain
|
||||
satellite positions available you can
|
||||
disable them via this option.
|
||||
- Disabled filters = none Certain section filters might cause some
|
||||
unwanted behaviour to VDR such as time
|
||||
being falsely synchronized etc. This option
|
||||
allows creation of blacklists of ill-behaving
|
||||
filters. If this option is set to a non-zero
|
||||
value, the menu page will contain that many
|
||||
"Disable filter" options which allow you
|
||||
to disable the individual section filters.
|
||||
Valid range: "none" = 0 ... 7
|
||||
- Transport mode = unicast If you want to use the non-standard
|
||||
multicast RTP-over-TCP transport mode, set this option
|
||||
rtp-o-tcp accordingly. Otherwise, the transport
|
||||
mode will be RTP-over-UDP via unicast or
|
||||
multicast.
|
||||
- Enable frontend reuse = yes Certain devices might have artifacts if
|
||||
multiple channels are assigned to the same
|
||||
frontend. If you want to avoid such a
|
||||
frontend assignment, set this option to "no".
|
||||
- [Red:Scan] Forces network scanning of SAT>IP hardware.
|
||||
- [Yellow:Devices] Opens SAT>IP device status menu.
|
||||
- [Blue:Info] Opens SAT>IP information/statistics menu.
|
||||
- [Ok] Opens information menu of selected SAT>IP
|
||||
device.
|
||||
|
||||
Information menu:
|
||||
|
||||
@ -159,6 +189,9 @@ Notes:
|
||||
from their webpage: http://www.inverto.tv/support/
|
||||
An update to a newer firmware should be offered afterwards.
|
||||
|
||||
- FRITZ!OS 7.00 or greater recommended for FRITZ!Box Cable devices.
|
||||
Older firmware versions require both PlayPids and ForceLock quirks.
|
||||
|
||||
- If you are experiencing glitches in the video stream, one possible
|
||||
reason can be buffer overflows in RTP receive sockets. You can verify
|
||||
this by checking "receive buffer errors" counter by running "netstat -s"
|
||||
|
1
config.c
1
config.c
@ -15,6 +15,7 @@ cSatipConfig::cSatipConfig(void)
|
||||
: operatingModeM(eOperatingModeLow),
|
||||
traceModeM(eTraceModeNormal),
|
||||
ciExtensionM(0),
|
||||
frontendReuseM(1),
|
||||
eitScanM(1),
|
||||
useBytesM(1),
|
||||
portRangeStartM(0),
|
||||
|
3
config.h
3
config.h
@ -17,6 +17,7 @@ private:
|
||||
unsigned int operatingModeM;
|
||||
unsigned int traceModeM;
|
||||
unsigned int ciExtensionM;
|
||||
unsigned int frontendReuseM;
|
||||
unsigned int eitScanM;
|
||||
unsigned int useBytesM;
|
||||
unsigned int portRangeStartM;
|
||||
@ -74,6 +75,7 @@ public:
|
||||
unsigned int GetTraceMode(void) const { return traceModeM; }
|
||||
bool IsTraceMode(eTraceMode modeP) const { return (traceModeM & modeP); }
|
||||
unsigned int GetCIExtension(void) const { return ciExtensionM; }
|
||||
unsigned int GetFrontendReuse(void) const { return frontendReuseM; }
|
||||
int GetCICAM(unsigned int indexP) const;
|
||||
unsigned int GetEITScan(void) const { return eitScanM; }
|
||||
unsigned int GetUseBytes(void) const { return useBytesM; }
|
||||
@ -95,6 +97,7 @@ public:
|
||||
void SetOperatingMode(unsigned int operatingModeP) { operatingModeM = operatingModeP; }
|
||||
void SetTraceMode(unsigned int modeP) { traceModeM = (modeP & eTraceModeMask); }
|
||||
void SetCIExtension(unsigned int onOffP) { ciExtensionM = onOffP; }
|
||||
void SetFrontendReuse(unsigned int onOffP) { frontendReuseM = onOffP; }
|
||||
void SetCICAM(unsigned int indexP, int cicamP);
|
||||
void SetEITScan(unsigned int onOffP) { eitScanM = onOffP; }
|
||||
void SetUseBytes(unsigned int onOffP) { useBytesM = onOffP; }
|
||||
|
@ -1,5 +1,4 @@
|
||||
#!/usr/bin/env python2
|
||||
# -*- coding: utf-8 -*-
|
||||
#!/usr/bin/env python3
|
||||
""" Simple tool to detect SAT>IP devices as JSON.
|
||||
"""
|
||||
import json
|
||||
@ -8,21 +7,26 @@ import sys
|
||||
import xml.etree.ElementTree as ET
|
||||
import requests
|
||||
|
||||
SSDP_BIND = '0.0.0.0'
|
||||
SSDP_ADDR = '239.255.255.250'
|
||||
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'
|
||||
SSDP_ST = "urn:ses-com:device:SatIPServer:1"
|
||||
SSDP_REQUEST = "\r\n".join(
|
||||
[
|
||||
"M-SEARCH * HTTP/1.1",
|
||||
f"HOST: {SSDP_ADDR}:{SSDP_PORT}",
|
||||
'MAN: "ssdp:discover"',
|
||||
f"MX: {SSDP_MX}",
|
||||
f"ST: {SSDP_ST}",
|
||||
"USER-AGENT: vdr-detectsatip",
|
||||
"\r\n",
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
def parse_satip_xml(data):
|
||||
""" Parse SAT>IP XML data.
|
||||
"""Parse SAT>IP XML data.
|
||||
|
||||
Args:
|
||||
data (str): XML input data..
|
||||
@ -30,12 +34,15 @@ def parse_satip_xml(data):
|
||||
Returns:
|
||||
dict: Parsed SAT>IP device name and frontend information.
|
||||
"""
|
||||
result = {'name': '', 'frontends': {}}
|
||||
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')
|
||||
name = root.find(".//*/{urn:schemas-upnp-org:device-1-0}friendlyName")
|
||||
result["name"] = name.text
|
||||
satipcap = root.find(".//*/{urn:ses-com:satip}X_SATIPCAP")
|
||||
if satipcap is None:
|
||||
# fallback for non-standard Panasonic
|
||||
satipcap = root.find(".//*/{urn-ses-com:satip}X_SATIPCAP")
|
||||
caps = {}
|
||||
for system in satipcap.text.split(","):
|
||||
cap = system.split("-")
|
||||
@ -44,12 +51,12 @@ def parse_satip_xml(data):
|
||||
if cap[0] in caps:
|
||||
count = count + caps[cap[0]]
|
||||
caps[cap[0]] = count
|
||||
result['frontends'] = caps
|
||||
result["frontends"] = caps
|
||||
return result
|
||||
|
||||
|
||||
def detect_satip_devices():
|
||||
""" Detect available SAT>IP devices by sending a broadcast message.
|
||||
"""Detect available SAT>IP devices by sending a broadcast message.
|
||||
|
||||
Returns:
|
||||
list: Found SAT>IP devices.
|
||||
@ -66,14 +73,14 @@ def detect_satip_devices():
|
||||
pass
|
||||
sock.settimeout(1)
|
||||
sock.bind((SSDP_BIND, SSDP_PORT))
|
||||
sock.sendto(SSDP_REQUEST, (SSDP_ADDR, SSDP_PORT))
|
||||
sock.sendto(SSDP_REQUEST.encode("utf-8"), (SSDP_ADDR, SSDP_PORT))
|
||||
try:
|
||||
while 1:
|
||||
data = sock.recv(1024)
|
||||
data = sock.recv(1024).decode("utf-8")
|
||||
if data:
|
||||
for row in data.split('\r\n'):
|
||||
if 'LOCATION:' in row:
|
||||
url = row.replace('LOCATION:', '').strip()
|
||||
for row in data.split("\r\n"):
|
||||
if "LOCATION:" in row:
|
||||
url = row.replace("LOCATION:", "").strip()
|
||||
if url in urls:
|
||||
continue
|
||||
urls.append(url)
|
||||
@ -87,5 +94,5 @@ def detect_satip_devices():
|
||||
return devices
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
if __name__ == "__main__":
|
||||
json.dump(detect_satip_devices(), fp=sys.stdout, sort_keys=True, indent=2)
|
||||
|
18
device.c
18
device.c
@ -295,10 +295,10 @@ bool cSatipDevice::ProvidesChannel(const cChannel *channelP, int priorityP, bool
|
||||
result = true;
|
||||
}
|
||||
else
|
||||
result = true;
|
||||
result = !!SatipConfig.GetFrontendReuse();
|
||||
}
|
||||
else
|
||||
needsDetachReceivers = Receiving();
|
||||
needsDetachReceivers = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -309,7 +309,11 @@ bool cSatipDevice::ProvidesChannel(const cChannel *channelP, int priorityP, bool
|
||||
|
||||
bool cSatipDevice::ProvidesEIT(void) const
|
||||
{
|
||||
#if defined(APIVERSNUM) && APIVERSNUM < 20403
|
||||
return (SatipConfig.GetEITScan());
|
||||
#else
|
||||
return (SatipConfig.GetEITScan()) && DeviceHooksProvidesEIT();
|
||||
#endif
|
||||
}
|
||||
|
||||
int cSatipDevice::NumProvidedSystems(void) const
|
||||
@ -390,7 +394,7 @@ void cSatipDevice::SetChannelTuned(void)
|
||||
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);
|
||||
if (pTunerM && handleP && handleP->pid >= 0) {
|
||||
if (pTunerM && handleP && handleP->pid >= 0 && handleP->pid <= 8191) {
|
||||
if (onP)
|
||||
return pTunerM->SetPid(handleP->pid, typeP, true);
|
||||
else if (!handleP->used && pSectionFilterHandlerM && !pSectionFilterHandlerM->Exists(handleP->pid))
|
||||
@ -444,6 +448,14 @@ void cSatipDevice::CloseDvr(void)
|
||||
bool cSatipDevice::HasLock(int timeoutMsP) const
|
||||
{
|
||||
debug16("%s (%d) [device %d]", __PRETTY_FUNCTION__, timeoutMsP, deviceIndexM);
|
||||
if (timeoutMsP > 0) {
|
||||
cTimeMs timer(timeoutMsP);
|
||||
while (!timer.TimedOut()) {
|
||||
if (pTunerM && pTunerM->HasLock())
|
||||
return true;
|
||||
cCondWait::SleepMs(100);
|
||||
}
|
||||
}
|
||||
return (pTunerM && pTunerM->HasLock());
|
||||
}
|
||||
|
||||
|
@ -76,13 +76,13 @@ void cSatipMsearch::Process(void)
|
||||
if (status) {
|
||||
// Check the location data
|
||||
// LOCATION: http://192.168.0.115:8888/octonet.xml
|
||||
if (startswith(r, "LOCATION:")) {
|
||||
if (strcasestr(r, "LOCATION:") == r) {
|
||||
location = compactspace(r + 9);
|
||||
debug1("%s location='%s'", __PRETTY_FUNCTION__, location);
|
||||
}
|
||||
// Check the source type
|
||||
// ST: urn:ses-com:device:SatIPServer:1
|
||||
else if (startswith(r, "ST:")) {
|
||||
else if (strcasestr(r, "ST:") == r) {
|
||||
char *st = compactspace(r + 3);
|
||||
if (strstr(st, "urn:ses-com:device:SatIPServer:1"))
|
||||
valid = true;
|
||||
|
62
param.c
62
param.c
@ -59,6 +59,10 @@ static const tSatipParameterMap SatipCodeRateValues[] = {
|
||||
static const tSatipParameterMap SatipModulationValues[] = {
|
||||
{ QPSK, "&mtype=qpsk" },
|
||||
{ PSK_8, "&mtype=8psk" },
|
||||
{ APSK_16, "&mtype=16apsk" },
|
||||
{ APSK_32, "&mtype=32apsk" },
|
||||
{ VSB_8, "&mtype=8vsb" },
|
||||
{ VSB_16, "&mtype=16vsb" },
|
||||
{ QAM_16, "&mtype=16qam" },
|
||||
{ QAM_64, "&mtype=64qam" },
|
||||
{ QAM_128, "&mtype=128qam" },
|
||||
@ -85,6 +89,11 @@ static const tSatipParameterMap SatipSystemValuesCable[] = {
|
||||
{ -1, NULL }
|
||||
};
|
||||
|
||||
static const tSatipParameterMap SatipSystemValuesAtsc[] = {
|
||||
{ 0, "&msys=atsc" },
|
||||
{ -1, NULL }
|
||||
};
|
||||
|
||||
static const tSatipParameterMap SatipTransmissionValues[] = {
|
||||
{ TRANSMISSION_MODE_1K, "&tmode=1k" },
|
||||
{ TRANSMISSION_MODE_2K, "&tmode=2k" },
|
||||
@ -165,33 +174,36 @@ 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);
|
||||
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);
|
||||
ST("C 2") q += snprintf(q, STBUFLEFT, "&c2tft=%d", C2TuningFrequencyType);
|
||||
ST(" T*") q += PrintUrlString(q, STBUFLEFT, dtp.Bandwidth(), SatipBandwidthValues);
|
||||
ST("C 2") q += PrintUrlString(q, STBUFLEFT, dtp.Bandwidth(), SatipBandwidthValues);
|
||||
ST(" S *") q += PrintUrlString(q, STBUFLEFT, dtp.System(), SatipSystemValuesSat);
|
||||
ST("C *") q += PrintUrlString(q, STBUFLEFT, dtp.System(), SatipSystemValuesCable);
|
||||
ST(" T*") q += PrintUrlString(q, STBUFLEFT, dtp.System(), SatipSystemValuesTerrestrial);
|
||||
ST(" T*") q += PrintUrlString(q, STBUFLEFT, dtp.Transmission(), SatipTransmissionValues);
|
||||
ST(" S *") q += PrintUrlString(q, STBUFLEFT, dtp.Modulation(), SatipModulationValues);
|
||||
ST(" T*") q += PrintUrlString(q, STBUFLEFT, dtp.Modulation(), SatipModulationValues);
|
||||
ST("C 1") q += PrintUrlString(q, STBUFLEFT, dtp.Modulation(), SatipModulationValues);
|
||||
ST(" S *") q += PrintUrlString(q, STBUFLEFT, dtp.Pilot(), SatipPilotValues);
|
||||
ST(" S *") q += snprintf(q, STBUFLEFT, "&sr=%d", channelP->Srate());
|
||||
ST("C 1") q += snprintf(q, STBUFLEFT, "&sr=%d", channelP->Srate());
|
||||
ST(" T*") q += PrintUrlString(q, STBUFLEFT, dtp.Guard(), SatipGuardValues);
|
||||
ST("CST*") q += PrintUrlString(q, STBUFLEFT, dtp.CoderateH(), SatipCodeRateValues);
|
||||
ST("C 2") q += snprintf(q, STBUFLEFT, "&ds=%d", DataSlice);
|
||||
ST("C T2") q += snprintf(q, STBUFLEFT, "&plp=%d", dtp.StreamId());
|
||||
ST(" T2") q += snprintf(q, STBUFLEFT, "&t2id=%d", dtp.T2SystemId());
|
||||
ST(" T2") q += PrintUrlString(q, STBUFLEFT, dtp.SisoMiso(), SatipSisoMisoValues);
|
||||
ST("C 1") q += PrintUrlString(q, STBUFLEFT, dtp.Inversion(), SatipInversionValues);
|
||||
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);
|
||||
ST(" C 2") q += snprintf(q, STBUFLEFT, "&c2tft=%d", C2TuningFrequencyType);
|
||||
ST(" T*") q += PrintUrlString(q, STBUFLEFT, dtp.Bandwidth(), SatipBandwidthValues);
|
||||
ST(" C 2") q += PrintUrlString(q, STBUFLEFT, dtp.Bandwidth(), SatipBandwidthValues);
|
||||
ST(" S *") q += PrintUrlString(q, STBUFLEFT, dtp.System(), SatipSystemValuesSat);
|
||||
ST(" C *") q += PrintUrlString(q, STBUFLEFT, dtp.System(), SatipSystemValuesCable);
|
||||
ST(" T*") q += PrintUrlString(q, STBUFLEFT, dtp.System(), SatipSystemValuesTerrestrial);
|
||||
ST("A *") q += PrintUrlString(q, STBUFLEFT, dtp.System(), SatipSystemValuesAtsc);
|
||||
ST(" T*") q += PrintUrlString(q, STBUFLEFT, dtp.Transmission(), SatipTransmissionValues);
|
||||
ST(" S *") q += PrintUrlString(q, STBUFLEFT, dtp.Modulation(), SatipModulationValues);
|
||||
ST(" T*") q += PrintUrlString(q, STBUFLEFT, dtp.Modulation(), SatipModulationValues);
|
||||
ST(" C 1") q += PrintUrlString(q, STBUFLEFT, dtp.Modulation(), SatipModulationValues);
|
||||
ST("A *") q += PrintUrlString(q, STBUFLEFT, dtp.Modulation(), SatipModulationValues);
|
||||
ST(" S *") q += PrintUrlString(q, STBUFLEFT, dtp.Pilot(), SatipPilotValues);
|
||||
ST(" S *") q += snprintf(q, STBUFLEFT, "&sr=%d", channelP->Srate());
|
||||
ST(" C 1") q += snprintf(q, STBUFLEFT, "&sr=%d", channelP->Srate());
|
||||
ST(" T*") q += PrintUrlString(q, STBUFLEFT, dtp.Guard(), SatipGuardValues);
|
||||
ST(" CST*") q += PrintUrlString(q, STBUFLEFT, dtp.CoderateH(), SatipCodeRateValues);
|
||||
ST(" C 2") q += snprintf(q, STBUFLEFT, "&ds=%d", DataSlice);
|
||||
ST(" C T2") q += snprintf(q, STBUFLEFT, "&plp=%d", dtp.StreamId());
|
||||
ST(" T2") q += snprintf(q, STBUFLEFT, "&t2id=%d", dtp.T2SystemId());
|
||||
ST(" T2") q += PrintUrlString(q, STBUFLEFT, dtp.SisoMiso(), SatipSisoMisoValues);
|
||||
ST(" C 1") q += PrintUrlString(q, STBUFLEFT, dtp.Inversion(), SatipInversionValues);
|
||||
ST("A *") q += PrintUrlString(q, STBUFLEFT, dtp.Inversion(), SatipInversionValues);
|
||||
#undef ST
|
||||
return buffer;
|
||||
return &buffer[1];
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
14
po/ca_ES.po
14
po/ca_ES.po
@ -1,14 +1,14 @@
|
||||
# VDR plugin language source file.
|
||||
# Copyright (C) 2007-2017 Rolf Ahrenberg
|
||||
# Copyright (C) 2007-2019 Rolf Ahrenberg
|
||||
# This file is distributed under the same license as the satip package.
|
||||
# Gabriel Bonich, 2014-2017
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: vdr-satip 2.3.1\n"
|
||||
"Project-Id-Version: vdr-satip 2.4.0\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"
|
||||
"POT-Creation-Date: 2019-10-27 19:12+0200\n"
|
||||
"PO-Revision-Date: 2019-10-27 10:27+0200\n"
|
||||
"Last-Translator: Gabriel Bonich <gbonich@gmail.com>\n"
|
||||
"Language-Team: Catalan <vdr@linuxtv.org>\n"
|
||||
"Language: ca\n"
|
||||
@ -196,6 +196,12 @@ msgid ""
|
||||
"Unicast, Multicast, RTP-over-TCP"
|
||||
msgstr ""
|
||||
|
||||
msgid "Enable frontend reuse"
|
||||
msgstr ""
|
||||
|
||||
msgid "Define whether reusing a frontend for multiple channels in a transponder should be enabled."
|
||||
msgstr ""
|
||||
|
||||
msgid "Active SAT>IP servers:"
|
||||
msgstr "Activa SAT>IP servers:"
|
||||
|
||||
|
22
po/de_DE.po
22
po/de_DE.po
@ -1,14 +1,14 @@
|
||||
# VDR plugin language source file.
|
||||
# Copyright (C) 2007-2017 Rolf Ahrenberg
|
||||
# Copyright (C) 2007-2019 Rolf Ahrenberg
|
||||
# This file is distributed under the same license as the satip package.
|
||||
# Frank Neumann, 2014-2017
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: vdr-satip 2.3.1\n"
|
||||
"Project-Id-Version: vdr-satip 2.4.0\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"
|
||||
"POT-Creation-Date: 2019-10-27 19:12+0200\n"
|
||||
"PO-Revision-Date: 2019-10-27 10:27+0200\n"
|
||||
"Last-Translator: Frank Neumann <fnu@yavdr.org>\n"
|
||||
"Language-Team: German <vdr@linuxtv.org>\n"
|
||||
"Language: de\n"
|
||||
@ -56,7 +56,7 @@ msgid "Creation date"
|
||||
msgstr "Zeitpunkt der Erstellung"
|
||||
|
||||
msgid "SAT>IP Device Status"
|
||||
msgstr "SAT>IP Geräte Status"
|
||||
msgstr "SAT>IP Gerätestatus"
|
||||
|
||||
msgid "SAT>IP Information"
|
||||
msgstr "SAT>IP Informationen"
|
||||
@ -110,10 +110,10 @@ msgid ""
|
||||
msgstr ""
|
||||
"Bestimme die Betriebsart für alle SAT>IP Geräte:\n"
|
||||
"\n"
|
||||
"aus - Geräte sind abgeschaltet\n"
|
||||
"aus - Geräte sind deaktiviert\n"
|
||||
"niedrig - Geräte arbeiten mit geringster Priorität\n"
|
||||
"normal - Geräte arbeiten innerhalb der gewöhnlichen Parameter\n"
|
||||
"hoch - Geräte arbeiten mit höchste Priorität"
|
||||
"hoch - Geräte arbeiten mit höchster Priorität"
|
||||
|
||||
msgid "Enable CI extension"
|
||||
msgstr "Aktiviere CI Erweiterung"
|
||||
@ -149,7 +149,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Legt fest ob EPG im Hintergrund aktualisiert werden soll oder nicht.\n"
|
||||
"\n"
|
||||
"Diese Einstellung schaltet die automatische EIT Aktualisierung für alle SAT>IP Geräte."
|
||||
"Diese Einstellung schaltet die automatische EIT Aktualisierung für alle SAT>IP Geräte aus."
|
||||
|
||||
msgid "Disabled sources"
|
||||
msgstr "Deaktivierte Quellen"
|
||||
@ -199,6 +199,12 @@ msgstr ""
|
||||
"\n"
|
||||
"Unicast, Multicast, RTP-over-TCP"
|
||||
|
||||
msgid "Enable frontend reuse"
|
||||
msgstr "Frontend Mehrfachnutzung aktivieren"
|
||||
|
||||
msgid "Define whether reusing a frontend for multiple channels in a transponder should be enabled."
|
||||
msgstr "Festlegung ob ein Tuner-Frontend für mehrere Kanäle genutzt wird."
|
||||
|
||||
msgid "Active SAT>IP servers:"
|
||||
msgstr "Aktive SAT>IP Server:"
|
||||
|
||||
|
14
po/es_ES.po
14
po/es_ES.po
@ -1,14 +1,14 @@
|
||||
# VDR plugin language source file.
|
||||
# Copyright (C) 2007-2017 Rolf Ahrenberg
|
||||
# Copyright (C) 2007-2019 Rolf Ahrenberg
|
||||
# This file is distributed under the same license as the satip package.
|
||||
# Gabriel Bonich, 2014-2017
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: vdr-satip 2.3.1\n"
|
||||
"Project-Id-Version: vdr-satip 2.4.0\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"
|
||||
"POT-Creation-Date: 2019-10-27 19:12+0200\n"
|
||||
"PO-Revision-Date: 2019-10-27 10:27+0200\n"
|
||||
"Last-Translator: Gabriel Bonich <gbonich@gmail.com>\n"
|
||||
"Language-Team: Spanish <vdr@linuxtv.org>\n"
|
||||
"Language: es\n"
|
||||
@ -196,6 +196,12 @@ msgid ""
|
||||
"Unicast, Multicast, RTP-over-TCP"
|
||||
msgstr ""
|
||||
|
||||
msgid "Enable frontend reuse"
|
||||
msgstr ""
|
||||
|
||||
msgid "Define whether reusing a frontend for multiple channels in a transponder should be enabled."
|
||||
msgstr ""
|
||||
|
||||
msgid "Active SAT>IP servers:"
|
||||
msgstr "Activa SAT>IP servers:"
|
||||
|
||||
|
16
po/fi_FI.po
16
po/fi_FI.po
@ -1,14 +1,14 @@
|
||||
# VDR plugin language source file.
|
||||
# Copyright (C) 2007-2017 Rolf Ahrenberg
|
||||
# Copyright (C) 2007-2019 Rolf Ahrenberg
|
||||
# This file is distributed under the same license as the satip package.
|
||||
# Rolf Ahrenberg, 2015-2017
|
||||
# Rolf Ahrenberg, 2015-2019
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: vdr-satip 2.3.1\n"
|
||||
"Project-Id-Version: vdr-satip 2.4.0\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"
|
||||
"POT-Creation-Date: 2019-10-27 19:12+0200\n"
|
||||
"PO-Revision-Date: 2019-10-27 10:27+0200\n"
|
||||
"Last-Translator: Rolf Ahrenberg\n"
|
||||
"Language-Team: Finnish <vdr@linuxtv.org>\n"
|
||||
"Language: fi\n"
|
||||
@ -198,6 +198,12 @@ msgstr ""
|
||||
"\n"
|
||||
"Unicast, Multicast, RTP-over-TCP"
|
||||
|
||||
msgid "Enable frontend reuse"
|
||||
msgstr "Uusiokäytä virittimiä"
|
||||
|
||||
msgid "Define whether reusing a frontend for multiple channels in a transponder should be enabled."
|
||||
msgstr "Määrittele virittien uusiokäyttö kanaville, jotka ovat samalla transponderilla."
|
||||
|
||||
msgid "Active SAT>IP servers:"
|
||||
msgstr "Aktiiviset SAT>IP-palvelimet:"
|
||||
|
||||
|
14
po/pl_PL.po
14
po/pl_PL.po
@ -1,14 +1,14 @@
|
||||
# VDR plugin language source file.
|
||||
# Copyright (C) 2007-2017 Rolf Ahrenberg
|
||||
# Copyright (C) 2007-2019 Rolf Ahrenberg
|
||||
# This file is distributed under the same license as the vdr-satip package.
|
||||
# Tomasz Maciej Nowak, 2017
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: vdr-satip 2.3.1\n"
|
||||
"Project-Id-Version: vdr-satip 2.4.0\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"
|
||||
"POT-Creation-Date: 2019-10-27 19:12+0200\n"
|
||||
"PO-Revision-Date: 2019-10-27 10:27+0200\n"
|
||||
"Last-Translator: Tomasz Maciej Nowak <tomek_n@o2.pl>\n"
|
||||
"Language-Team: Polish <vdr@linuxtv.org>\n"
|
||||
"Language: pl_PL\n"
|
||||
@ -199,6 +199,12 @@ msgstr ""
|
||||
"Określa tryb transmisji.\n"
|
||||
"Unicast, Multicast, RTP-over-TCP."
|
||||
|
||||
msgid "Enable frontend reuse"
|
||||
msgstr ""
|
||||
|
||||
msgid "Define whether reusing a frontend for multiple channels in a transponder should be enabled."
|
||||
msgstr ""
|
||||
|
||||
msgid "Active SAT>IP servers:"
|
||||
msgstr "Aktywne serwery SAT>IP:"
|
||||
|
||||
|
28
rtcp.c
28
rtcp.c
@ -34,7 +34,7 @@ int cSatipRtcp::GetFd(void)
|
||||
return Fd();
|
||||
}
|
||||
|
||||
int cSatipRtcp::GetApplicationOffset(int *lengthP)
|
||||
int cSatipRtcp::GetApplicationOffset(unsigned char *bufferP, int *lengthP)
|
||||
{
|
||||
debug16("%s (%d) [device %d]", __PRETTY_FUNCTION__, lengthP ? *lengthP : -1, tunerM.GetId());
|
||||
if (!lengthP)
|
||||
@ -43,29 +43,29 @@ int cSatipRtcp::GetApplicationOffset(int *lengthP)
|
||||
int total = *lengthP;
|
||||
while (total > 0) {
|
||||
// Version
|
||||
unsigned int v = (bufferM[offset] >> 6) & 0x03;
|
||||
unsigned int v = (bufferP[offset] >> 6) & 0x03;
|
||||
// Padding
|
||||
//unsigned int p = (bufferM[offset] >> 5) & 0x01;
|
||||
//unsigned int p = (bufferP[offset] >> 5) & 0x01;
|
||||
// Subtype
|
||||
//unsigned int st = bufferM[offset] & 0x1F;
|
||||
//unsigned int st = bufferP[offset] & 0x1F;
|
||||
// Payload type
|
||||
unsigned int pt = bufferM[offset + 1] & 0xFF;
|
||||
unsigned int pt = bufferP[offset + 1] & 0xFF;
|
||||
// Length
|
||||
unsigned int length = ((bufferM[offset + 2] & 0xFF) << 8) | (bufferM[offset + 3] & 0xFF);
|
||||
unsigned int length = ((bufferP[offset + 2] & 0xFF) << 8) | (bufferP[offset + 3] & 0xFF);
|
||||
// Convert it to bytes
|
||||
length = (length + 1) * 4;
|
||||
// V=2, APP = 204
|
||||
if ((v == 2) && (pt == 204)) {
|
||||
// SSCR/CSCR
|
||||
//unsigned int ssrc = ((bufferM[offset + 4] & 0xFF) << 24) | ((bufferM[offset + 5] & 0xFF) << 16) |
|
||||
// ((bufferM[offset + 6] & 0xFF) << 8) | (bufferM[offset + 7] & 0xFF);
|
||||
//unsigned int ssrc = ((bufferP[offset + 4] & 0xFF) << 24) | ((bufferP[offset + 5] & 0xFF) << 16) |
|
||||
// ((bufferP[offset + 6] & 0xFF) << 8) | (bufferP[offset + 7] & 0xFF);
|
||||
// Name
|
||||
if ((bufferM[offset + 8] == 'S') && (bufferM[offset + 9] == 'E') &&
|
||||
(bufferM[offset + 10] == 'S') && (bufferM[offset + 11] == '1')) {
|
||||
if ((bufferP[offset + 8] == 'S') && (bufferP[offset + 9] == 'E') &&
|
||||
(bufferP[offset + 10] == 'S') && (bufferP[offset + 11] == '1')) {
|
||||
// Identifier
|
||||
//unsigned int id = ((bufferM[offset + 12] & 0xFF) << 8) | (bufferM[offset + 13] & 0xFF);
|
||||
//unsigned int id = ((bufferP[offset + 12] & 0xFF) << 8) | (bufferP[offset + 13] & 0xFF);
|
||||
// String length
|
||||
int string_length = ((bufferM[offset + 14] & 0xFF) << 8) | (bufferM[offset + 15] & 0xFF);
|
||||
int string_length = ((bufferP[offset + 14] & 0xFF) << 8) | (bufferP[offset + 15] & 0xFF);
|
||||
if (string_length > 0) {
|
||||
*lengthP = string_length;
|
||||
return (offset + 16);
|
||||
@ -85,7 +85,7 @@ void cSatipRtcp::Process(void)
|
||||
if (bufferM) {
|
||||
int length;
|
||||
while ((length = Read(bufferM, bufferLenM)) > 0) {
|
||||
int offset = GetApplicationOffset(&length);
|
||||
int offset = GetApplicationOffset(bufferM, &length);
|
||||
if (offset >= 0)
|
||||
tunerM.ProcessApplicationData(bufferM + offset, length);
|
||||
}
|
||||
@ -96,7 +96,7 @@ void cSatipRtcp::Process(unsigned char *dataP, int lengthP)
|
||||
{
|
||||
debug16("%s [device %d]", __PRETTY_FUNCTION__, tunerM.GetId());
|
||||
if (dataP && lengthP > 0) {
|
||||
int offset = GetApplicationOffset(&lengthP);
|
||||
int offset = GetApplicationOffset(dataP, &lengthP);
|
||||
if (offset >= 0)
|
||||
tunerM.ProcessApplicationData(dataP + offset, lengthP);
|
||||
}
|
||||
|
2
rtcp.h
2
rtcp.h
@ -20,7 +20,7 @@ private:
|
||||
cSatipTunerIf &tunerM;
|
||||
unsigned int bufferLenM;
|
||||
unsigned char *bufferM;
|
||||
int GetApplicationOffset(int *lengthP);
|
||||
int GetApplicationOffset(unsigned char *bufferP, int *lengthP);
|
||||
|
||||
public:
|
||||
explicit cSatipRtcp(cSatipTunerIf &tunerP);
|
||||
|
22
rtsp.c
22
rtsp.c
@ -206,6 +206,28 @@ bool cSatipRtsp::SetInterface(const char *bindAddrP)
|
||||
return result;
|
||||
}
|
||||
|
||||
bool cSatipRtsp::Receive(const char *uriP)
|
||||
{
|
||||
debug1("%s (%s) [device %d]", __PRETTY_FUNCTION__, uriP, tunerM.GetId());
|
||||
bool result = false;
|
||||
|
||||
if (handleM && !isempty(uriP) && modeM == cSatipConfig::eTransportModeRtpOverTcp) {
|
||||
long rc = 0;
|
||||
cTimeMs processing(0);
|
||||
CURLcode res = CURLE_OK;
|
||||
|
||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_URL, uriP);
|
||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_RTSP_STREAM_URI, uriP);
|
||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_RTSP_REQUEST, (long)CURL_RTSPREQ_OPTIONS); // FIXME: this really should be CURL_RTSPREQ_RECEIVE, but getting timeout errors
|
||||
SATIP_CURL_EASY_PERFORM(handleM);
|
||||
|
||||
result = ValidateLatestResponse(&rc);
|
||||
debug5("%s (%s) Response %ld in %" PRIu64 " ms [device %d]", __PRETTY_FUNCTION__, uriP, rc, processing.Elapsed(), tunerM.GetId());
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool cSatipRtsp::Options(const char *uriP)
|
||||
{
|
||||
debug1("%s (%s) [device %d]", __PRETTY_FUNCTION__, uriP, tunerM.GetId());
|
||||
|
1
rtsp.h
1
rtsp.h
@ -59,6 +59,7 @@ public:
|
||||
cString RtspUnescapeString(const char *strP);
|
||||
void Reset(void);
|
||||
bool SetInterface(const char *bindAddrP);
|
||||
bool Receive(const char *uriP);
|
||||
bool Options(const char *uriP);
|
||||
bool Setup(const char *uriP, int rtpPortP, int rtcpPortP, bool useTcpP);
|
||||
bool SetSession(const char *sessionP);
|
||||
|
35
satip.c
35
satip.c
@ -20,15 +20,15 @@
|
||||
#warning "CURL version >= 7.36.0 is recommended"
|
||||
#endif
|
||||
|
||||
#if defined(APIVERSNUM) && APIVERSNUM < 20307
|
||||
#error "VDR-2.3.7 API version or greater is required!"
|
||||
#if defined(APIVERSNUM) && APIVERSNUM < 20400
|
||||
#error "VDR-2.4.0 API version or greater is required!"
|
||||
#endif
|
||||
|
||||
#ifndef GITVERSION
|
||||
#define GITVERSION ""
|
||||
#endif
|
||||
|
||||
const char VERSION[] = "2.3.1" GITVERSION;
|
||||
const char VERSION[] = "2.4.1" GITVERSION;
|
||||
static const char DESCRIPTION[] = trNOOP("SAT>IP Devices");
|
||||
|
||||
class cPluginSatip : public cPlugin {
|
||||
@ -85,8 +85,31 @@ const char *cPluginSatip::CommandLineHelp(void)
|
||||
// Return a string that describes all known command line options.
|
||||
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>:<port>|<model2>:<filter>|<desc2>:<quirk>\n"
|
||||
" define hard-coded SAT>IP server(s)\n"
|
||||
" -s <ipaddr>|<model>|<desc>, --server=[<srcaddress>@]<ipaddress>[:<port>]|<model>[:<filter>]|<description>[:<quirk>];...\n"
|
||||
" define hard-coded SAT>IP server(s)\n\n"
|
||||
" srcaddress (Optional) Source address can be used to define used\n"
|
||||
" networking interface on a host, e.g. 127.0.0.1.\n"
|
||||
" ipaddress IP address of SAT>IP server, e.g. 127.0.0.1.\n"
|
||||
" port (Optional) IP port number of SAT>IP server, e.g 443.\n"
|
||||
" model Model defines DVB modulation system (DVBS2,\n"
|
||||
" DVBT2, DVBT, DVBC) and number of available\n"
|
||||
" frontends separated by a hyphen, e.g. DVBT2-4.\n"
|
||||
" filter (Optional) Filter can be used to limit satellite frontends\n"
|
||||
" to certain satellite position, e.g. S19.2E.\n"
|
||||
" description Friendly name of SAT>IP server. This is used\n"
|
||||
" for autodetection of quirks.\n"
|
||||
" quirk (Optional) Quirks are non-standard compliant features and\n"
|
||||
" bug fixes of SAT>IP server defined by a\n"
|
||||
" hexadecimal number. Multiple quirks can be\n"
|
||||
" defined by combining values by addition:\n\n"
|
||||
" 0x01: Fix session id bug\n"
|
||||
" 0x02: Fix play parameter (addpids/delpids) bug\n"
|
||||
" 0x04: Fix frontend locking bug\n"
|
||||
" 0x08: Support for RTP over TCP\n"
|
||||
" 0x10: Support the X_PMT protocol extension\n"
|
||||
" 0x20: Support the CI TNR protocol extension\n"
|
||||
" 0x40: Fix auto-detection of pilot tones bug\n"
|
||||
" 0x80: Fix re-tuning bug by teardowning a session\n"
|
||||
" -D, --detach set the detached mode on\n"
|
||||
" -S, --single set the single model server mode on\n"
|
||||
" -n, --noquirks disable autodetection of the server quirks\n"
|
||||
@ -392,6 +415,8 @@ bool cPluginSatip::SetupParse(const char *nameP, const char *valueP)
|
||||
SatipConfig.SetOperatingMode(atoi(valueP));
|
||||
else if (!strcasecmp(nameP, "EnableCIExtension"))
|
||||
SatipConfig.SetCIExtension(atoi(valueP));
|
||||
else if (!strcasecmp(nameP, "EnableFrontendReuse"))
|
||||
SatipConfig.SetFrontendReuse(atoi(valueP));
|
||||
else if (!strcasecmp(nameP, "CICAM")) {
|
||||
int Cicams[MAX_CICAM_COUNT];
|
||||
for (unsigned int i = 0; i < ELEMENTS(Cicams); ++i)
|
||||
|
@ -18,35 +18,14 @@ cSatipSectionFilter::cSatipSectionFilter(int deviceIndexP, uint16_t pidP, uint8_
|
||||
secLenM(0),
|
||||
tsFeedpM(0),
|
||||
pidM(pidP),
|
||||
tidM(tidP),
|
||||
maskM(maskP),
|
||||
ringBufferM(new cRingBufferFrame(eDmxMaxSectionCount * eDmxMaxSectionSize)),
|
||||
deviceIndexM(deviceIndexP)
|
||||
{
|
||||
debug16("%s (%d, %d, %d, %d) [device %d]", __PRETTY_FUNCTION__, deviceIndexM, pidM, tidP, maskP, deviceIndexM);
|
||||
int i;
|
||||
|
||||
memset(secBufBaseM, 0, sizeof(secBufBaseM));
|
||||
memset(filterValueM, 0, sizeof(filterValueM));
|
||||
memset(filterMaskM, 0, sizeof(filterMaskM));
|
||||
memset(filterModeM, 0, sizeof(filterModeM));
|
||||
memset(maskAndModeM, 0, sizeof(maskAndModeM));
|
||||
memset(maskAndNotModeM, 0, sizeof(maskAndNotModeM));
|
||||
|
||||
filterValueM[0] = tidP;
|
||||
filterMaskM[0] = maskP;
|
||||
|
||||
// Invert the filter
|
||||
for (i = 0; i < eDmxMaxFilterSize; ++i)
|
||||
filterValueM[i] ^= 0xFF;
|
||||
|
||||
uint8_t doneq = 0;
|
||||
for (i = 0; i < eDmxMaxFilterSize; ++i) {
|
||||
uint8_t mode = filterModeM[i];
|
||||
uint8_t mask = filterMaskM[i];
|
||||
maskAndModeM[i] = (uint8_t)(mask & mode);
|
||||
maskAndNotModeM[i] = (uint8_t)(mask & ~mode);
|
||||
doneq |= maskAndNotModeM[i];
|
||||
}
|
||||
doneqM = doneq ? 1 : 0;
|
||||
|
||||
// Create sockets
|
||||
socketM[0] = socketM[1] = -1;
|
||||
@ -89,23 +68,12 @@ void cSatipSectionFilter::New(void)
|
||||
int cSatipSectionFilter::Filter(void)
|
||||
{
|
||||
if (secBufM) {
|
||||
int i;
|
||||
uint8_t neq = 0;
|
||||
|
||||
for (i = 0; i < eDmxMaxFilterSize; ++i) {
|
||||
uint8_t calcxor = (uint8_t)(filterValueM[i] ^ secBufM[i]);
|
||||
if (maskAndModeM[i] & calcxor)
|
||||
return 0;
|
||||
neq |= (maskAndNotModeM[i] & calcxor);
|
||||
}
|
||||
|
||||
if (doneqM && !neq)
|
||||
return 0;
|
||||
|
||||
if (ringBufferM && (secLenM > 0)) {
|
||||
cFrame* section = new cFrame(secBufM, secLenM);
|
||||
if (!ringBufferM->Put(section))
|
||||
DELETE_POINTER(section);
|
||||
if ((tidM & maskM) == (secBufM[0] & maskM)) {
|
||||
if (ringBufferM && (secLenM > 0)) {
|
||||
cFrame* section = new cFrame(secBufM, secLenM);
|
||||
if (!ringBufferM->Put(section))
|
||||
DELETE_POINTER(section);
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
@ -33,18 +33,13 @@ private:
|
||||
uint16_t secLenM;
|
||||
uint16_t tsFeedpM;
|
||||
uint16_t pidM;
|
||||
uint8_t tidM;
|
||||
uint8_t maskM;
|
||||
|
||||
cRingBufferFrame *ringBufferM;
|
||||
int deviceIndexM;
|
||||
int socketM[2];
|
||||
|
||||
uint8_t filterValueM[eDmxMaxFilterSize];
|
||||
uint8_t filterMaskM[eDmxMaxFilterSize];
|
||||
uint8_t filterModeM[eDmxMaxFilterSize];
|
||||
|
||||
uint8_t maskAndModeM[eDmxMaxFilterSize];
|
||||
uint8_t maskAndNotModeM[eDmxMaxFilterSize];
|
||||
|
||||
inline uint16_t GetLength(const uint8_t *dataP);
|
||||
void New(void);
|
||||
int Filter(void);
|
||||
|
63
server.c
63
server.c
@ -40,29 +40,43 @@ bool cSatipFrontends::Matches(int deviceIdP, int transponderP)
|
||||
bool cSatipFrontends::Assign(int deviceIdP, int transponderP)
|
||||
{
|
||||
cSatipFrontend *tmp = NULL;
|
||||
// Prefer any unused one
|
||||
// Prefer any used one
|
||||
for (cSatipFrontend *f = First(); f; f = Next(f)) {
|
||||
if (!f->Attached() || (f->DeviceId() == deviceIdP)) {
|
||||
if (f->DeviceId() == deviceIdP) { // give deviceID priority, but take detached frontend if deviceID ist not yet attached
|
||||
tmp = f;
|
||||
break;
|
||||
}
|
||||
if (!f->Attached()) {
|
||||
tmp = f;
|
||||
}
|
||||
}
|
||||
if (tmp) {
|
||||
tmp->SetTransponder(transponderP);
|
||||
debug9("%s assigned TP %d to %s/#%d", __PRETTY_FUNCTION__, transponderP, *tmp->Description(), tmp->Index());
|
||||
return true;
|
||||
}
|
||||
error("no assignable frontend found [device %u]", deviceIdP);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool cSatipFrontends::Attach(int deviceIdP, int transponderP)
|
||||
{
|
||||
cSatipFrontend *tmp = NULL;
|
||||
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;
|
||||
tmp = f;
|
||||
if (f->DeviceId() == deviceIdP) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (tmp) {
|
||||
tmp->Attach(deviceIdP);
|
||||
debug9("%s attached deviceId %d (TP %d) to %s/#%d", __PRETTY_FUNCTION__, deviceIdP, transponderP, *tmp->Description(), tmp->Index());
|
||||
return true;
|
||||
}
|
||||
error("%s no Frontend found for attaching deviceID %d (TP %d)", __PRETTY_FUNCTION__, deviceIdP, transponderP);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -71,7 +85,7 @@ 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());
|
||||
debug9("%s detached deviceID %d (TP %d) from %s/#%d", __PRETTY_FUNCTION__, deviceIdP, transponderP, *f->Description(), f->Index());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -119,6 +133,7 @@ cSatipServer::cSatipServer(const char *srcAddressP, const char *addressP, const
|
||||
// Elgato EyeTV Netstream 4Sat ?
|
||||
if (strstr(*descriptionM, "GSSBOX") || // Grundig Sat Systems GSS.box DSI 400
|
||||
strstr(*descriptionM, "DIGIBIT") || // Telestar Digibit R1
|
||||
strstr(*descriptionM, "Multibox-") || // Inverto IDL-400s: Multibox-<MMAACC>:SAT>IP
|
||||
strstr(*descriptionM, "Triax SatIP Converter") // Triax TSS 400
|
||||
)
|
||||
quirkM |= eSatipQuirkSessionId;
|
||||
@ -128,34 +143,38 @@ cSatipServer::cSatipServer(const char *srcAddressP, const char *addressP, const
|
||||
)
|
||||
quirkM |= eSatipQuirkRtpOverTcp;
|
||||
// These devices contain a play (add/delpids) parameter bug:
|
||||
if (strstr(*descriptionM, "FRITZ!Box 6490 Cable") || // FRITZ!Box 6490 Cable
|
||||
strstr(*descriptionM, "FRITZ!WLAN Repeater DVB-C") || // FRITZ!WLAN Repeater DVB-C
|
||||
if (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, "FRITZ!Box 6490 Cable") || // FRITZ!Box 6490 Cable
|
||||
strstr(*descriptionM, "FRITZ!WLAN Repeater DVB-C") || // FRITZ!WLAN Repeater DVB-C
|
||||
if (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
|
||||
// These devices support the X_PMT protocol extension:
|
||||
if (strstr(*descriptionM, "OctopusNet") || // Digital Devices OctopusNet
|
||||
strstr(*descriptionM, "minisatip") // minisatip server
|
||||
)
|
||||
quirkM |= eSatipQuirkCiXpmt;
|
||||
// These devices support the TNR protocol extension
|
||||
// These devices support the TNR protocol extension:
|
||||
if (strstr(*descriptionM, "DVBViewer") // DVBViewer Media Server
|
||||
)
|
||||
quirkM |= eSatipQuirkCiTnr;
|
||||
// These devices don't support auto-detection of pilot tones
|
||||
// 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, "Multibox-") || // Inverto IDL-400s: Multibox-<MMAACC>:SAT>IP
|
||||
strstr(*descriptionM, "Triax SatIP Converter") || // Triax TSS 400
|
||||
strstr(*descriptionM, "KATHREIN SatIP Server") // Kathrein ExIP 414/E
|
||||
)
|
||||
quirkM |= eSatipQuirkForcePilot;
|
||||
// These devices require TEARDOWN before new PLAY command:
|
||||
if (strstr(*descriptionM, "FRITZ!WLAN Repeater DVB-C") || // FRITZ!WLAN Repeater DVB-C
|
||||
strstr(*descriptionM, "fritzdvbc") // FRITZ!WLAN Repeater DVB-C (old firmware)
|
||||
)
|
||||
quirkM |= eSatipQuirkTearAndPlay;
|
||||
}
|
||||
if ((quirkM & eSatipQuirkMask) & eSatipQuirkSessionId)
|
||||
quirksM = cString::sprintf("%s%sSessionId", *quirksM, isempty(*quirksM) ? "" : ",");
|
||||
@ -208,6 +227,11 @@ cSatipServer::cSatipServer(const char *srcAddressP, const char *addressP, const
|
||||
for (int i = 1; i <= count; ++i)
|
||||
frontendsM[eSatipFrontendDVBC2].Add(new cSatipFrontend(i, "DVB-C2"));
|
||||
}
|
||||
else if (c = strstr(r, "ATSC-")) {
|
||||
int count = atoi(c + 5);
|
||||
for (int i = 1; i <= count; ++i)
|
||||
frontendsM[eSatipFrontendATSC].Add(new cSatipFrontend(i, "ATSC"));
|
||||
}
|
||||
r = strtok_r(NULL, ",", &s);
|
||||
}
|
||||
FREE_POINTER(p);
|
||||
@ -260,6 +284,8 @@ bool cSatipServer::Assign(int deviceIdP, int sourceP, int systemP, int transpond
|
||||
else
|
||||
result = frontendsM[eSatipFrontendDVBC].Assign(deviceIdP, transponderP) || frontendsM[eSatipFrontendDVBC2].Assign(deviceIdP, transponderP);
|
||||
}
|
||||
else if (cSource::IsType(sourceP, 'A'))
|
||||
result = frontendsM[eSatipFrontendATSC].Assign(deviceIdP, transponderP);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@ -273,6 +299,8 @@ bool cSatipServer::Matches(int sourceP)
|
||||
return GetModulesDVBT() || GetModulesDVBT2();
|
||||
else if (cSource::IsType(sourceP, 'C'))
|
||||
return GetModulesDVBC() || GetModulesDVBC2();
|
||||
else if (cSource::IsType(sourceP, 'A'))
|
||||
return GetModulesATSC();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@ -295,6 +323,8 @@ bool cSatipServer::Matches(int deviceIdP, int sourceP, int systemP, int transpon
|
||||
else
|
||||
result = frontendsM[eSatipFrontendDVBC].Matches(deviceIdP, transponderP) || frontendsM[eSatipFrontendDVBC2].Matches(deviceIdP, transponderP);
|
||||
}
|
||||
else if (cSource::IsType(sourceP, 'A'))
|
||||
result = frontendsM[eSatipFrontendATSC].Matches(deviceIdP, transponderP);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@ -340,6 +370,11 @@ int cSatipServer::GetModulesDVBC2(void)
|
||||
return frontendsM[eSatipFrontendDVBC2].Count();
|
||||
}
|
||||
|
||||
int cSatipServer::GetModulesATSC(void)
|
||||
{
|
||||
return frontendsM[eSatipFrontendATSC].Count();
|
||||
}
|
||||
|
||||
// --- cSatipServers ----------------------------------------------------------
|
||||
|
||||
cSatipServer *cSatipServers::Find(cSatipServer *serverP)
|
||||
@ -521,6 +556,8 @@ int cSatipServers::NumProvidedSystems(void)
|
||||
count += s->GetModulesDVBC() * 3;
|
||||
// DVB-C2: qam16, qam32, qam64, qam128, qam256
|
||||
count += s->GetModulesDVBC2() * 5;
|
||||
// ATSC: 8vbs, 16vbs, qam256
|
||||
count += s->GetModulesATSC() * 3;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
21
server.h
21
server.h
@ -52,6 +52,7 @@ private:
|
||||
eSatipFrontendDVBT2,
|
||||
eSatipFrontendDVBC,
|
||||
eSatipFrontendDVBC2,
|
||||
eSatipFrontendATSC,
|
||||
eSatipFrontendCount
|
||||
};
|
||||
enum {
|
||||
@ -75,15 +76,16 @@ private:
|
||||
|
||||
public:
|
||||
enum eSatipQuirk {
|
||||
eSatipQuirkNone = 0x00,
|
||||
eSatipQuirkSessionId = 0x01,
|
||||
eSatipQuirkPlayPids = 0x02,
|
||||
eSatipQuirkForceLock = 0x04,
|
||||
eSatipQuirkRtpOverTcp = 0x08,
|
||||
eSatipQuirkCiXpmt = 0x10,
|
||||
eSatipQuirkCiTnr = 0x20,
|
||||
eSatipQuirkForcePilot = 0x40,
|
||||
eSatipQuirkMask = 0xFF
|
||||
eSatipQuirkNone = 0x00,
|
||||
eSatipQuirkSessionId = 0x01,
|
||||
eSatipQuirkPlayPids = 0x02,
|
||||
eSatipQuirkForceLock = 0x04,
|
||||
eSatipQuirkRtpOverTcp = 0x08,
|
||||
eSatipQuirkCiXpmt = 0x10,
|
||||
eSatipQuirkCiTnr = 0x20,
|
||||
eSatipQuirkForcePilot = 0x40,
|
||||
eSatipQuirkTearAndPlay = 0x80,
|
||||
eSatipQuirkMask = 0xFF
|
||||
};
|
||||
cSatipServer(const char *srcAddressP, const char *addressP, const int portP, const char *modelP, const char *filtersP, const char *descriptionP, const int quirkP);
|
||||
virtual ~cSatipServer();
|
||||
@ -98,6 +100,7 @@ public:
|
||||
int GetModulesDVBT2(void);
|
||||
int GetModulesDVBC(void);
|
||||
int GetModulesDVBC2(void);
|
||||
int GetModulesATSC(void);
|
||||
void Activate(bool onOffP) { activeM = onOffP; }
|
||||
const char *SrcAddress(void) { return *srcAddressM; }
|
||||
const char *Address(void) { return *addressM; }
|
||||
|
9
setup.c
9
setup.c
@ -347,6 +347,7 @@ cSatipPluginSetup::cSatipPluginSetup()
|
||||
operatingModeM(SatipConfig.GetOperatingMode()),
|
||||
transportModeM(SatipConfig.GetTransportMode()),
|
||||
ciExtensionM(SatipConfig.GetCIExtension()),
|
||||
frontendReuseM(SatipConfig.GetFrontendReuse()),
|
||||
eitScanM(SatipConfig.GetEITScan()),
|
||||
numDisabledSourcesM(SatipConfig.GetDisabledSourcesCount()),
|
||||
numDisabledFiltersM(SatipConfig.GetDisabledFiltersCount())
|
||||
@ -418,6 +419,10 @@ void cSatipPluginSetup::Setup(void)
|
||||
}
|
||||
Add(new cMenuEditStraItem(tr("Transport mode"), &transportModeM, ELEMENTS(transportModeTextsM), transportModeTextsM));
|
||||
helpM.Append(tr("Define which transport mode shall be used.\n\nUnicast, Multicast, RTP-over-TCP"));
|
||||
|
||||
Add(new cMenuEditBoolItem(tr("Enable frontend reuse"), &frontendReuseM));
|
||||
helpM.Append(tr("Define whether reusing a frontend for multiple channels in a transponder should be enabled."));
|
||||
|
||||
Add(new cOsdItem(tr("Active SAT>IP servers:"), osUnknown, false));
|
||||
helpM.Append("");
|
||||
|
||||
@ -479,6 +484,7 @@ eOSState cSatipPluginSetup::ProcessKey(eKeys keyP)
|
||||
bool hadSubMenu = HasSubMenu();
|
||||
int oldOperatingMode = operatingModeM;
|
||||
int oldCiExtension = ciExtensionM;
|
||||
int oldFrontendReuse = frontendReuseM;
|
||||
int oldNumDisabledSources = numDisabledSourcesM;
|
||||
int oldNumDisabledFilters = numDisabledFiltersM;
|
||||
eOSState state = cMenuSetupPage::ProcessKey(keyP);
|
||||
@ -504,7 +510,7 @@ eOSState cSatipPluginSetup::ProcessKey(eKeys keyP)
|
||||
if ((keyP == kNone) && (cSatipDiscover::GetInstance()->GetServers()->Count() != deviceCountM))
|
||||
Setup();
|
||||
|
||||
if ((keyP != kNone) && ((numDisabledSourcesM != oldNumDisabledSources) || (numDisabledFiltersM != oldNumDisabledFilters) || (operatingModeM != oldOperatingMode) || (ciExtensionM != oldCiExtension) || (detachedModeM != SatipConfig.GetDetachedMode()))) {
|
||||
if ((keyP != kNone) && ((numDisabledSourcesM != oldNumDisabledSources) || (numDisabledFiltersM != oldNumDisabledFilters) || (operatingModeM != oldOperatingMode) || (ciExtensionM != oldCiExtension) || ( oldFrontendReuse != frontendReuseM) || (detachedModeM != SatipConfig.GetDetachedMode()))) {
|
||||
while ((numDisabledSourcesM < oldNumDisabledSources) && (oldNumDisabledSources > 0))
|
||||
disabledSourcesM[--oldNumDisabledSources] = cSource::stNone;
|
||||
while ((numDisabledFiltersM < oldNumDisabledFilters) && (oldNumDisabledFilters > 0))
|
||||
@ -569,6 +575,7 @@ void cSatipPluginSetup::Store(void)
|
||||
SetupStore("OperatingMode", operatingModeM);
|
||||
SetupStore("TransportMode", transportModeM);
|
||||
SetupStore("EnableCIExtension", ciExtensionM);
|
||||
SetupStore("EnableFrontendReuse", frontendReuseM);
|
||||
SetupStore("EnableEITScan", eitScanM);
|
||||
StoreCicams("CICAM", cicamsM);
|
||||
StoreSources("DisabledSources", disabledSourcesM);
|
||||
|
1
setup.h
1
setup.h
@ -22,6 +22,7 @@ private:
|
||||
const char *operatingModeTextsM[cSatipConfig::eOperatingModeCount];
|
||||
const char *transportModeTextsM[cSatipConfig::eTransportModeCount];
|
||||
int ciExtensionM;
|
||||
int frontendReuseM;
|
||||
int cicamsM[MAX_CICAM_COUNT];
|
||||
const char *cicamTextsM[CA_SYSTEMS_TABLE_SIZE];
|
||||
int eitScanM;
|
||||
|
86
tuner.c
86
tuner.c
@ -25,6 +25,8 @@ cSatipTuner::cSatipTuner(cSatipDeviceIf &deviceP, unsigned int packetLenP)
|
||||
rtcpM(*this),
|
||||
streamAddrM(""),
|
||||
streamParamM(""),
|
||||
lastAddrM(""),
|
||||
lastParamM(""),
|
||||
tnrParamM(""),
|
||||
streamPortM(SATIP_DEFAULT_RTSP_PORT),
|
||||
currentServerM(NULL, deviceP.GetId(), 0),
|
||||
@ -34,11 +36,12 @@ cSatipTuner::cSatipTuner(cSatipDeviceIf &deviceP, unsigned int packetLenP)
|
||||
keepAliveM(),
|
||||
statusUpdateM(),
|
||||
pidUpdateCacheM(),
|
||||
setupTimeoutM(-1),
|
||||
sessionM(""),
|
||||
currentStateM(tsIdle),
|
||||
internalStateM(),
|
||||
externalStateM(),
|
||||
timeoutM(eMinKeepAliveIntervalMs),
|
||||
timeoutM(eMinKeepAliveIntervalMs - eKeepAlivePreBufferMs),
|
||||
hasLockM(false),
|
||||
signalStrengthDBmM(0.0),
|
||||
signalStrengthM(-1),
|
||||
@ -117,6 +120,8 @@ void cSatipTuner::Action(void)
|
||||
break;
|
||||
case tsSet:
|
||||
debug4("%s: tsSet [device %d]", __PRETTY_FUNCTION__, deviceIdM);
|
||||
if (currentServerM.IsQuirk(cSatipServer::eSatipQuirkTearAndPlay))
|
||||
Disconnect();
|
||||
if (Connect()) {
|
||||
tuning.Set(eTuningTimeoutMs);
|
||||
RequestState(tsTuned, smInternal);
|
||||
@ -175,6 +180,7 @@ void cSatipTuner::Action(void)
|
||||
idleCheck.Set(eIdleCheckTimeoutMs);
|
||||
break;
|
||||
}
|
||||
Receive();
|
||||
break;
|
||||
default:
|
||||
error("Unknown tuner status %d [device %d]", currentStateM, deviceIdM);
|
||||
@ -191,8 +197,6 @@ bool cSatipTuner::Open(void)
|
||||
cMutexLock MutexLock(&mutexM);
|
||||
debug1("%s [device %d]", __PRETTY_FUNCTION__, deviceIdM);
|
||||
|
||||
RequestState(tsSet, smExternal);
|
||||
|
||||
// return always true
|
||||
return true;
|
||||
}
|
||||
@ -202,7 +206,8 @@ bool cSatipTuner::Close(void)
|
||||
cMutexLock MutexLock(&mutexM);
|
||||
debug1("%s [device %d]", __PRETTY_FUNCTION__, deviceIdM);
|
||||
|
||||
RequestState(tsRelease, smExternal);
|
||||
if (setupTimeoutM.TimedOut())
|
||||
RequestState(tsRelease, smExternal);
|
||||
|
||||
// return always true
|
||||
return true;
|
||||
@ -218,10 +223,15 @@ bool cSatipTuner::Connect(void)
|
||||
tnrParamM = "";
|
||||
// Just retune
|
||||
if (streamIdM >= 0) {
|
||||
if (!strcmp(*streamParamM, *lastParamM) && hasLockM) {
|
||||
debug1("%s Identical parameters [device %d]", __PRETTY_FUNCTION__, deviceIdM);
|
||||
//return true; // fall through because detection does not work reliably
|
||||
}
|
||||
cString uri = cString::sprintf("%sstream=%d?%s", *connectionUri, streamIdM, *streamParamM);
|
||||
debug1("%s Retuning [device %d]", __PRETTY_FUNCTION__, deviceIdM);
|
||||
if (rtspM.Play(*uri)) {
|
||||
keepAliveM.Set(timeoutM);
|
||||
lastParamM = streamParamM;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -234,11 +244,13 @@ bool cSatipTuner::Connect(void)
|
||||
if (useTcp)
|
||||
debug1("%s Requesting TCP [device %d]", __PRETTY_FUNCTION__, deviceIdM);
|
||||
if (rtspM.Setup(*uri, rtpM.Port(), rtcpM.Port(), useTcp)) {
|
||||
lastParamM = streamParamM;
|
||||
keepAliveM.Set(timeoutM);
|
||||
if (nextServerM.IsValid()) {
|
||||
currentServerM = nextServerM;
|
||||
nextServerM.Reset();
|
||||
}
|
||||
lastAddrM = connectionUri;
|
||||
currentServerM.Attach();
|
||||
return true;
|
||||
}
|
||||
@ -256,8 +268,8 @@ bool cSatipTuner::Disconnect(void)
|
||||
cMutexLock MutexLock(&mutexM);
|
||||
debug1("%s [device %d]", __PRETTY_FUNCTION__, deviceIdM);
|
||||
|
||||
if (!isempty(*streamAddrM) && (streamIdM >= 0)) {
|
||||
cString uri = cString::sprintf("%sstream=%d", *GetBaseUrl(*streamAddrM, streamPortM), streamIdM);
|
||||
if (!isempty(*lastAddrM) && (streamIdM >= 0)) {
|
||||
cString uri = cString::sprintf("%sstream=%d", *lastAddrM, streamIdM);
|
||||
rtspM.Teardown(*uri);
|
||||
// some devices requires a teardown for TCP connection also
|
||||
rtspM.Reset();
|
||||
@ -273,7 +285,7 @@ bool cSatipTuner::Disconnect(void)
|
||||
|
||||
currentServerM.Detach();
|
||||
statusUpdateM.Set(0);
|
||||
timeoutM = eMinKeepAliveIntervalMs;
|
||||
timeoutM = eMinKeepAliveIntervalMs - eKeepAlivePreBufferMs;
|
||||
pmtPidM = -1;
|
||||
addPidsM.Clear();
|
||||
delPidsM.Clear();
|
||||
@ -382,6 +394,7 @@ void cSatipTuner::SetSessionTimeout(const char *sessionP, int timeoutP)
|
||||
if (nextServerM.IsQuirk(cSatipServer::eSatipQuirkSessionId) && !isempty(*sessionM) && startswith(*sessionM, "0"))
|
||||
rtspM.SetSession(SkipZeroes(*sessionM));
|
||||
timeoutM = (timeoutP > eMinKeepAliveIntervalMs) ? timeoutP : eMinKeepAliveIntervalMs;
|
||||
timeoutM -= eKeepAlivePreBufferMs;
|
||||
}
|
||||
|
||||
void cSatipTuner::SetupTransport(int rtpPortP, int rtcpPortP, const char *streamAddrP, const char *sourceAddrP)
|
||||
@ -446,7 +459,13 @@ bool cSatipTuner::SetSource(cSatipServer *serverP, const int transponderP, const
|
||||
if (nextServerM.IsQuirk(cSatipServer::eSatipQuirkForcePilot) && strstr(parameterP, "msys=dvbs2") && !strstr(parameterP, "plts="))
|
||||
streamParamM = rtspM.RtspUnescapeString(*cString::sprintf("%s&plts=on", parameterP));
|
||||
// Reconnect
|
||||
if (!isempty(*lastAddrM)) {
|
||||
cString connectionUri = GetBaseUrl(*streamAddrM, streamPortM);
|
||||
if (strcmp(*connectionUri, *lastAddrM))
|
||||
RequestState(tsRelease, smInternal);
|
||||
}
|
||||
RequestState(tsSet, smExternal);
|
||||
setupTimeoutM.Set(eSetupTimeoutMs);
|
||||
}
|
||||
}
|
||||
else {
|
||||
@ -486,17 +505,24 @@ bool cSatipTuner::UpdatePids(bool forceP)
|
||||
cString uri = cString::sprintf("%sstream=%d", *GetBaseUrl(*streamAddrM, streamPortM), streamIdM);
|
||||
bool useci = (SatipConfig.GetCIExtension() && currentServerM.HasCI());
|
||||
bool usedummy = currentServerM.IsQuirk(cSatipServer::eSatipQuirkPlayPids);
|
||||
bool paramadded = false;
|
||||
if (forceP || usedummy) {
|
||||
if (pidsM.Size())
|
||||
uri = cString::sprintf("%s?pids=%s", *uri, *pidsM.ListPids());
|
||||
if (usedummy && (pidsM.Size() == 1) && (pidsM[0] < 0x20))
|
||||
uri = cString::sprintf("%s,%d", *uri, eDummyPid);
|
||||
if (pidsM.Size()) {
|
||||
uri = cString::sprintf("%s%spids=%s", *uri, paramadded ? "&" : "?", *pidsM.ListPids());
|
||||
if (usedummy && (pidsM.Size() == 1) && (pidsM[0] < 0x20))
|
||||
uri = cString::sprintf("%s,%d", *uri, eDummyPid);
|
||||
paramadded = true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (addPidsM.Size())
|
||||
uri = cString::sprintf("%s?addpids=%s", *uri, *addPidsM.ListPids());
|
||||
if (delPidsM.Size())
|
||||
uri = cString::sprintf("%s%sdelpids=%s", *uri, addPidsM.Size() ? "&" : "?", *delPidsM.ListPids());
|
||||
if (addPidsM.Size()) {
|
||||
uri = cString::sprintf("%s%saddpids=%s", *uri, paramadded ? "&" : "?", *addPidsM.ListPids());
|
||||
paramadded = true;
|
||||
}
|
||||
if (delPidsM.Size()) {
|
||||
uri = cString::sprintf("%s%sdelpids=%s", *uri, paramadded ? "&" : "?", *delPidsM.ListPids());
|
||||
paramadded = true;
|
||||
}
|
||||
}
|
||||
if (useci) {
|
||||
if (currentServerM.IsQuirk(cSatipServer::eSatipQuirkCiXpmt)) {
|
||||
@ -509,9 +535,10 @@ bool cSatipTuner::UpdatePids(bool forceP)
|
||||
int pid = deviceM->GetPmtPid();
|
||||
if ((pid > 0) && (pid != pmtPidM)) {
|
||||
int slot = deviceM->GetCISlot();
|
||||
uri = cString::sprintf("%s&x_pmt=%d", *uri, pid);
|
||||
uri = cString::sprintf("%s%sx_pmt=%d", *uri, paramadded ? "&" : "?", pid);
|
||||
if (slot > 0)
|
||||
uri = cString::sprintf("%s&x_ci=%d", *uri, slot);
|
||||
paramadded = true;
|
||||
}
|
||||
pmtPidM = pid;
|
||||
}
|
||||
@ -519,14 +546,18 @@ bool cSatipTuner::UpdatePids(bool forceP)
|
||||
// CI extension parameters:
|
||||
// - tnr : specifies a channel config entry
|
||||
cString param = deviceM->GetTnrParameterString();
|
||||
if (!isempty(*param) && strcmp(*tnrParamM, *param) != 0)
|
||||
uri = cString::sprintf("%s&tnr=%s", *uri, *param);
|
||||
if (!isempty(*param) && strcmp(*tnrParamM, *param) != 0) {
|
||||
uri = cString::sprintf("%s%stnr=%s", *uri, paramadded ? "&" : "?", *param);
|
||||
paramadded = true;
|
||||
}
|
||||
tnrParamM = param;
|
||||
}
|
||||
}
|
||||
pidUpdateCacheM.Set(ePidUpdateIntervalMs);
|
||||
if (!rtspM.Play(*uri))
|
||||
return false;
|
||||
if (paramadded) {
|
||||
pidUpdateCacheM.Set(ePidUpdateIntervalMs);
|
||||
if (!rtspM.Play(*uri))
|
||||
return false;
|
||||
}
|
||||
addPidsM.Clear();
|
||||
delPidsM.Clear();
|
||||
}
|
||||
@ -534,6 +565,19 @@ bool cSatipTuner::UpdatePids(bool forceP)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool cSatipTuner::Receive(void)
|
||||
{
|
||||
debug16("%s tunerState=%s [device %d]", __PRETTY_FUNCTION__, TunerStateString(currentStateM), deviceIdM);
|
||||
cMutexLock MutexLock(&mutexM);
|
||||
if (!isempty(*streamAddrM)) {
|
||||
cString uri = GetBaseUrl(*streamAddrM, streamPortM);
|
||||
if (!rtspM.Receive(*uri))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool cSatipTuner::KeepAlive(bool forceP)
|
||||
{
|
||||
debug16("%s (%d) tunerState=%s [device %d]", __PRETTY_FUNCTION__, forceP, TunerStateString(currentStateM), deviceIdM);
|
||||
|
8
tuner.h
8
tuner.h
@ -88,7 +88,9 @@ private:
|
||||
eConnectTimeoutMs = 5000, // in milliseconds
|
||||
eIdleCheckTimeoutMs = 15000, // in milliseconds
|
||||
eTuningTimeoutMs = 20000, // in milliseconds
|
||||
eMinKeepAliveIntervalMs = 30000 // in milliseconds
|
||||
eMinKeepAliveIntervalMs = 30000, // in milliseconds
|
||||
eKeepAlivePreBufferMs = 2000, // in milliseconds
|
||||
eSetupTimeoutMs = 2000 // in milliseconds
|
||||
};
|
||||
enum eTunerState { tsIdle, tsRelease, tsSet, tsTuned, tsLocked };
|
||||
enum eStateMode { smInternal, smExternal };
|
||||
@ -101,6 +103,8 @@ private:
|
||||
cSatipRtcp rtcpM;
|
||||
cString streamAddrM;
|
||||
cString streamParamM;
|
||||
cString lastAddrM;
|
||||
cString lastParamM;
|
||||
cString tnrParamM;
|
||||
int streamPortM;
|
||||
cSatipTunerServer currentServerM;
|
||||
@ -110,6 +114,7 @@ private:
|
||||
cTimeMs keepAliveM;
|
||||
cTimeMs statusUpdateM;
|
||||
cTimeMs pidUpdateCacheM;
|
||||
cTimeMs setupTimeoutM;
|
||||
cString sessionM;
|
||||
eTunerState currentStateM;
|
||||
cVector<eTunerState> internalStateM;
|
||||
@ -128,6 +133,7 @@ private:
|
||||
|
||||
bool Connect(void);
|
||||
bool Disconnect(void);
|
||||
bool Receive(void);
|
||||
bool KeepAlive(bool forceP = false);
|
||||
bool ReadReceptionStatus(bool forceP = false);
|
||||
bool UpdatePids(bool forceP = false);
|
||||
|
Loading…
x
Reference in New Issue
Block a user