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

24 Commits

Author SHA1 Message Date
Rolf Ahrenberg
fb40846171 Bumped up the version number. 2014-04-12 23:07:27 +03:00
Rolf Ahrenberg
b19be5b5c5 Reformatted the channel frequency value. 2014-04-12 23:02:26 +03:00
Rolf Ahrenberg
1a304e9dc2 Improved debug messages. 2014-04-12 16:57:28 +03:00
Rolf Ahrenberg
5ff54d27a3 Removed unnecessary PLAY commands and header callbacks. 2014-04-12 16:45:29 +03:00
Rolf Ahrenberg
276370afbb Added Spanish translation (Thanks to Gabriel Bonich). 2014-04-11 13:22:34 +03:00
Rolf Ahrenberg
f2081c4f00 Fixed the OPTIONS URL and enchanced the user agent string. 2014-04-06 23:42:49 +03:00
Rolf Ahrenberg
388543a58d Added a recommendation for using libcurl version >= 7.36.0. 2014-04-06 00:55:16 +03:00
Rolf Ahrenberg
f46d07a95f Added Catalan translation (Thanks to Gabriel Bonich). 2014-04-05 13:50:55 +03:00
Rolf Ahrenberg
43cc15357e Optimized re-sending. 2014-04-05 13:46:07 +03:00
Rolf Ahrenberg
5b1af5ba29 Refactored the section filtering. 2014-04-04 00:56:00 +03:00
Rolf Ahrenberg
80fc28d8cf Fixed eMinKeepAliveIntervalMs typo. 2014-04-02 21:06:37 +03:00
Rolf Ahrenberg
5e8b7b7c5e Fixed keepalive heartbeat again. 2014-04-01 09:05:13 +03:00
Rolf Ahrenberg
88b2ad9244 Added missing RTP packet error message. 2014-03-30 22:58:43 +03:00
Rolf Ahrenberg
7b58d9f28f Added a check to write new sections only if there is no data in the read socket. 2014-03-30 22:20:56 +03:00
Rolf Ahrenberg
f493df0e3d Changed implementation to report about RTP packet errors on 5 minutes interval only. 2014-03-30 18:20:20 +03:00
Rolf Ahrenberg
9a6ae40954 Optimized the startup delay. 2014-03-28 19:53:22 +02:00
Rolf Ahrenberg
b5ec84fd91 Fixed keepalive heartbeat. 2014-03-28 19:52:17 +02:00
Rolf Ahrenberg
e7a74f3ad4 Fixed reconnection. 2014-03-25 23:50:30 +02:00
Rolf Ahrenberg
40d280af10 Fixed pid leaking while disabling section filters, EIT filter defition and RTP sequence overflow detection. 2014-03-25 23:25:36 +02:00
Rolf Ahrenberg
9f2d99435d Added support for cDevice::Ready() and preliminary RTP packet sequence check. 2014-03-23 17:59:08 +02:00
Rolf Ahrenberg
06dd2f7261 Fixed dates. 2014-03-16 22:30:48 +02:00
Rolf Ahrenberg
dfbb3515ef Changed code to utilize a proper XML library, refactored the session code, fxed EIT scan functionality, and updated for vdr-2.1.6. 2014-03-16 19:58:09 +02:00
Rolf Ahrenberg
497b1893db Refactored code and added support for 'C' sources. 2014-03-15 12:49:13 +02:00
Rolf Ahrenberg
8c05ce31f9 Switched to standard 'S' and 'T' sources.
Added a new OperationMode setup parameter.
Added new SVDRP commands.
2014-03-12 00:19:37 +02:00
31 changed files with 1404 additions and 1042 deletions

40
HISTORY
View File

@@ -6,3 +6,43 @@ VDR Plugin 'satip' Revision History
- Initial revision.
- Added German translation (Thanks to Frank Neumann).
2014-03-15: Version 0.1.0
- Switched to the standard S/T/C source identifiers.
- Added a new operation mode setup parameter.
- Added new SVDRP commands.
2014-03-16: Version 0.1.1
- Changed code to utilize a proper XML library.
- Refactored the session code.
- Fixed EIT scan functionality.
- Updated for vdr-2.1.6.
2014-03-28: Version 0.2.0
- Added support for cDevice::Ready().
- Fixed pid leaking while disabling section filters.
- Fixed keepalive heartbeat.
2014-04-01: Version 0.2.1
- Changed implementation to report about RTP packet
errors on 5 minutes interval only.
- Added a check to write new sections only if there
is no data in the read socket.
- Fixed keepalive heartbeat again.
2014-04-05: Version 0.2.2
- Fixed the default keepalive interval.
- Refactored the section filtering.
- Added Catalan translation (Thanks to Gabriel Bonich).
2014-04-12: Version 0.2.3
- Added Spanish translation (Thanks to Gabriel Bonich).
- Fixed parameters of the OPTIONS command.
- Added a device identication into the user agent string.
- Removed unnecessary PLAY commands and header callbacks.

View File

@@ -6,6 +6,10 @@
#SATIP_DEBUG = 1
# Use TinyXML instead of PugiXML
#SATIP_USE_TINYXML = 1
# Strip debug symbols? Set eg. to /bin/true if not
STRIP = strip
@@ -64,6 +68,13 @@ INCLUDES +=
DEFINES += -DPLUGIN_NAME_I18N='"$(PLUGIN)"'
ifdef SATIP_USE_TINYXML
DEFINES += -DUSE_TINYXML
LIBS += -ltinyxml
else
LIBS += -lpugixml
endif
ifdef SATIP_DEBUG
DEFINES += -DDEBUG
endif
@@ -77,8 +88,8 @@ all-redirect: all
### The object files (add further files here):
OBJS = $(PLUGIN).o common.o config.o device.o discover.o \
sectionfilter.o setup.o socket.o source.o statistics.o tuner.o
OBJS = $(PLUGIN).o common.o config.o device.o discover.o param.o \
sectionfilter.o server.o setup.o socket.o statistics.o tuner.o
### The main target:

151
README
View File

@@ -14,10 +14,16 @@ See the file COPYING for more information.
Requirements:
- Libcurl - the multiprotocol file transfer library with RTSP support
- Libcurl >= 7.36.0 - the multiprotocol file transfer library with RTSP support
http://curl.haxx.se/libcurl/
- VDR-2.1.4+ for scrambled channels
- PugiXML - Light-weight, simple and fast XML parser for C++
http://pugixml.org/
or
TinyXML - a simple, small, C++ XML parser
http://www.grinninglizard.com/tinyxml/
- VDR >= 2.1.4 for scrambled channels
Description:
@@ -32,9 +38,37 @@ Installation:
tar -xzf /put/your/path/here/vdr-satip-X.Y.Z.tgz
make -C satip-X.Y.Z install
Configuration:
The plugin accepts a "--devices" (-d) command-line parameter defaulting
to one. This parameter defines how many simultaneous transponders can
be received, if there are available SAT>IP tuners.
SAT>IP satellite positions (aka. signal sources) shall be defined via
sources.conf. If the source description begins with a number, it's used
as SAT>IP signal source selection parameter. Otherwise, the default
parameter is one:
S19.2E Astra 1KR/1L/1M/2C
=> Signal source = 1
S19.2E 2
=> Signal source = 2
S19.2E 3 Astra 1KR/1L/1M/2C
=> Signal source = 3
Setup menu:
- Enable EPG scanning = yes If you want exclude all SAT>IP devices
- 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.
- Enable EPG scanning = yes If you want exclude all SAT>IP devices
from VDR's EIT background scanning, set
this option to "no".
- Disabled filters = none Certain section filters might cause some
@@ -46,6 +80,7 @@ Setup menu:
"Disable filter" options which allow you
to disable the individual section filters.
Valid range: "none" = 0 ... 7
- [Red:Scan] Forces network scanning of SAT>IP hardware.
- [Blue:Info] Opens SAT>IP information/statistics menu.
- [Ok] Opens information menu of selected SAT>IP
device.
@@ -57,118 +92,22 @@ Information menu:
- [Yellow:Filters] Opens the section filter statistics page.
- [Blue:Bits/bytes] Toggles between bits and bytes mode.
SAT>IP device menu:
- [Red:Scan] Starts the channel scanning sometime in
the future.
Configuration:
- Parameters
Various parameters, depending on whether this is a DVB-S, DVB-S2, DVB-T,
or DVB-T2 channel. Each parameter consist of a key character, followed by
an integer number that represents the actual setting of that parameter.
The valid key characters, their meaning, and allowed values are:
B Bandwidth (1712, 5, 6, 7, 8, 10)
C Code rate high priority (12, 23, 34, 35, 45, 56, 67, 78, 89, 910)
G Guard interval (4, 8, 16, 32, 128, 19128, 19256)
H Horizontal polarization
L Left circular polarization
M Modulation (2, 5, 16, 64, 256)
N pilot toNes (0, 1)
O rollOff (20, 25, 35)
P stream id (0-255)
Q t2 system id (0-65535)
R Right circular polarization
S delivery System (0, 1)
T Transmission mode (1, 2, 4, 8, 16, 32)
V Vertical polarization
X siso/miso mode (0, 1)
Z signal source position (1-255)
Bandwidth: The bandwidth of the channel in MHz (1712 in kHz)
(DVB-T/DVB-T2)
Code rate high priority: Forward Error Correction (FEC) of the high
priority stream (DVB-T/DVB-T2) or the the inner FEC scheme (DVB-S/DVB-S2)
12 = 1/2, 23 = 2/3, 34 = 3/4, 35 = 3/5, 45 = 4/5, 56 = 5/6,
67 = 6/7, 78 = 7/8, 89 = 8/9, 910 = 9/10
(DVB-T/DVB-T2/DVB-S/DVB-S2)
Guard interval: The guard interval value
4 = 1/4, 8 = 1/8, 16 = 1/16, 32 = 1/32, 128 = 1/128,
19128 = 19/128, 19256 = 19/256
(DVB-T/DVB-T2)
Modulation: Specifies the modulation/constellation of the channel
2 = QPSK (DVB-S, DVB-S2, DVB-T, DVB-T2)
5 = 8PSK (DVB-S, DVB-S2)
16 = QAM16 (DVB-T, DVB-T2)
64 = QAM64 (DVB-T, DVB-T2)
256 = QAM256 (DVB-T2)
Pilot tones: Specifies pilot tones usage
0 = off, 1 = on
(DVB-S2)
Rolloff: The Nyquist filter rolloff factor
35 = 0.35, 25 = 0.25, 20 = 0.20
(DVB-S/DVB-S2)
Stream id: Physical Layer Pipe (PLP) id (0-255) for DVB-T2 multiplex
(DVB-T2)
T2 system id: Unique identifier (0-65535) of the T2 system
(DVB-T2)
Transmission mode: Number of DVB-T OFDM carriers
32 = 32k, 16 = 16k, 8 = 8k, 4 = 4k, 2 = 2k, 1 = 1k
(DVB-T/DVB-T2)
Delivery System: The delivery system
0 = "first generation" (DVB-S/DVB-T)
1 = "second generation" (DVB-S2/DVB-T2)
Polarization: Satellite antenna polarization
H = horizontal, V = vertical
R = circular right, L = circular left
(DVB-S/DVB-S2)
Signal source: Specifies the signal source (satellite) position
(DVB-S/DVB-S2)
SISO/MISO: Specifies the Single-Input/Multiple-Input Single-Output mode
0 = SISO, 1 = MISO
(DVB-T2)
- Source
There are two separate signal sources for SAT>IP channels:
Z = SAT>IP Satellite (DVB-S/DVB-S2)
Y = SAT>IP Terrestrial (DVB-T/DVB-T2)
- Examples
MTV3;DVB-T:658000000:B8C23D23G8M64S0T8Y0:T:0:305=2:561=fin@4,562=dut@4:5010;1073=fin,1074=dut:0:49:8438:8193:0
=>
MTV3;SAT>IP:658000000:B8C23G8M64S0T8:Y:0:305=2:561=fin@4,562=dut@4:5010;1073=fin,1074=dut:0:49:8438:8193:0
Das Erste HD;DVB-S2:11494:HC23M5O35S1:S19.2E:22000:5101=27:5102=deu@3,5103=mis@3;5106=deu@106:5104;5105=deu:0:10301:1:1019:0
=>
Das Erste HD;SAT>IP:11494:HC23M5O35S1:Z:22000:5101=27:5102=deu@3,5103=mis@3;5106=deu@106:5104;5105=deu:0:10301:1:1019:0
Notes:
- The stream id "-1" states about unsuccessful tuning. This might be a
result of invalid channel parameters or lack of free SAT>IP tuners.
- SAT>IP specification 1.2 doesn't support DVB-C/DVB-C2 receivers yet.
- SAT>IP specification 1.2 doesn't support DVB-C/DVB-C2 receivers yet,
but DVB-C (KABEL>IP) is supported for Digital Devices Octopus Net
devices.
- If the plugin doesn't detect your SAT>IP network device, make sure
your setup doesn't have firewalled the UDP port 1900.
- Stream decryption requires a separate CAM plugin that works without
direct access to any DVB card devices. The integrated CAM slot in
Octopus Net devices isn't supported.
Acknowledgements:
- Big thanks to Digital Devices GmbH for providing the Octopus Net

View File

@@ -70,12 +70,10 @@ cString ChangeCase(const cString &strP, bool upperP)
const section_filter_table_type section_filter_table[SECTION_FILTER_TABLE_SIZE] =
{
/* description tag pid tid mask */
{trNOOP("PAT (0x00)"), "PAT", 0x00, 0x00, 0xFF},
{trNOOP("NIT (0x40)"), "NIT", 0x10, 0x40, 0xFF},
{trNOOP("SDT (0x42)"), "SDT", 0x11, 0x42, 0xFF},
{trNOOP("EIT (0x4E/0x4F)"), "EIT", 0x12, 0x4E, 0xFE},
{trNOOP("EIT (0x5X)"), "EIT", 0x12, 0x50, 0xF0},
{trNOOP("EIT (0x6X)"), "EIT", 0x12, 0x60, 0xF0},
{trNOOP("TDT (0x70)"), "TDT", 0x14, 0x70, 0xFF},
/* description tag pid tid mask */
{trNOOP("PAT (0x00)"), "PAT", 0x00, 0x00, 0xFF},
{trNOOP("NIT (0x40)"), "NIT", 0x10, 0x40, 0xFF},
{trNOOP("SDT (0x42)"), "SDT", 0x11, 0x42, 0xFF},
{trNOOP("EIT (0x4E/0x4F/0x5X/0x6X)"), "EIT", 0x12, 0x40, 0xC0},
{trNOOP("TDT (0x70)"), "TDT", 0x14, 0x70, 0xFF},
};

View File

@@ -36,7 +36,7 @@
#define SATIP_STATS_ACTIVE_PIDS_COUNT 10
#define SATIP_STATS_ACTIVE_FILTERS_COUNT 10
#define SECTION_FILTER_TABLE_SIZE 7
#define SECTION_FILTER_TABLE_SIZE 5
#define SATIP_CURL_EASY_GETINFO(X, Y, Z) \
if ((res = curl_easy_getinfo((X), (Y), (Z))) != CURLE_OK) { \
@@ -78,6 +78,15 @@
} \
} while (0)
#define FREE_POINTER(ptr) \
do { \
if (ptr) { \
typeof(*ptr) *tmp = ptr; \
ptr = NULL; \
free(tmp); \
} \
} while (0)
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof(arr[0]))
uint16_t ts_pid(const uint8_t *bufP);

View File

@@ -11,7 +11,8 @@
cSatipConfig SatipConfig;
cSatipConfig::cSatipConfig(void)
: eitScanM(1),
: operatingModeM(eOperatingModeLow),
eitScanM(1),
useBytesM(1)
{
for (unsigned int i = 0; i < ARRAY_SIZE(disabledFiltersM); ++i)

View File

@@ -14,19 +14,34 @@
class cSatipConfig
{
private:
unsigned int operatingModeM;
unsigned int eitScanM;
unsigned int useBytesM;
int disabledFiltersM[SECTION_FILTER_TABLE_SIZE];
char configDirectoryM[PATH_MAX];
public:
enum {
eOperatingModeOff = 0,
eOperatingModeLow,
eOperatingModeNormal,
eOperatingModeHigh,
eOperatingModeCount
};
cSatipConfig();
unsigned int GetOperatingMode(void) const { return operatingModeM; }
bool IsOperatingModeOff(void) const { return (operatingModeM == eOperatingModeOff); }
bool IsOperatingModeLow(void) const { return (operatingModeM == eOperatingModeLow); }
bool IsOperatingModeNormal(void) const { return (operatingModeM == eOperatingModeNormal); }
bool IsOperatingModeHigh(void) const { return (operatingModeM == eOperatingModeHigh); }
void ToggleOperatingMode(void) { operatingModeM = (operatingModeM + 1) % eOperatingModeCount; }
unsigned int GetEITScan(void) const { return eitScanM; }
unsigned int GetUseBytes(void) const { return useBytesM; }
const char *GetConfigDirectory(void) const { return configDirectoryM; }
unsigned int GetDisabledFiltersCount(void) const;
int GetDisabledFilters(unsigned int indexP) const;
void SetOperatingMode(unsigned int operatingModeP) { operatingModeM = operatingModeP; }
void SetEITScan(unsigned int onOffP) { eitScanM = onOffP; }
void SetUseBytes(unsigned int onOffP) { useBytesM = onOffP; }
void SetConfigDirectory(const char *directoryP);

View File

@@ -7,7 +7,7 @@
#include "config.h"
#include "discover.h"
#include "source.h"
#include "param.h"
#include "device.h"
#define SATIP_MAX_DEVICES MAXDEVICES
@@ -19,7 +19,9 @@ cSatipDevice::cSatipDevice(unsigned int indexP)
isPacketDeliveredM(false),
isOpenDvrM(false),
deviceNameM(*cString::sprintf("%s %d", *DeviceType(), deviceIndexM)),
channelM()
channelM(),
createdM(0),
mutexM()
{
unsigned int bufsize = (unsigned int)SATIP_BUFFER_SIZE;
bufsize -= (bufsize % TS_SIZE);
@@ -49,8 +51,6 @@ cSatipDevice::~cSatipDevice()
bool cSatipDevice::Initialize(unsigned int deviceCountP)
{
debug("cSatipDevice::%s(%u)", __FUNCTION__, deviceCountP);
new cSatipSourceParam('Y', "DVB-T (SAT>IP)");
new cSatipSourceParam('Z', "DVB-S (SAT>IP)");
if (deviceCountP > SATIP_MAX_DEVICES)
deviceCountP = SATIP_MAX_DEVICES;
for (unsigned int i = 0; i < deviceCountP; ++i)
@@ -146,6 +146,12 @@ cString cSatipDevice::GetInformation(unsigned int pageP)
return s;
}
bool cSatipDevice::Ready(void)
{
//debug("cSatipDevice::%s(%u)", __FUNCTION__, deviceIndexM);
return ((cSatipDiscover::GetInstance()->GetServerCount() > 0) || (createdM.Elapsed() > eReadyTimeoutMs));
}
cString cSatipDevice::DeviceType(void) const
{
//debug("cSatipDevice::%s(%u)", __FUNCTION__, deviceIndexM);
@@ -158,6 +164,12 @@ cString cSatipDevice::DeviceName(void) const
return deviceNameM;
}
bool cSatipDevice::AvoidRecording(void) const
{
//debug("cSatipDevice::%s(%u)", __FUNCTION__, deviceIndexM);
return SatipConfig.IsOperatingModeLow();
}
int cSatipDevice::SignalStrength(void) const
{
//debug("cSatipDevice::%s(%u)", __FUNCTION__, deviceIndexM);
@@ -172,13 +184,8 @@ int cSatipDevice::SignalQuality(void) const
bool cSatipDevice::ProvidesSource(int sourceP) const
{
debug("cSatipDevice::%s(%u)", __FUNCTION__, deviceIndexM);
int model = 0;
if (cSource::IsType(sourceP, 'Z'))
model |= cSatipServer::eSatipModelTypeDVBS2;
if (cSource::IsType(sourceP, 'Y'))
model |= cSatipServer::eSatipModelTypeDVBT2 | cSatipServer::eSatipModelTypeDVBT;
return !!cSatipDiscover::GetInstance()->GetServer(model);
//debug("cSatipDevice::%s(%u)", __FUNCTION__, deviceIndexM);
return (!SatipConfig.IsOperatingModeOff() && !!cSatipDiscover::GetInstance()->GetServer(sourceP));
}
bool cSatipDevice::ProvidesTransponder(const cChannel *channelP) const
@@ -225,12 +232,23 @@ bool cSatipDevice::ProvidesChannel(const cChannel *channelP, int priorityP, bool
bool cSatipDevice::ProvidesEIT(void) const
{
return (SatipConfig.GetEITScan() && pTunerM && pTunerM->IsTuned());
return (SatipConfig.GetEITScan());
}
int cSatipDevice::NumProvidedSystems(void) const
{
return cSatipDiscover::GetInstance()->NumProvidedSystems();
int count = cSatipDiscover::GetInstance()->NumProvidedSystems();
// Tweak the count according to operation mode
if (SatipConfig.IsOperatingModeLow())
count = 15;
else if (SatipConfig.IsOperatingModeHigh())
count = 1;
// Clamp the count between 1 and 15
if (count > 15)
count = 15;
else if (count < 1)
count = 1;
return count;
}
const cChannel *cSatipDevice::GetCurrentlyTunedTransponder(void) const
@@ -255,33 +273,20 @@ bool cSatipDevice::MaySwitchTransponder(const cChannel *channelP) const
bool cSatipDevice::SetChannelDevice(const cChannel *channelP, bool liveViewP)
{
if (channelP) {
cSatipTransponderParameters stp(channelP->Parameters());
cString params = stp.UrlParameters(cSource::ToChar(channelP->Source()));
cString address;
int mode = 0;
if (cSource::IsType(channelP->Source(), 'Z'))
mode |= cSatipServer::eSatipModelTypeDVBS2;
if (cSource::IsType(channelP->Source(), 'Y'))
mode |= stp.System() ? cSatipServer::eSatipModelTypeDVBT2 : cSatipServer::eSatipModelTypeDVBT;
cSatipServer *server = cSatipDiscover::GetInstance()->GetServer(mode);
if (!server) {
debug("cSatipDevice::%s(%u): no suitable server found", __FUNCTION__, deviceIndexM);
return false;
}
address = server->Address();
float freq = channelP->Frequency();
cDvbTransponderParameters dtp(channelP->Parameters());
cString params = GetTransponderUrlParameters(channelP);
if (isempty(params)) {
error("Unrecognized SAT>IP channel parameters: %s", channelP->Parameters());
return false;
}
// Scale down frequencies to MHz
while (freq > 20000L)
freq /= 1000L;
params = cString::sprintf("freq=%s%s", *dtoa(freq, "%.3f"), *params);
if (cSource::IsType(channelP->Source(), 'Z'))
params = cString::sprintf("%s&sr=%d", *params, channelP->Srate());
if (pTunerM && pTunerM->SetSource(*address, *params, deviceIndexM)) {
deviceNameM = cString::sprintf("%s %d %s:%s:%s", *DeviceType(), deviceIndexM, server->Address(), server->Model(), server->Description());
cString address;
cSatipServer *server = cSatipDiscover::GetInstance()->GetServer(channelP->Source(), dtp.System());
if (!server) {
debug("cSatipDevice::%s(%u): no suitable server found", __FUNCTION__, deviceIndexM);
return false;
}
if (pTunerM && pTunerM->SetSource(server, *params, deviceIndexM)) {
deviceNameM = cString::sprintf("%s %d %s", *DeviceType(), deviceIndexM, *cSatipDiscover::GetInstance()->GetServerString(server));
channelM = *channelP;
return true;
}
@@ -303,11 +308,12 @@ bool cSatipDevice::SetPid(cPidHandle *handleP, int typeP, bool onP)
int cSatipDevice::OpenFilter(u_short pidP, u_char tidP, u_char maskP)
{
//debug("cSatipDevice::%s(%u): pid=%d tid=%d mask=%d", __FUNCTION__, deviceIndexM, pidP, tidP, maskP);
//debug("cSatipDevice::%s(%u): pid=%d tid=%d mask=%d", __FUNCTION__, deviceIndexM, pidP, tidP, maskP);
if (pSectionFilterHandlerM) {
if (pTunerM)
int handle = pSectionFilterHandlerM->Open(pidP, tidP, maskP);
if (pTunerM && (handle >= 0))
pTunerM->SetPid(pidP, ptOther, true);
return pSectionFilterHandlerM->Open(pidP, tidP, maskP);
return handle;
}
return -1;
}
@@ -375,6 +381,12 @@ unsigned int cSatipDevice::CheckData(void)
return 0;
}
int cSatipDevice::GetId(void)
{
//debug("cSatipDevice::%s(%u)", __FUNCTION__, deviceIndexM);
return deviceIndexM;
}
uchar *cSatipDevice::GetData(int *availableP)
{
//debug("cSatipDevice::%s(%u)", __FUNCTION__, deviceIndexM);

View File

@@ -26,6 +26,9 @@ public:
// private parts
private:
enum {
eReadyTimeoutMs = 2000 // in milliseconds
};
unsigned int deviceIndexM;
bool isPacketDeliveredM;
bool isOpenDvrM;
@@ -34,6 +37,7 @@ private:
cRingBufferLinear *tsBufferM;
cSatipTuner *pTunerM;
cSatipSectionFilterHandler *pSectionFilterHandlerM;
cTimeMs createdM;
cMutex mutexM;
// constructor & destructor
@@ -54,8 +58,10 @@ private:
// for channel info
public:
virtual bool Ready(void);
virtual cString DeviceType(void) const;
virtual cString DeviceName(void) const;
virtual bool AvoidRecording(void) const;
virtual int SignalStrength(void) const;
virtual int SignalQuality(void) const;
@@ -101,6 +107,7 @@ public:
public:
virtual void WriteData(u_char *bufferP, int lengthP);
virtual unsigned int CheckData(void);
virtual int GetId(void);
};
#endif // __SATIP_DEVICE_H

View File

@@ -14,6 +14,7 @@ public:
virtual ~cSatipDeviceIf() {}
virtual void WriteData(u_char *bufferP, int lengthP) = 0;
virtual unsigned int CheckData(void) = 0;
virtual int GetId(void) = 0;
private:
cSatipDeviceIf(const cSatipDeviceIf&);

View File

@@ -6,7 +6,11 @@
*/
#include <string.h>
#ifdef USE_TINYXML
#include <tinyxml.h>
#else
#include <pugixml.hpp>
#endif
#include "common.h"
#include "config.h"
#include "socket.h"
@@ -31,36 +35,52 @@ cSatipDiscover *cSatipDiscover::GetInstance(void)
bool cSatipDiscover::Initialize(void)
{
debug("cSatipDiscover::%s()", __FUNCTION__);
if (instanceS)
instanceS->Activate();
return true;
}
void cSatipDiscover::Destroy(void)
{
debug("cSatipDiscover::%s()", __FUNCTION__);
DELETE_POINTER(instanceS);
if (instanceS)
instanceS->Deactivate();
}
size_t cSatipDiscover::WriteCallback(void *ptrP, size_t sizeP, size_t nmembP, void *dataP)
size_t cSatipDiscover::WriteCallback(char *ptrP, size_t sizeP, size_t nmembP, void *dataP)
{
cSatipDiscover *obj = reinterpret_cast<cSatipDiscover *>(dataP);
size_t len = sizeP * nmembP;
//debug("cSatipDiscover::%s(%zu)", __FUNCTION__, len);
char *s, *p = (char *)ptrP;
char *r = strtok_r(p, "\r\n", &s);
char *desc = NULL, *model = NULL, *addr = NULL;
while (r) {
//debug("cSatipDiscover::%s(%zu): %s", __FUNCTION__, len, r);
// <friendlyName>OctopusNet</friendlyName>
if (startswith(r, "<friendlyName"))
desc = StripTags(r);
// <satip:X_SATIPCAP xmlns:satip="urn:ses-com:satip">DVBT-2</satip:X_SATIPCAP>
if (startswith(r, "<satip:X_SATIPCAP"))
model = StripTags(r);
r = strtok_r(NULL, "\r\n", &s);
}
if (obj) {
CURLcode res = CURLE_OK;
const char *desc = NULL, *model = NULL, *addr = NULL;
#ifdef USE_TINYXML
TiXmlDocument doc;
char *xml = MALLOC(char, len + 1);
memcpy(xml, ptrP, len);
*(xml + len + 1) = 0;
doc.Parse((const char *)xml);
TiXmlHandle docHandle(&doc);
TiXmlElement *descElement = docHandle.FirstChild("root").FirstChild("device").FirstChild("friendlyName").ToElement();
if (descElement)
desc = descElement->GetText() ? descElement->GetText() : "MyBrokenHardware";
TiXmlElement *modelElement = docHandle.FirstChild("root").FirstChild("device").FirstChild("satip:X_SATIPCAP").ToElement();
if (modelElement)
model = modelElement->GetText() ? modelElement->GetText() : "DVBS2-1";
#else
pugi::xml_document doc;
pugi::xml_parse_result result = doc.load_buffer(ptrP, len);
if (result) {
pugi::xml_node descNode = doc.first_element_by_path("root/device/friendlyName");
if (descNode)
desc = descNode.text().as_string("MyBrokenHardware");
pugi::xml_node modelNode = doc.first_element_by_path("root/device/satip:X_SATIPCAP");
if (modelNode)
model = modelNode.text().as_string("DVBS2-1");
}
#endif
SATIP_CURL_EASY_GETINFO(obj->handleM, CURLINFO_PRIMARY_IP, &addr);
obj->AddServer(addr, desc, model);
}
@@ -85,10 +105,8 @@ cSatipDiscover::cSatipDiscover()
cSatipDiscover::~cSatipDiscover()
{
debug("cSatipDiscover::%s()", __FUNCTION__);
Deactivate();
cMutexLock MutexLock(&mutexM);
sleepM.Signal();
if (Running())
Cancel(3);
// Free allocated memory
DELETENULL(socketM);
DELETENULL(serversM);
@@ -97,6 +115,21 @@ cSatipDiscover::~cSatipDiscover()
handleM = NULL;
}
void cSatipDiscover::Activate(void)
{
// Start the thread
Start();
}
void cSatipDiscover::Deactivate(void)
{
debug("cSatipDiscover::%s()", __FUNCTION__);
cMutexLock MutexLock(&mutexM);
sleepM.Signal();
if (Running())
Cancel(3);
}
void cSatipDiscover::Action(void)
{
debug("cSatipDiscover::%s(): entering", __FUNCTION__);
@@ -117,12 +150,8 @@ void cSatipDiscover::Janitor(void)
{
debug("cSatipDiscover::%s()", __FUNCTION__);
cMutexLock MutexLock(&mutexM);
for (cSatipServer *srv = serversM->First(); srv; srv = serversM->Next(srv)) {
if (srv->LastSeen() > eProbeIntervalMs * 2) {
info("Removing device %s (%s %s)", srv->Description(), srv->Address(), srv->Model());
serversM->Del(srv);
}
}
if (serversM)
serversM->Cleanup(eProbeIntervalMs * 2);
}
void cSatipDiscover::Probe(void)
@@ -213,15 +242,7 @@ void cSatipDiscover::AddServer(const char *addrP, const char *descP, const char
if (serversM) {
cSatipServer *tmp = new cSatipServer(addrP, descP, modelP);
// Validate against existing servers
bool found = false;
for (cSatipServer *s = serversM->First(); s; s = serversM->Next(s)) {
if (s->Compare(*tmp) == 0) {
found = true;
s->Update();
break;
}
}
if (!found) {
if (!serversM->Update(tmp)) {
info("Adding device %s (%s %s)", tmp->Description(), tmp->Address(), tmp->Model());
serversM->Add(tmp);
}
@@ -230,26 +251,25 @@ void cSatipDiscover::AddServer(const char *addrP, const char *descP, const char
}
}
bool cSatipDiscover::IsValidServer(cSatipServer *serverP)
int cSatipDiscover::GetServerCount(void)
{
//debug("cSatipDiscover::%s(%d)", __FUNCTION__);
//debug("cSatipDiscover::%s()", __FUNCTION__);
cMutexLock MutexLock(&mutexM);
for (cSatipServer *srv = serversM->First(); srv; srv = serversM->Next(srv)) {
if (srv == serverP)
return true;
}
return false;
return serversM ? serversM->Count() : -1;
}
cSatipServer *cSatipDiscover::GetServer(int modelP)
cSatipServer *cSatipDiscover::GetServer(int sourceP, int systemP)
{
//debug("cSatipDiscover::%s(%d)", __FUNCTION__, modelP);
//debug("cSatipDiscover::%s(%d, %d)", __FUNCTION__, sourceP, systemP);
cMutexLock MutexLock(&mutexM);
for (cSatipServer *srv = serversM->First(); srv; srv = serversM->Next(srv)) {
if (srv->Match(modelP))
return srv;
}
return NULL;
return serversM ? serversM->Find(sourceP, systemP) : NULL;
}
cSatipServer *cSatipDiscover::GetServer(cSatipServer *serverP)
{
//debug("cSatipDiscover::%s()", __FUNCTION__);
cMutexLock MutexLock(&mutexM);
return serversM ? serversM->Find(serverP) : NULL;
}
cSatipServers *cSatipDiscover::GetServers(void)
@@ -259,25 +279,31 @@ cSatipServers *cSatipDiscover::GetServers(void)
return serversM;
}
cString cSatipDiscover::GetServerString(cSatipServer *serverP)
{
//debug("cSatipDiscover::%s(%d)", __FUNCTION__, modelP);
cMutexLock MutexLock(&mutexM);
return serversM ? serversM->GetString(serverP) : "";
}
cString cSatipDiscover::GetServerList(void)
{
//debug("cSatipDiscover::%s(%d)", __FUNCTION__, modelP);
cMutexLock MutexLock(&mutexM);
cString list = "";
for (cSatipServer *srv = serversM->First(); srv; srv = serversM->Next(srv))
list = cString::sprintf("%s%s:%s:%s\n", *list, srv->Address(), srv->Model(), srv->Description());
return list;
return serversM ? serversM->List() : "";
}
void cSatipDiscover::UseServer(cSatipServer *serverP, bool onOffP)
{
//debug("cSatipDiscover::%s(%d)", __FUNCTION__, modelP);
cMutexLock MutexLock(&mutexM);
if (serversM)
serversM->Use(serverP, onOffP);
}
int cSatipDiscover::NumProvidedSystems(void)
{
//debug("cSatipDiscover::%s(%d)", __FUNCTION__, modelP);
cMutexLock MutexLock(&mutexM);
int count = 0;
for (cSatipServer *srv = serversM->First(); srv; srv = serversM->Next(srv)) {
count += srv->Satellite();
count += srv->Terrestrial();
count += srv->Terrestrial2();
}
return count;
return serversM ? serversM->NumProvidedSystems() : 0;
}

View File

@@ -9,79 +9,13 @@
#define __SATIP_DISCOVER_H
#include <curl/curl.h>
#include <curl/easy.h>
#include <vdr/thread.h>
#include <vdr/tools.h>
#include "server.h"
#include "socket.h"
class cSatipServer : public cListObject {
private:
enum eSatipServer {
eSatipServerDVBS2 = 0,
eSatipServerDVBT,
eSatipServerDVBT2,
eSatipServerCount
};
cString addressM;
cString descriptionM;
cString modelM;
int modelCountM[eSatipServerCount];
int modelTypeM;
cTimeMs lastSeenM;
public:
enum eSatipModelType {
eSatipModelTypeDVBS2 = 0x01,
eSatipModelTypeDVBT = 0x02,
eSatipModelTypeDVBT2 = 0x04,
eSatipModelTypeMask = 0x0F
};
cSatipServer(const char *addressP, const char *descriptionP, const char *modelP) : addressM(addressP), descriptionM(descriptionP), modelM(modelP), modelTypeM(eSatipModelTypeMask), lastSeenM(0)
{
memset(modelCountM, 0, sizeof(modelCountM));
if (isempty(*modelM))
modelM = "DVBS-1,DVBT2-1";
char *s, *p = strdup(*modelM);
char *r = strtok_r(p, ",", &s);
while (r) {
if (strstr(r, "DVBS2")) {
modelTypeM |= cSatipServer::eSatipModelTypeDVBS2;
if (char *c = strstr(r, "-"))
modelCountM[eSatipServerDVBS2] = atoi(++c);
}
if (strstr(r, "DVBT2")) {
modelTypeM |= cSatipServer::eSatipModelTypeDVBT | cSatipServer::eSatipModelTypeDVBT2;
if (char *c = strstr(r, "-"))
modelCountM[eSatipServerDVBT2] = atoi(++c);
}
if (strstr(r, "DVBT")) {
modelTypeM |= cSatipServer::eSatipModelTypeDVBT;
if (char *c = strstr(r, "-"))
modelCountM[eSatipServerDVBT] = atoi(++c);
}
r = strtok_r(NULL, ",", &s);
}
free(p);
}
virtual int Compare(const cListObject &listObjectP) const { const cSatipServer *s = (const cSatipServer *)&listObjectP; return strcasecmp(*addressM, *s->addressM); }
const char *Description() { return *descriptionM; }
const char *Address() { return *addressM; }
const char *Model(void) { return modelM; }
int ModelType(void) { return modelTypeM; }
bool Match(int modelP) { return ((modelP & eSatipModelTypeMask) & modelTypeM); }
int Satellite() { return (modelTypeM & eSatipModelTypeDVBS2) ? modelCountM[eSatipServerDVBS2] : 0; }
int Terrestrial() { return (modelTypeM & eSatipModelTypeDVBT) ? modelCountM[eSatipServerDVBT] : 0; }
int Terrestrial2() { return (modelTypeM & eSatipModelTypeDVBT2) ? modelCountM[eSatipServerDVBT2] : 0; }
int LastSeen(void) { return lastSeenM.Elapsed(); }
void Update(void) { lastSeenM.Set(); }
};
class cSatipServers : public cList<cSatipServer> {
};
class cSatipDiscover : public cThread {
private:
enum {
@@ -94,13 +28,15 @@ private:
static cSatipDiscover *instanceS;
static const char *bcastAddressS;
static const char *bcastMessageS;
static size_t WriteCallback(void *ptrP, size_t sizeP, size_t nmembP, void *dataP);
static size_t WriteCallback(char *ptrP, size_t sizeP, size_t nmembP, void *dataP);
cMutex mutexM;
CURL *handleM;
cSatipSocket *socketM;
cCondWait sleepM;
cTimeMs probeIntervalM;
cSatipServers *serversM;
void Activate(void);
void Deactivate(void);
void Janitor(void);
void Probe(void);
void Read(void);
@@ -119,9 +55,13 @@ public:
static bool Initialize(void);
static void Destroy(void);
virtual ~cSatipDiscover();
bool IsValidServer(cSatipServer *serverP);
cSatipServer *GetServer(int modelP);
void TriggerScan(void) { probeIntervalM.Set(0); }
int GetServerCount(void);
cSatipServer *GetServer(int sourceP, int systemP = -1);
cSatipServer *GetServer(cSatipServer *serverP);
cSatipServers *GetServers(void);
cString GetServerString(cSatipServer *serverP);
void UseServer(cSatipServer *serverP, bool onOffP);
cString GetServerList(void);
int NumProvidedSystems(void);
};

183
param.c Normal file
View File

@@ -0,0 +1,183 @@
/*
* param.c: SAT>IP plugin for the Video Disk Recorder
*
* See the README file for copyright information and how to reach the author.
*
*/
#include <ctype.h>
#include <vdr/dvbdevice.h>
#include "common.h"
#include "param.h"
// --- cSatipParameterMaps ----------------------------------------------------
struct tSatipParameterMap {
int driverValue;
const char *satipString;
};
static const tSatipParameterMap SatipBandwidthValues[] = {
{ 5000000, "&bw=5" },
{ 6000000, "&bw=6" },
{ 7000000, "&bw=7" },
{ 8000000, "&bw=8" },
{ 10000000, "&bw=10" },
{ 1712000, "&bw=1.712" },
{ -1, NULL }
};
static const tSatipParameterMap SatipPilotValues[] = {
{ PILOT_OFF, "&plts=off" },
{ PILOT_ON, "&plts=on" },
{ PILOT_AUTO, "" },
{ -1, NULL }
};
static const tSatipParameterMap SatipSisoMisoValues[] = {
{ 0, "&sm=0" },
{ 1, "&sm=1" },
{ -1, NULL }
};
static const tSatipParameterMap SatipCodeRateValues[] = {
{ FEC_NONE, "" },
{ FEC_1_2, "&fec=12" },
{ FEC_2_3, "&fec=23" },
{ FEC_3_4, "&fec=34" },
{ FEC_3_5, "&fec=35" },
{ FEC_4_5, "&fec=45" },
{ FEC_5_6, "&fec=56" },
{ FEC_6_7, "&fec=67" },
{ FEC_7_8, "&fec=78" },
{ FEC_8_9, "&fec=89" },
{ FEC_9_10, "&fec=910" },
{ FEC_AUTO, "" },
{ -1, NULL }
};
static const tSatipParameterMap SatipModulationValues[] = {
{ QPSK, "&mtype=qpsk" },
{ PSK_8, "&mtype=8psk" },
{ QAM_16, "&mtype=16qam" },
{ QAM_64, "&mtype=64qam" },
{ QAM_128, "&mtype=128qam" },
{ QAM_256, "&mtype=256qam" },
{ QAM_AUTO, "" },
{ -1, NULL }
};
static const tSatipParameterMap SatipSystemValuesSat[] = {
{ 0, "&msys=dvbs" },
{ 1, "&msys=dvbs2" },
{ -1, NULL }
};
static const tSatipParameterMap SatipSystemValuesTerrestrial[] = {
{ 0, "&msys=dvbt" },
{ 1, "&msys=dvbt2" },
{ -1, NULL }
};
static const tSatipParameterMap SatipSystemValuesCable[] = {
{ 0, "&msys=dvbc" },
{ 1, "&msys=dvbc2" },
{ -1, NULL }
};
static const tSatipParameterMap SatipTransmissionValues[] = {
{ TRANSMISSION_MODE_1K, "&tmode=1k" },
{ TRANSMISSION_MODE_2K, "&tmode=2k" },
{ TRANSMISSION_MODE_4K, "&tmode=4k" },
{ TRANSMISSION_MODE_8K, "&tmode=8k" },
{ TRANSMISSION_MODE_16K, "&tmode=16k" },
{ TRANSMISSION_MODE_32K, "&tmode=32k" },
{ TRANSMISSION_MODE_AUTO, "" },
{ -1, NULL }
};
static const tSatipParameterMap SatipGuardValues[] = {
{ GUARD_INTERVAL_1_4, "&gi=14" },
{ GUARD_INTERVAL_1_8, "&gi=18" },
{ GUARD_INTERVAL_1_16, "&gi=116" },
{ GUARD_INTERVAL_1_32, "&gi=132" },
{ GUARD_INTERVAL_1_128, "&gi=1128" },
{ GUARD_INTERVAL_19_128, "&gi=19128" },
{ GUARD_INTERVAL_19_256, "&gi=19256" },
{ GUARD_INTERVAL_AUTO, "" },
{ -1, NULL }
};
static const tSatipParameterMap SatipRollOffValues[] = {
{ ROLLOFF_AUTO, "" },
{ ROLLOFF_20, "&ro=0.20" },
{ ROLLOFF_25, "&ro=0.25" },
{ ROLLOFF_35, "&ro=0.35" },
{ -1, NULL }
};
static int SatipUserIndex(int valueP, const tSatipParameterMap *mapP)
{
const tSatipParameterMap *map = mapP;
while (map && map->driverValue != -1) {
if (map->driverValue == valueP)
return map - mapP;
map++;
}
return -1;
}
static int PrintUrlString(char *bufP, int lenP, int valueP, const tSatipParameterMap *mapP)
{
int n = SatipUserIndex(valueP, mapP);
return ((n >= 0) && (lenP > 0)) ? snprintf(bufP, lenP, "%s", mapP[n].satipString) : 0;
}
cString GetTransponderUrlParameters(const cChannel *channelP)
{
if (channelP) {
char buffer[255];
cDvbTransponderParameters dtp(channelP->Parameters());
#if defined(APIVERSNUM) && APIVERSNUM < 20106
int Pilot = PILOT_AUTO;
int T2SystemId = 0;
int SisoMiso = 0;
#else
int Pilot = dtp.Pilot();
int T2SystemId = dtp.T2SystemId();
int SisoMiso = dtp.SisoMiso();
#endif
float freq = channelP->Frequency();
char type = cSource::ToChar(channelP->Source());
cSource *source = Sources.Get(channelP->Source());
int src = (strchr("S", type) && source) ? atoi(source->Description()) : 1;
char *q = buffer;
*q = 0;
// Scale down frequencies to MHz
while (freq > 20000L)
freq /= 1000L;
#define ST(s) if (strchr(s, type) && (strchr(s, '0' + dtp.System() + 1) || strchr(s, '*')))
#define STBUFLEFT (sizeof(buffer) - (q - buffer))
q += snprintf(q, STBUFLEFT, "freq=%s", *dtoa(freq, "%lg"));
ST(" S *") q += snprintf(q, STBUFLEFT, "&src=%d", ((src > 0) && (src <= 255)) ? src : 1);
ST("CS *") q += snprintf(q, STBUFLEFT, "&sr=%d", channelP->Srate());
ST(" S *") q += snprintf(q, STBUFLEFT, "&pol=%c", tolower(dtp.Polarization()));
ST("C T2") q += snprintf(q, STBUFLEFT, "&plp=%d", dtp.StreamId());
ST(" T2") q += snprintf(q, STBUFLEFT, "&t2id=%d", T2SystemId);
ST(" T2") q += PrintUrlString(q, STBUFLEFT, SisoMiso, SatipSisoMisoValues);
ST(" T*") q += PrintUrlString(q, STBUFLEFT, dtp.Bandwidth(), SatipBandwidthValues);
ST(" T*") q += PrintUrlString(q, STBUFLEFT, dtp.Guard(), SatipGuardValues);
ST("CST*") q += PrintUrlString(q, STBUFLEFT, dtp.CoderateH(), SatipCodeRateValues);
ST(" S 2") q += PrintUrlString(q, STBUFLEFT, Pilot, SatipPilotValues);
ST(" S 2") q += PrintUrlString(q, STBUFLEFT, dtp.Modulation(), SatipModulationValues);
ST("C T*") q += PrintUrlString(q, STBUFLEFT, dtp.Modulation(), SatipModulationValues);
ST(" S 2") q += PrintUrlString(q, STBUFLEFT, dtp.RollOff(), SatipRollOffValues);
ST(" S *") q += PrintUrlString(q, STBUFLEFT, dtp.System(), SatipSystemValuesSat);
ST("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);
#undef ST
return buffer;
}
return NULL;
}

15
param.h Normal file
View File

@@ -0,0 +1,15 @@
/*
* param.h: SAT>IP plugin for the Video Disk Recorder
*
* See the README file for copyright information and how to reach the author.
*
*/
#ifndef __SATIP_PARAM_H
#define __SATIP_PARAM_H
#include "common.h"
cString GetTransponderUrlParameters(const cChannel *channelP);
#endif // __SATIP_PARAM_H

137
po/ca_ES.po Normal file
View File

@@ -0,0 +1,137 @@
# VDR plugin language source file.
# Copyright (C) 2007-2014 Rolf Ahrenberg
# This file is distributed under the same license as the satip package.
# Gabriel Bonich, 2014
#
msgid ""
msgstr ""
"Project-Id-Version: vdr-satip 0.2.3\n"
"Report-Msgid-Bugs-To: <see README>\n"
"POT-Creation-Date: 2014-04-12 04:12+0200\n"
"PO-Revision-Date: 2014-04-12 04:12+0200\n"
"Last-Translator: Gabriel Bonich <gbonich@gmail.com>\n"
"Language-Team: Catalan <vdr@linuxtv.org>\n"
"Language: ca\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\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 Devices"
msgstr "SAT>IP Dispositius"
msgid "SAT>IP Device"
msgstr "SAT>IP Dispositiu"
msgid "Address"
msgstr "Adressa"
msgid "Model"
msgstr "Model"
msgid "Description"
msgstr "Descripció"
msgid "Creation date"
msgstr "Creació de data"
msgid "SAT>IP Information"
msgstr "SAT>IP Informació"
msgid "General"
msgstr "General"
msgid "Pids"
msgstr "Pids"
msgid "Filters"
msgstr "Filtres"
msgid "Bits/bytes"
msgstr "Bits/Bytes"
msgid "SAT>IP information not available!"
msgstr "SAT>IP Informació no disponible!"
msgid "off"
msgstr "Apagat"
msgid "low"
msgstr "Baix"
msgid "normal"
msgstr "Normal"
msgid "high"
msgstr "Alt"
msgid "Operating mode"
msgstr "Mode de operació"
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 ""
"Defineig la manera de operar els Disposituis SAT>IP:\n"
"\n"
"Apagat - Dispositius desactivats\n"
"Baix - Dispositius treballan a baixa prioritat\n"
"Normal - Dispositius treballan en parametres normals\n"
"Alta - Dispositius treballan a prioritat Alta"
msgid "Enable EPG scanning"
msgstr "Activa Escanneig 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 ""
"Definir si s'utilitzarà l'anàlisi en segon pla del EPG.\n"
"\n"
"Aquesta configuració desactiva la funcionalitat d'escaneig EIT automàtica per a tots els dispositius SAT>IP."
msgid "Disabled filters"
msgstr "Desactiva filtres"
msgid "none"
msgstr "no"
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 black-listing the filters here useful section data can be left intact for VDR to process."
msgstr ""
"Defineix el numero de filtres de secció que seran deshabilitats.\n"
"\n"
"Alguns filtres de secció podrien provocar un comportament no desitjat a VDR, com sincronitzar malament l'hora. Posant aquests filtres a la llista negra, aqui, la secció de dades útil pot ser deixada intacta pel seu procès en el VDR."
msgid "Filter"
msgstr "Filtra"
msgid "Define an ill-behaving filter to be blacklisted."
msgstr "Definir un filtre mal comportar a la llista negra."
msgid "Active SAT>IP devices:"
msgstr "Dispositius SAT>IP actius:"
msgid "Help"
msgstr "Ajuda"

View File

@@ -1,14 +1,14 @@
# VDR plugin language source file.
# Copyright (C) 2007-2014 Rolf Ahrenberg & Antti Seppala
# This file is distributed under the same license as the iptv package.
# Copyright (C) 2007-2014 Rolf Ahrenberg
# This file is distributed under the same license as the satip package.
# Frank Neumann, 2014
#
msgid ""
msgstr ""
"Project-Id-Version: vdr-satip 0.0.1\n"
"Project-Id-Version: vdr-satip 0.2.3\n"
"Report-Msgid-Bugs-To: <see README>\n"
"POT-Creation-Date: 2014-03-08 03:08+0200\n"
"PO-Revision-Date: 2014-03-08 03:08+0200\n"
"POT-Creation-Date: 2014-04-12 04:12+0200\n"
"PO-Revision-Date: 2014-04-12 04:12+0200\n"
"Last-Translator: Frank Neumann <fnu@yavdr.org>\n"
"Language-Team: German <vdr@linuxtv.org>\n"
"Language: de\n"
@@ -25,14 +25,8 @@ msgstr "NIT (0x40)"
msgid "SDT (0x42)"
msgstr "SDT (0x42)"
msgid "EIT (0x4E/0x4F)"
msgstr "EIT (0x4E/0x4F)"
msgid "EIT (0x5X)"
msgstr "EIT (0x5X)"
msgid "EIT (0x6X)"
msgstr "EIT (0x6X)"
msgid "EIT (0x4E/0x4F/0x5X/0x6X)"
msgstr "EIT (0x4E/0x4F/0x5X/0x6X)"
msgid "TDT (0x70)"
msgstr "TDT (0x70)"
@@ -43,8 +37,17 @@ msgstr "SAT>IP Geräte"
msgid "SAT>IP Device"
msgstr "SAT>IP Gerät"
msgid "Button$Scan"
msgstr "Starte Kanalsuche"
msgid "Address"
msgstr "Adresse"
msgid "Model"
msgstr "Modell"
msgid "Description"
msgstr "Beschreibung"
msgid "Creation date"
msgstr "Zeitpunkt der Erstellung"
msgid "SAT>IP Information"
msgstr "SAT>IP Informationen"
@@ -64,6 +67,36 @@ msgstr "Bits/Bytes"
msgid "SAT>IP information not available!"
msgstr "Keine SAT>IP Informationen verfügbar!"
msgid "off"
msgstr "aus"
msgid "low"
msgstr "niedrig"
msgid "normal"
msgstr "normal"
msgid "high"
msgstr "hoch"
msgid "Operating mode"
msgstr "Betriebsmodus"
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 ""
"Bestimme den Betriebsmodus für alle SAT>IP Geräte:\n"
"\n"
"aus - Geräte sind abgeschaltet\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"
msgid "Enable EPG scanning"
msgstr "Aktiviere EPG Aktualisierung"
@@ -76,7 +109,6 @@ msgstr ""
"\n"
"Diese Einstellung schaltet die automatische EIT Aktualisierung für alle SAT>IP Geräte."
msgid "Disabled filters"
msgstr "Deaktivierte Filter"
@@ -103,39 +135,3 @@ msgstr "Aktive SAT>IP Geräte:"
msgid "Help"
msgstr "Hilfe"
msgid "off"
msgstr "aus"
msgid "on"
msgstr "ein"
msgid "auto"
msgstr "auto"
msgid "SISO"
msgstr "SISO"
msgid "MISO"
msgstr "MISO"
msgid "Nid"
msgstr "Nid"
msgid "Tid"
msgstr "Tid"
msgid "Rid"
msgstr "Rid"
msgid "SignalSource"
msgstr "Signalquelle"
msgid "PilotTones"
msgstr "Pilottöne"
msgid "T2SystemId"
msgstr "T2-Systemkennung"
msgid "SISO/MISO"
msgstr "SISO/MISO"

137
po/es_ES.po Normal file
View File

@@ -0,0 +1,137 @@
# VDR plugin language source file.
# Copyright (C) 2007-2014 Rolf Ahrenberg
# This file is distributed under the same license as the satip package.
# Gabriel Bonich, 2014
#
msgid ""
msgstr ""
"Project-Id-Version: vdr-satip 0.2.3\n"
"Report-Msgid-Bugs-To: <see README>\n"
"POT-Creation-Date: 2014-04-12 04:12+0200\n"
"PO-Revision-Date: 2014-04-12 04:12+0200\n"
"Last-Translator: Gabriel Bonich <gbonich@gmail.com>\n"
"Language-Team: Spanish <vdr@linuxtv.org>\n"
"Language: es\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\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 Devices"
msgstr "SAT>IP Dispositivos"
msgid "SAT>IP Device"
msgstr "SAT>IP Dispositivo"
msgid "Address"
msgstr "Dirección"
msgid "Model"
msgstr "Modelo"
msgid "Description"
msgstr "Descripción"
msgid "Creation date"
msgstr "Fecha creación"
msgid "SAT>IP Information"
msgstr "SAT>IP Información"
msgid "General"
msgstr "General"
msgid "Pids"
msgstr "Pids"
msgid "Filters"
msgstr "Filtros"
msgid "Bits/bytes"
msgstr "Bits/Bytes"
msgid "SAT>IP information not available!"
msgstr "SAT>IP Información no disponible!"
msgid "off"
msgstr "Apagado"
msgid "low"
msgstr "Bajo"
msgid "normal"
msgstr "Normal"
msgid "high"
msgstr "Alto"
msgid "Operating mode"
msgstr "Modo de operación"
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 ""
"Define la manera que trabajan los Dispositivos SAT>IP:\n"
"\n"
"Apagat - Dispositivos desactivados\n"
"Baix - Dispositivos trabajando con prioridad Baja\n"
"Normal - Dispositivos trabajando con prioridad Normal\n"
"Alta - Dispositivos trabajando con prioridad Alta"
msgid "Enable EPG scanning"
msgstr "Activa Escaneo 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 ""
"Definir si se utilitzará el analisí en segundo plano del EPG.\n"
"\n"
"Esta configuración desactiva la funcionalidad del escaneo EIT automática para todos los Dispositivos SAT>IP."
msgid "Disabled filters"
msgstr "Desactiva filtros"
msgid "none"
msgstr "no"
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 black-listing the filters here useful section data can be left intact for VDR to process."
msgstr ""
"Define el numero de filtros de sección que seran deshabilitados.\n"
"\n"
"Algunos filtros de sección podrian causar un comportamiento no deseado a VDR, como sincronizar mal la hora. Poniendo estos filtros en la lista negra, aqui, la sección de datos útiles se puede dejar intacta para su proceso con el VDR."
msgid "Filter"
msgstr "Filtra"
msgid "Define an ill-behaving filter to be blacklisted."
msgstr "Define un filtro para poner en la lista negra."
msgid "Active SAT>IP devices:"
msgstr "Dispositivos SAT>IP activos:"
msgid "Help"
msgstr "Ayuda"

View File

@@ -1,14 +1,14 @@
# VDR plugin language source file.
# Copyright (C) 2007-2014 Rolf Ahrenberg & Antti Seppala
# This file is distributed under the same license as the iptv package.
# Copyright (C) 2007-2014 Rolf Ahrenberg
# This file is distributed under the same license as the satip package.
# Rolf Ahrenberg, 2014
#
msgid ""
msgstr ""
"Project-Id-Version: vdr-satip 0.0.1\n"
"Project-Id-Version: vdr-satip 0.2.3\n"
"Report-Msgid-Bugs-To: <see README>\n"
"POT-Creation-Date: 2014-03-08 03:08+0200\n"
"PO-Revision-Date: 2014-03-08 03:08+0200\n"
"POT-Creation-Date: 2014-04-12 04:12+0200\n"
"PO-Revision-Date: 2014-04-12 04:12+0200\n"
"Last-Translator: Rolf Ahrenberg\n"
"Language-Team: Finnish <vdr@linuxtv.org>\n"
"Language: fi\n"
@@ -25,14 +25,8 @@ msgstr "NIT (0x40)"
msgid "SDT (0x42)"
msgstr "SDT (0x42)"
msgid "EIT (0x4E/0x4F)"
msgstr "EIT (0x4E/0x4F)"
msgid "EIT (0x5X)"
msgstr "EIT (0x5X)"
msgid "EIT (0x6X)"
msgstr "EIT (0x6X)"
msgid "EIT (0x4E/0x4F/0x5X/0x6X)"
msgstr "EIT (0x4E/0x4F/0x5X/0x6X)"
msgid "TDT (0x70)"
msgstr "TDT (0x70)"
@@ -43,8 +37,17 @@ msgstr "SAT>IP-laitteet"
msgid "SAT>IP Device"
msgstr "SAT>IP-laite"
msgid "Button$Scan"
msgstr "Kanavahaku"
msgid "Address"
msgstr "Osoite"
msgid "Model"
msgstr "Malli"
msgid "Description"
msgstr "Kuvaus"
msgid "Creation date"
msgstr "Luontiajankohta"
msgid "SAT>IP Information"
msgstr "SAT>IP-tiedot"
@@ -64,6 +67,35 @@ msgstr "Bitit/tavut"
msgid "SAT>IP information not available!"
msgstr "SAT>IP-tietoja ei saatavilla!"
msgid "off"
msgstr "ei käytössä"
msgid "low"
msgstr "matala"
msgid "normal"
msgstr "normaali"
msgid "high"
msgstr "korkea"
msgid "Operating mode"
msgstr "Laitteiden toimintatapa"
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 ""
"Määrittele toimintamoodi SAT>IP-laitteille:\n"
"ei käytössä - laitteet ovat pois käytöstä\n"
"matala - laitteet toimivat matalalla prioriteetilla\n"
"normaali - laitteet toimivat normaalilla prioriteetilla\n"
"korkea - laitteet toimivat korkealla prioriteetilla"
msgid "Enable EPG scanning"
msgstr "Käytä ohjelmaoppaan taustapäivitystä"
@@ -102,39 +134,3 @@ msgstr "Aktiiviset SAT>IP-laitteet:"
msgid "Help"
msgstr "Opaste"
msgid "off"
msgstr "pois"
msgid "on"
msgstr "päällä"
msgid "auto"
msgstr "auto"
msgid "SISO"
msgstr "SISO"
msgid "MISO"
msgstr "MISO"
msgid "Nid"
msgstr "Verkko-ID"
msgid "Tid"
msgstr "Lähete-ID"
msgid "Rid"
msgstr "Radio-ID"
msgid "SignalSource"
msgstr "Signaalin lähde"
msgid "PilotTones"
msgstr "Pilottiäänet"
msgid "T2SystemId"
msgstr "T2-järjestelmä"
msgid "SISO/MISO"
msgstr "SISO/MISO"

34
satip.c
View File

@@ -13,6 +13,10 @@
#include "discover.h"
#include "setup.h"
#if defined(LIBCURL_VERSION_NUM) && LIBCURL_VERSION_NUM < 0x072400
#warning "CURL version >= 0.7.36 is recommended"
#endif
#if defined(APIVERSNUM) && APIVERSNUM < 20000
#error "VDR-2.0.0 API version or greater is required!"
#endif
@@ -21,7 +25,7 @@
#define GITVERSION ""
#endif
const char VERSION[] = "0.0.1" GITVERSION;
const char VERSION[] = "0.2.3" GITVERSION;
static const char DESCRIPTION[] = trNOOP("SAT>IP Devices");
class cPluginSatip : public cPlugin {
@@ -194,7 +198,9 @@ bool cPluginSatip::SetupParse(const char *nameP, const char *valueP)
{
debug("cPluginSatip::%s()", __FUNCTION__);
// Parse your own setup parameters and store their values.
if (!strcasecmp(nameP, "EnableEITScan"))
if (!strcasecmp(nameP, "OperatingMode"))
SatipConfig.SetOperatingMode(atoi(valueP));
else if (!strcasecmp(nameP, "EnableEITScan"))
SatipConfig.SetEITScan(atoi(valueP));
else if (!strcasecmp(nameP, "DisabledFilters")) {
int DisabledFilters[SECTION_FILTER_TABLE_SIZE];
@@ -229,6 +235,8 @@ const char **cPluginSatip::SVDRPHelpPages(void)
" Lists active SAT>IP servers.\n",
"CONT\n"
" Shows SAT>IP device count.\n",
"OPER\n"
" Toggles operating mode of SAT>IP devices.\n",
NULL
};
return HelpPages;
@@ -284,6 +292,28 @@ cString cPluginSatip::SVDRPCommand(const char *commandP, const char *optionP, in
else if (strcasecmp(commandP, "CONT") == 0) {
return cString::sprintf("SAT>IP device count: %u", cSatipDevice::Count());
}
else if (strcasecmp(commandP, "OPER") == 0) {
cString mode;
SatipConfig.ToggleOperatingMode();
switch (SatipConfig.GetOperatingMode()) {
case cSatipConfig::eOperatingModeOff:
mode = "off";
break;
case cSatipConfig::eOperatingModeLow:
mode = "low";
break;
case cSatipConfig::eOperatingModeNormal:
mode = "normal";
break;
case cSatipConfig::eOperatingModeHigh:
mode = "high";
break;
default:
mode = "unknown";
break;
}
return cString::sprintf("SAT>IP operating mode: %s\n", *mode);
}
return NULL;
}

View File

@@ -17,6 +17,7 @@ cSatipSectionFilter::cSatipSectionFilter(int deviceIndexP, uint16_t pidP, uint8_
secLenM(0),
tsFeedpM(0),
pidM(pidP),
ringBufferM(new cRingBufferFrame(eDmxMaxSectionCount * eDmxMaxSectionSize)),
deviceIndexM(deviceIndexP)
{
//debug("cSatipSectionFilter::%s(%d, %d)", __FUNCTION__, deviceIndexM, pidM);
@@ -33,11 +34,11 @@ cSatipSectionFilter::cSatipSectionFilter(int deviceIndexP, uint16_t pidP, uint8_
filterMaskM[0] = maskP;
// Invert the filter
for (i = 0; i < DMX_MAX_FILTER_SIZE; ++i)
for (i = 0; i < eDmxMaxFilterSize; ++i)
filterValueM[i] ^= 0xFF;
uint8_t mask, mode, doneq = 0;
for (i = 0; i < DMX_MAX_FILTER_SIZE; ++i) {
for (i = 0; i < eDmxMaxFilterSize; ++i) {
mode = filterModeM[i];
mask = filterMaskM[i];
maskAndModeM[i] = (uint8_t)(mask & mode);
@@ -48,7 +49,7 @@ cSatipSectionFilter::cSatipSectionFilter(int deviceIndexP, uint16_t pidP, uint8_
// Create sockets
socketM[0] = socketM[1] = -1;
if (socketpair(AF_UNIX, SOCK_DGRAM, 0, socketM) != 0) {
if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, socketM) != 0) {
char tmp[64];
error("Opening section filter sockets failed (device=%d pid=%d): %s", deviceIndexM, pidM, strerror_r(errno, tmp, sizeof(tmp)));
}
@@ -70,6 +71,7 @@ cSatipSectionFilter::~cSatipSectionFilter()
if (tmp >= 0)
close(tmp);
secBufM = NULL;
DELETENULL(ringBufferM);
}
inline uint16_t cSatipSectionFilter::GetLength(const uint8_t *dataP)
@@ -89,7 +91,7 @@ int cSatipSectionFilter::Filter(void)
int i;
uint8_t neq = 0;
for (i = 0; i < DMX_MAX_FILTER_SIZE; ++i) {
for (i = 0; i < eDmxMaxFilterSize; ++i) {
uint8_t calcxor = (uint8_t)(filterValueM[i] ^ secBufM[i]);
if (maskAndModeM[i] & calcxor)
return 0;
@@ -99,13 +101,8 @@ int cSatipSectionFilter::Filter(void)
if (doneqM && !neq)
return 0;
// There is no data in the read socket, more can be written
if ((socketM[0] >= 0) && (socketM[1] >= 0) /*&& !select_single_desc(socketM[0], 0, false)*/) {
ssize_t len = write(socketM[1], secBufM, secLenM);
ERROR_IF(len < 0, "write()");
// Update statistics
AddSectionStatistic(len, 1);
}
if (ringBufferM && (secLenM > 0))
ringBufferM->Put(new cFrame(secBufM, secLenM));
}
return 0;
}
@@ -122,11 +119,11 @@ int cSatipSectionFilter::CopyDump(const uint8_t *bufP, uint8_t lenP)
{
uint16_t limit, seclen, n;
if (tsFeedpM >= DMX_MAX_SECFEED_SIZE)
if (tsFeedpM >= eDmxMaxSectionFeedSize)
return 0;
if (tsFeedpM + lenP > DMX_MAX_SECFEED_SIZE)
lenP = (uint8_t)(DMX_MAX_SECFEED_SIZE - tsFeedpM);
if (tsFeedpM + lenP > eDmxMaxSectionFeedSize)
lenP = (uint8_t)(eDmxMaxSectionFeedSize - tsFeedpM);
if (lenP <= 0)
return 0;
@@ -135,7 +132,7 @@ int cSatipSectionFilter::CopyDump(const uint8_t *bufP, uint8_t lenP)
tsFeedpM = uint16_t(tsFeedpM + lenP);
limit = tsFeedpM;
if (limit > DMX_MAX_SECFEED_SIZE)
if (limit > eDmxMaxSectionFeedSize)
return -1; // internal error should never happen
// Always set secbuf
@@ -143,7 +140,7 @@ int cSatipSectionFilter::CopyDump(const uint8_t *bufP, uint8_t lenP)
for (n = 0; secBufpM + 2 < limit; ++n) {
seclen = GetLength(secBufM);
if ((seclen <= 0) || (seclen > DMX_MAX_SECTION_SIZE) || ((seclen + secBufpM) > limit))
if ((seclen <= 0) || (seclen > eDmxMaxSectionSize) || ((seclen + secBufpM) > limit))
return 0;
secLenM = seclen;
if (pusiSeenM)
@@ -211,13 +208,33 @@ void cSatipSectionFilter::Process(const uint8_t* dataP)
}
}
bool 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();
// Update statistics
AddSectionStatistic(len, 1);
}
}
}
return result;
}
cSatipSectionFilterHandler::cSatipSectionFilterHandler(int deviceIndexP, unsigned int bufferLenP)
: cThread("SAT>IP section handler", true),
: cThread("SAT>IP section handler"),
ringBufferM(new cRingBufferLinear(bufferLenP, TS_SIZE, false, *cString::sprintf("SAT>IP SECTION HANDLER %d", deviceIndexP))),
mutexM(),
deviceIndexM(deviceIndexP),
processedM(false),
ringBufferM(new cRingBufferLinear(bufferLenP, TS_SIZE, false, *cString::sprintf("SAT>IP SECTION HANDLER %d", deviceIndexP)))
deviceIndexM(deviceIndexP)
{
debug("cSatipSectionFilterHandler::%s(%d)", __FUNCTION__, deviceIndexM);
@@ -238,8 +255,9 @@ cSatipSectionFilterHandler::cSatipSectionFilterHandler(int deviceIndexP, unsigne
cSatipSectionFilterHandler::~cSatipSectionFilterHandler()
{
debug("cSatipSectionFilterHandler::%s(%d)", __FUNCTION__, deviceIndexM);
Stop();
// Stop thread
if (Running())
Cancel(3);
DELETE_POINTER(ringBufferM);
// Destroy all filters
@@ -248,26 +266,28 @@ cSatipSectionFilterHandler::~cSatipSectionFilterHandler()
Delete(i);
}
bool cSatipSectionFilterHandler::Stop(void)
{
debug("cSatipSectionFilterHandler::%s(%d): entering", __FUNCTION__, deviceIndexM);
// Stop thread
if (Running())
Cancel(3);
return true;
}
void cSatipSectionFilterHandler::Action(void)
{
debug("cSatipSectionFilterHandler::%s(%d): entering", __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 (processedM) {
if (processed) {
ringBufferM->Del(TS_SIZE);
processedM = false;
processed = false;
}
uchar *p = ringBufferM->Get(len);
if (p && (len >= TS_SIZE)) {
@@ -289,7 +309,7 @@ void cSatipSectionFilterHandler::Action(void)
filtersM[i]->Process(p);
}
mutexM.Unlock();
processedM = true;
processed = true;
continue;
}
}

View File

@@ -8,9 +8,6 @@
#ifndef __SATIP_SECTIONFILTER_H
#define __SATIP_SECTIONFILTER_H
#ifdef __FreeBSD__
#include <sys/socket.h>
#endif // __FreeBSD__
#include <vdr/device.h>
#include "common.h"
@@ -18,10 +15,11 @@
class cSatipSectionFilter : public cSatipSectionStatistics {
private:
enum dmx_limits {
DMX_MAX_FILTER_SIZE = 18,
DMX_MAX_SECTION_SIZE = 4096,
DMX_MAX_SECFEED_SIZE = (DMX_MAX_SECTION_SIZE + TS_SIZE)
enum {
eDmxMaxFilterSize = 18,
eDmxMaxSectionCount = 64,
eDmxMaxSectionSize = 4096,
eDmxMaxSectionFeedSize = (eDmxMaxSectionSize + TS_SIZE)
};
int pusiSeenM;
@@ -29,21 +27,22 @@ private:
int doneqM;
uint8_t *secBufM;
uint8_t secBufBaseM[DMX_MAX_SECFEED_SIZE];
uint8_t secBufBaseM[eDmxMaxSectionFeedSize];
uint16_t secBufpM;
uint16_t secLenM;
uint16_t tsFeedpM;
uint16_t pidM;
cRingBufferFrame *ringBufferM;
int deviceIndexM;
int socketM[2];
uint8_t filterValueM[DMX_MAX_FILTER_SIZE];
uint8_t filterMaskM[DMX_MAX_FILTER_SIZE];
uint8_t filterModeM[DMX_MAX_FILTER_SIZE];
uint8_t filterValueM[eDmxMaxFilterSize];
uint8_t filterMaskM[eDmxMaxFilterSize];
uint8_t filterModeM[eDmxMaxFilterSize];
uint8_t maskAndModeM[DMX_MAX_FILTER_SIZE];
uint8_t maskAndNotModeM[DMX_MAX_FILTER_SIZE];
uint8_t maskAndModeM[eDmxMaxFilterSize];
uint8_t maskAndNotModeM[eDmxMaxFilterSize];
inline uint16_t GetLength(const uint8_t *dataP);
void New(void);
@@ -56,6 +55,7 @@ public:
cSatipSectionFilter(int deviceIndexP, uint16_t pidP, uint8_t tidP, uint8_t maskP);
virtual ~cSatipSectionFilter();
void Process(const uint8_t* dataP);
bool Send(void);
int GetFd(void) { return socketM[0]; }
uint16_t GetPid(void) const { return pidM; }
};
@@ -65,10 +65,9 @@ private:
enum {
eMaxSecFilterCount = 32
};
cRingBufferLinear *ringBufferM;
cMutex mutexM;
int deviceIndexM;
bool processedM;
cRingBufferLinear *ringBufferM;
cSatipSectionFilter *filtersM[eMaxSecFilterCount];
bool Delete(unsigned int indexP);
@@ -80,7 +79,6 @@ protected:
public:
cSatipSectionFilterHandler(int deviceIndexP, unsigned int bufferLenP);
virtual ~cSatipSectionFilterHandler();
bool Stop(void);
cString GetInformation(void);
int Open(u_short pidP, u_char tidP, u_char maskP);
void Close(int handleP);

177
server.c Normal file
View File

@@ -0,0 +1,177 @@
/*
* server.c: SAT>IP plugin for the Video Disk Recorder
*
* See the README file for copyright information and how to reach the author.
*
*/
#include <vdr/sources.h>
#include "common.h"
#include "server.h"
// --- cSatipServer -----------------------------------------------------------
cSatipServer::cSatipServer(const char *addressP, const char *descriptionP, const char *modelP)
: addressM(addressP),
descriptionM(descriptionP),
modelM(modelP),
modelTypeM(eSatipModelTypeMask),
useCountM(0),
createdM(time(NULL)),
lastSeenM(0)
{
memset(modelCountM, 0, sizeof(modelCountM));
if (isempty(*modelM))
modelM = "DVBS-1";
char *s, *p = strdup(*modelM);
char *r = strtok_r(p, ",", &s);
while (r) {
if (strstr(r, "DVBS2")) {
modelTypeM |= cSatipServer::eSatipModelTypeDVBS2;
if (char *c = strstr(r, "-"))
modelCountM[eSatipModuleDVBS2] = atoi(++c);
else
modelCountM[eSatipModuleDVBS2] = 1;
}
if (strstr(r, "DVBT2")) {
modelTypeM |= cSatipServer::eSatipModelTypeDVBT | cSatipServer::eSatipModelTypeDVBT2;
if (char *c = strstr(r, "-"))
modelCountM[eSatipModuleDVBT2] = atoi(++c);
else
modelCountM[eSatipModuleDVBT2] = 1;
// Add model quirks here
if (strstr(*addressM, "OctopusNet"))
modelTypeM |= cSatipServer::eSatipModelTypeDVBC;
}
if (strstr(r, "DVBT")) {
modelTypeM |= cSatipServer::eSatipModelTypeDVBT;
if (char *c = strstr(r, "-"))
modelCountM[eSatipModuleDVBT] = atoi(++c);
else
modelCountM[eSatipModuleDVBT] = 1;
// Add model quirks here
if (strstr(*addressM, "OctopusNet"))
modelTypeM |= cSatipServer::eSatipModelTypeDVBC;
}
r = strtok_r(NULL, ",", &s);
}
free(p);
}
cSatipServer::~cSatipServer()
{
}
int cSatipServer::Compare(const cListObject &listObjectP) const
{
const cSatipServer *s = (const cSatipServer *)&listObjectP;
return strcasecmp(*addressM, *s->addressM);
}
void cSatipServer::Use(bool onOffP)
{
if (onOffP)
++useCountM;
else
--useCountM;
}
// --- cSatipServers ----------------------------------------------------------
cSatipServer *cSatipServers::Find(cSatipServer *serverP)
{
for (cSatipServer *s = First(); s; s = Next(s)) {
if (s == serverP)
return s;
}
return NULL;
}
cSatipServer *cSatipServers::Find(int sourceP, int systemP)
{
cSatipServer *result = NULL;
int model = 0;
if (cSource::IsType(sourceP, 'S'))
model |= cSatipServer::eSatipModelTypeDVBS2;
else if (cSource::IsType(sourceP, 'T')) {
if (systemP < 0)
model |= cSatipServer::eSatipModelTypeDVBT2 | cSatipServer::eSatipModelTypeDVBT;
else
model |= systemP ? cSatipServer::eSatipModelTypeDVBT2 : cSatipServer::eSatipModelTypeDVBT;
}
else if (cSource::IsType(sourceP, 'C'))
model |= cSatipServer::eSatipModelTypeDVBC;
for (cSatipServer *s = First(); s; s = Next(s)) {
if (s->Match(model)) {
result = s;
if (!s->Used()) {
break;
}
}
}
return result;
}
cSatipServer *cSatipServers::Update(cSatipServer *serverP)
{
for (cSatipServer *s = First(); s; s = Next(s)) {
if (s->Compare(*serverP) == 0) {
s->Update();
return s;
}
}
return NULL;
}
void cSatipServers::Use(cSatipServer *serverP, bool onOffP)
{
for (cSatipServer *s = First(); s; s = Next(s)) {
if (s == serverP) {
s->Use(onOffP);
break;
}
}
}
void cSatipServers::Cleanup(uint64_t intervalMsP)
{
for (cSatipServer *s = First(); s; s = Next(s)) {
if (!intervalMsP || (s->LastSeen() > intervalMsP)) {
info("Removing device %s (%s %s)", s->Description(), s->Address(), s->Model());
Del(s);
}
}
}
cString cSatipServers::GetString(cSatipServer *serverP)
{
cString list = "";
for (cSatipServer *s = First(); s; s = Next(s)) {
if (s == serverP) {
list = cString::sprintf("%s|%s|%s", s->Address(), s->Model(), s->Description());
break;
}
}
return list;
}
cString cSatipServers::List(void)
{
cString list = "";
for (cSatipServer *s = First(); s; s = Next(s))
list = cString::sprintf("%s%s|%s|%s\n", *list, s->Address(), s->Model(), s->Description());
return list;
}
int cSatipServers::NumProvidedSystems(void)
{
int count = 0;
for (cSatipServer *s = First(); s; s = Next(s)) {
// DVB-S*: qpsk, 8psk
count += s->Satellite() * 4;
// DVB-T*: qpsk, qam16, qam64, qam256
count += (s->Terrestrial2() ? s->Terrestrial2() : s->Terrestrial()) * 4;
}
return count;
}

71
server.h Normal file
View File

@@ -0,0 +1,71 @@
/*
* server.h: SAT>IP plugin for the Video Disk Recorder
*
* See the README file for copyright information and how to reach the author.
*
*/
#ifndef __SATIP_SERVER_H
#define __SATIP_SERVER_H
// --- cSatipServer -----------------------------------------------------------
class cSatipServer : public cListObject {
private:
enum eSatipModule {
eSatipModuleDVBS2 = 0,
eSatipModuleDVBT,
eSatipModuleDVBT2,
eSatipModuleCount
};
cString addressM;
cString descriptionM;
cString modelM;
int modelCountM[eSatipModuleCount];
int modelTypeM;
int useCountM;
time_t createdM;
cTimeMs lastSeenM;
public:
enum eSatipModelType {
eSatipModelTypeDVBS2 = 0x01,
eSatipModelTypeDVBT = 0x02,
eSatipModelTypeDVBT2 = 0x04,
eSatipModelTypeDVBC = 0x08,
eSatipModelTypeMask = 0x0F
};
cSatipServer(const char *addressP, const char *descriptionP, const char *modelP);
virtual ~cSatipServer();
virtual int Compare(const cListObject &listObjectP) const;
void Use(bool onOffP);
bool Used(void) { return !!useCountM; }
const char *Description() { return *descriptionM; }
const char *Address() { return *addressM; }
const char *Model(void) { return modelM; }
int ModelType(void) { return modelTypeM; }
bool Match(int modelP) { return ((modelP & eSatipModelTypeMask) & modelTypeM); }
int Cable() { return Match(eSatipModelTypeDVBC) ? (Match(eSatipModelTypeDVBT2) ? modelCountM[eSatipModuleDVBT2] : modelCountM[eSatipModuleDVBT]) : 0; } // an ugly hack
int Satellite() { return Match(eSatipModelTypeDVBS2) ? modelCountM[eSatipModuleDVBS2] : 0; }
int Terrestrial() { return Match(eSatipModelTypeDVBT) ? modelCountM[eSatipModuleDVBT] : 0; }
int Terrestrial2() { return Match(eSatipModelTypeDVBT2) ? modelCountM[eSatipModuleDVBT2] : 0; }
void Update(void) { lastSeenM.Set(); }
uint64_t LastSeen(void) { return lastSeenM.Elapsed(); }
time_t Created(void) { return createdM; }
};
// --- cSatipServers ----------------------------------------------------------
class cSatipServers : public cList<cSatipServer> {
public:
cSatipServer *Find(cSatipServer *serverP);
cSatipServer *Find(int sourceP, int systemP);
cSatipServer *Update(cSatipServer *serverP);
void Use(cSatipServer *serverP, bool onOffP);
void Cleanup(uint64_t intervalMsP = 0);
cString GetString(cSatipServer *serverP);
cString List(void);
int NumProvidedSystems(void);
};
#endif // __SATIP_SERVER_H

118
setup.c
View File

@@ -14,68 +14,61 @@
#include "discover.h"
#include "setup.h"
// --- cSatipMenuScan ---------------------------------------------------------
// --- cSatipServerInfo -------------------------------------------------------
class cSatipMenuScan : public cOsdMenu
class cSatipServerInfo : public cOsdMenu
{
private:
enum {
INFO_TIMEOUT_MS = 2000
};
cString textM;
cTimeMs timeoutM;
cString addressM;
cString modelM;
cString descriptionM;
uint64_t createdM;
void Setup(void);
public:
cSatipMenuScan(cSatipServer *serverP);
virtual ~cSatipMenuScan();
virtual void Display(void);
cSatipServerInfo(cSatipServer *serverP);
virtual ~cSatipServerInfo();
virtual eOSState ProcessKey(eKeys keyP);
};
cSatipMenuScan::cSatipMenuScan(cSatipServer *serverP)
: cOsdMenu(tr("SAT>IP Device")),
textM("")
cSatipServerInfo::cSatipServerInfo(cSatipServer *serverP)
: cOsdMenu(tr("SAT>IP Device"), 20),
addressM(serverP ? serverP->Address() : "---"),
modelM(serverP ? serverP->Model() : "---"),
descriptionM(serverP ? serverP->Description() : "---"),
createdM(serverP ? serverP->Created() : 0)
{
SetMenuCategory(mcText);
if (serverP) {
if (serverP->Model())
textM = cString::sprintf("%s\nModel:\t%s", *textM, serverP->Model());
if (serverP->Address())
textM = cString::sprintf("%s\nAddress:\t%s", *textM, serverP->Address());
if (serverP->Description())
textM = cString::sprintf("%s\nDescription:\t%s", *textM, serverP->Description());
}
SetHelp(tr("Button$Scan"), NULL, NULL, NULL);
SetMenuCategory(mcSetupPlugins);
Setup();
SetHelp(NULL, NULL, NULL, NULL);
}
cSatipMenuScan::~cSatipMenuScan()
cSatipServerInfo::~cSatipServerInfo()
{
}
void cSatipMenuScan::Display(void)
void cSatipServerInfo::Setup(void)
{
cOsdMenu::Display();
DisplayMenu()->SetText(textM, true);
if (*textM)
cStatus::MsgOsdTextItem(textM);
Add(new cOsdItem(cString::sprintf("%s:\t%s", tr("Address"), *addressM), osUnknown, false));
Add(new cOsdItem(cString::sprintf("%s:\t%s", tr("Model"), *modelM), osUnknown, false));
Add(new cOsdItem(cString::sprintf("%s:\t%s", tr("Description"), *descriptionM), osUnknown, false));
Add(new cOsdItem(cString::sprintf("%s:\t%s", tr("Creation date"), *DayDateTime(createdM)), osUnknown, false));
}
eOSState cSatipMenuScan::ProcessKey(eKeys keyP)
eOSState cSatipServerInfo::ProcessKey(eKeys keyP)
{
eOSState state = cOsdMenu::ProcessKey(keyP);
if (state == osUnknown) {
switch (keyP) {
case kOk: return osBack;
case kRed:
default: state = osContinue;
break;
case kOk: state = osBack; break;
default: state = osContinue; break;
}
}
return state;
}
// --- cSatipMenuInfo ---------------------------------------------------------
// --- cSatipServerItem -------------------------------------------------------
class cSatipServerItem : public cOsdItem {
private:
@@ -107,7 +100,7 @@ class cSatipMenuInfo : public cOsdMenu
{
private:
enum {
INFO_TIMEOUT_MS = 2000
eInfoTimeoutMs = 2000
};
cString textM;
cTimeMs timeoutM;
@@ -128,7 +121,7 @@ cSatipMenuInfo::cSatipMenuInfo()
pageM(SATIP_DEVICE_INFO_GENERAL)
{
SetMenuCategory(mcText);
timeoutM.Set(INFO_TIMEOUT_MS);
timeoutM.Set(eInfoTimeoutMs);
UpdateInfo();
SetHelp(tr("General"), tr("Pids"), tr("Filters"), tr("Bits/bytes"));
}
@@ -145,7 +138,7 @@ void cSatipMenuInfo::UpdateInfo()
else
textM = cString(tr("SAT>IP information not available!"));
Display();
timeoutM.Set(INFO_TIMEOUT_MS);
timeoutM.Set(eInfoTimeoutMs);
}
void cSatipMenuInfo::Display(void)
@@ -203,10 +196,15 @@ eOSState cSatipMenuInfo::ProcessKey(eKeys keyP)
cSatipPluginSetup::cSatipPluginSetup()
: deviceCountM(0),
operatingModeM(SatipConfig.GetOperatingMode()),
eitScanM(SatipConfig.GetEITScan()),
numDisabledFiltersM(SatipConfig.GetDisabledFiltersCount())
{
debug("cSatipPluginSetup::%s()", __FUNCTION__);
operatingModeTextsM[cSatipConfig::eOperatingModeOff] = tr("off");
operatingModeTextsM[cSatipConfig::eOperatingModeLow] = tr("low");
operatingModeTextsM[cSatipConfig::eOperatingModeNormal] = tr("normal");
operatingModeTextsM[cSatipConfig::eOperatingModeHigh] = tr("high");
if (numDisabledFiltersM > SECTION_FILTER_TABLE_SIZE)
numDisabledFiltersM = SECTION_FILTER_TABLE_SIZE;
for (int i = 0; i < SECTION_FILTER_TABLE_SIZE; ++i) {
@@ -215,7 +213,7 @@ cSatipPluginSetup::cSatipPluginSetup()
}
SetMenuCategory(mcSetupPlugins);
Setup();
SetHelp(NULL, NULL, NULL, trVDR("Button$Info"));
SetHelp(trVDR("Button$Scan"), NULL, NULL, trVDR("Button$Info"));
}
void cSatipPluginSetup::Setup(void)
@@ -225,17 +223,21 @@ void cSatipPluginSetup::Setup(void)
Clear();
helpM.Clear();
Add(new cMenuEditBoolItem(tr("Enable EPG scanning"), &eitScanM));
helpM.Append(tr("Define whether the EPG background scanning shall be used.\n\nThis setting disables the automatic EIT scanning functionality for all SAT>IP devices."));
Add(new cMenuEditStraItem(tr("Operating mode"), &operatingModeM, ELEMENTS(operatingModeTextsM), operatingModeTextsM));
helpM.Append(tr("Define the used operating mode for all SAT>IP devices:\n\noff - devices are disabled\nlow - devices are working at the lowest priority\nnormal - devices are working within normal parameters\nhigh - devices are working at the highest priority"));
Add(new cMenuEditIntItem(tr("Disabled filters"), &numDisabledFiltersM, 0, SECTION_FILTER_TABLE_SIZE, tr("none")));
helpM.Append(tr("Define number of section filters to be disabled.\n\nCertain section filters might cause some unwanted behaviour to VDR such as time being falsely synchronized. By black-listing the filters here useful section data can be left intact for VDR to process."));
if (operatingModeM) {
Add(new cMenuEditBoolItem(tr("Enable EPG scanning"), &eitScanM));
helpM.Append(tr("Define whether the EPG background scanning shall be used.\n\nThis setting disables the automatic EIT scanning functionality for all SAT>IP devices."));
for (int i = 0; i < numDisabledFiltersM; ++i) {
Add(new cMenuEditStraItem(*cString::sprintf(" %s %d", tr("Filter"), i + 1), &disabledFilterIndexesM[i], SECTION_FILTER_TABLE_SIZE, disabledFilterNamesM));
helpM.Append(tr("Define an ill-behaving filter to be blacklisted."));
}
Add(new cMenuEditIntItem(tr("Disabled filters"), &numDisabledFiltersM, 0, SECTION_FILTER_TABLE_SIZE, tr("none")));
helpM.Append(tr("Define number of section filters to be disabled.\n\nCertain section filters might cause some unwanted behaviour to VDR such as time being falsely synchronized. By black-listing the filters here useful section data can be left intact for VDR to process."));
for (int i = 0; i < numDisabledFiltersM; ++i) {
Add(new cMenuEditStraItem(*cString::sprintf(" %s %d", tr("Filter"), i + 1), &disabledFilterIndexesM[i], SECTION_FILTER_TABLE_SIZE, disabledFilterNamesM));
helpM.Append(tr("Define an ill-behaving filter to be blacklisted."));
}
}
Add(new cOsdItem(tr("Active SAT>IP devices:"), osUnknown, false));
helpM.Append("");
@@ -250,15 +252,23 @@ void cSatipPluginSetup::Setup(void)
Display();
}
eOSState cSatipPluginSetup::ChannelScan(void)
eOSState cSatipPluginSetup::DeviceScan(void)
{
debug("cSatipPluginSetup::%s()", __FUNCTION__);
cSatipDiscover::GetInstance()->TriggerScan();
return osContinue;
}
eOSState cSatipPluginSetup::DeviceInfo(void)
{
debug("cSatipPluginSetup::%s()", __FUNCTION__);
if (HasSubMenu() || Count() == 0)
return osContinue;
cSatipServerItem *item = reinterpret_cast<cSatipServerItem *>(Get(Current()));
if (item && cSatipDiscover::GetInstance()->IsValidServer(item->Server()))
return AddSubMenu(new cSatipMenuScan(item->Server()));
if (item && !!cSatipDiscover::GetInstance()->GetServer(item->Server()))
return AddSubMenu(new cSatipServerInfo(item->Server()));
return osContinue;
}
@@ -275,16 +285,18 @@ eOSState cSatipPluginSetup::ShowInfo(void)
eOSState cSatipPluginSetup::ProcessKey(eKeys keyP)
{
bool hadSubMenu = HasSubMenu();
int oldOperatingMode = operatingModeM;
int oldNumDisabledFilters = numDisabledFiltersM;
eOSState state = cMenuSetupPage::ProcessKey(keyP);
// Ugly hack with hardcoded '#' character :(
const char *p = Get(Current())->Text();
if (!hadSubMenu && !HasSubMenu() && (*p == '#') && (keyP == kOk))
return ChannelScan();
return DeviceInfo();
if (state == osUnknown) {
switch (keyP) {
case kRed: return DeviceScan();
case kBlue: return ShowInfo();
case kInfo: if (Current() < helpM.Size())
return AddSubMenu(new cMenuText(cString::sprintf("%s - %s '%s'", tr("Help"), trVDR("Plugin"), PLUGIN_NAME_I18N), helpM[Current()]));
@@ -295,7 +307,7 @@ eOSState cSatipPluginSetup::ProcessKey(eKeys keyP)
if ((keyP == kNone) && (cSatipDiscover::GetInstance()->GetServers()->Count() != deviceCountM))
Setup();
if ((keyP != kNone) && (numDisabledFiltersM != oldNumDisabledFilters)) {
if ((keyP != kNone) && ((numDisabledFiltersM != oldNumDisabledFilters) || (operatingModeM != oldOperatingMode))) {
while ((numDisabledFiltersM < oldNumDisabledFilters) && (oldNumDisabledFilters > 0))
disabledFilterIndexesM[--oldNumDisabledFilters] = -1;
Setup();
@@ -326,9 +338,11 @@ void cSatipPluginSetup::StoreFilters(const char *nameP, int *valuesP)
void cSatipPluginSetup::Store(void)
{
// Store values into setup.conf
SetupStore("OperatingMode", operatingModeM);
SetupStore("EnableEITScan", eitScanM);
StoreFilters("DisabledFilters", disabledFilterIndexesM);
// Update global config
SatipConfig.SetOperatingMode(operatingModeM);
SatipConfig.SetEITScan(eitScanM);
for (int i = 0; i < SECTION_FILTER_TABLE_SIZE; ++i)
SatipConfig.SetDisabledFilters(i, disabledFilterIndexesM[i]);

View File

@@ -16,13 +16,16 @@ class cSatipPluginSetup : public cMenuSetupPage
{
private:
int deviceCountM;
int operatingModeM;
const char *operatingModeTextsM[cSatipConfig::eOperatingModeCount];
int eitScanM;
int numDisabledFiltersM;
int disabledFilterIndexesM[SECTION_FILTER_TABLE_SIZE];
const char *disabledFilterNamesM[SECTION_FILTER_TABLE_SIZE];
cVector<const char*> helpM;
eOSState ChannelScan(void);
eOSState DeviceScan(void);
eOSState DeviceInfo(void);
eOSState ShowInfo(void);
void Setup(void);
void StoreFilters(const char *nameP, int *valuesP);

View File

@@ -20,7 +20,10 @@
cSatipSocket::cSatipSocket()
: socketPortM(0),
socketDescM(-1)
socketDescM(-1),
lastErrorReportM(0),
packetErrorsM(0),
sequenceNumberM(-1)
{
debug("cSatipSocket::%s()", __FUNCTION__);
memset(&sockAddrM, 0, sizeof(sockAddrM));
@@ -72,8 +75,14 @@ void cSatipSocket::Close(void)
close(socketDescM);
socketDescM = -1;
socketPortM = 0;
sequenceNumberM = -1;
memset(&sockAddrM, 0, sizeof(sockAddrM));
}
if (packetErrorsM) {
info("detected %d RTP packet errors", packetErrorsM);
packetErrorsM = 0;
lastErrorReportM = time(NULL);
}
}
bool cSatipSocket::Flush(void)
@@ -150,6 +159,21 @@ int cSatipSocket::ReadVideo(unsigned char *bufferAddrP, unsigned int bufferLenP)
unsigned int cc = bufferAddrP[0] & 0x0F;
// Payload type: MPEG2 TS = 33
//unsigned int pt = bufferAddrP[1] & 0x7F;
// Sequence number
int seq = ((bufferAddrP[2] & 0xFF) << 8) | (bufferAddrP[3] & 0xFF);
if ((((sequenceNumberM + 1) % 0xFFFF) == 0) && (seq == 0xFFFF))
sequenceNumberM = -1;
else if ((sequenceNumberM >= 0) && (((sequenceNumberM + 1) % 0xFFFF) != seq)) {
packetErrorsM++;
if (time(NULL) - lastErrorReportM > eReportIntervalS) {
info("detected %d RTP packet errors", packetErrorsM);
packetErrorsM = 0;
lastErrorReportM = time(NULL);
}
sequenceNumberM = seq;
}
else
sequenceNumberM = seq;
// Header lenght
unsigned int headerlen = (3 + cc) * (unsigned int)sizeof(uint32_t);
// Check if extension

View File

@@ -12,9 +12,15 @@
class cSatipSocket {
private:
enum {
eReportIntervalS = 300 // in seconds
};
int socketPortM;
int socketDescM;
struct sockaddr_in sockAddrM;
time_t lastErrorReportM;
int packetErrorsM;
int sequenceNumberM;
public:
cSatipSocket();

384
source.c
View File

@@ -1,384 +0,0 @@
/*
* source.c: SAT>IP plugin for the Video Disk Recorder
*
* See the README file for copyright information and how to reach the author.
*
*/
#include <ctype.h>
#include "common.h"
#include "source.h"
// --- cSatipParameterMaps ----------------------------------------------------
static const tSatipParameterMap SatipBandwidthValues[] = {
{ 5, "5 MHz", "bw=5" },
{ 6, "6 MHz", "bw=6" },
{ 7, "7 MHz", "bw=7" },
{ 8, "8 MHz", "bw=8" },
{ 10, "10 MHz", "bw=10" },
{ 1712, "1.712 MHz", "bw=1.712" },
{ -1, NULL, NULL }
};
static const tSatipParameterMap SatipPilotTonesValues[] = {
{ 0, trNOOP("off"), "plts=off" },
{ 1, trNOOP("on"), "plts=on" },
{ 999, trNOOP("auto"), "" },
{ -1, NULL, NULL }
};
static const tSatipParameterMap SatipSisoMisoValues[] = {
{ 0, trNOOP("SISO"), "sm=0" },
{ 1, trNOOP("MISO"), "sm=1" },
{ 999, trNOOP("auto"), "" },
{ -1, NULL, NULL }
};
static const tSatipParameterMap SatipCodeRateValues[] = {
{ 0, trNOOP("none"), "" },
{ 12, "1/2", "fec=12" },
{ 23, "2/3", "fec=23" },
{ 34, "3/4", "fec=34" },
{ 35, "3/5", "fec=35" },
{ 45, "4/5", "fec=45" },
{ 56, "5/6", "fec=56" },
{ 78, "7/8", "fec=78" },
{ 89, "8/9", "fec=89" },
{ 910, "9/10", "fec=910" },
{ 999, trNOOP("auto"), "" },
{ -1, NULL, NULL }
};
static const tSatipParameterMap SatipModulationValues[] = {
{ 2, "QPSK", "mtype=qpsk" },
{ 5, "8PSK", "mtype=8psk" },
{ 16, "QAM16", "mtype=16qam" },
{ 64, "QAM64", "mtype=64qam" },
{ 256, "QAM256", "mtype=256qam" },
{ 999, trNOOP("auto"), "" },
{ -1, NULL, NULL }
};
static const tSatipParameterMap SatipSystemValuesSat[] = {
{ 0, "DVB-S", "msys=dvbs" },
{ 1, "DVB-S2", "msys=dvbs2" },
{ -1, NULL, NULL }
};
static const tSatipParameterMap SatipSystemValuesTerr[] = {
{ 0, "DVB-T", "msys=dvbt" },
{ 1, "DVB-T2", "msys=dvbt2" },
{ -1, NULL, NULL }
};
static const tSatipParameterMap SatipTransmissionValues[] = {
{ 1, "1K", "tmode=1k" },
{ 2, "2K", "tmode=2k" },
{ 4, "4K", "tmode=4k" },
{ 8, "8K", "tmode=8k" },
{ 16, "16K", "tmode=16k" },
{ 32, "32K", "tmode=32k" },
{ 999, trNOOP("auto"), "" },
{ -1, NULL, NULL }
};
static const tSatipParameterMap SatipGuardValues[] = {
{ 4, "1/4", "gi=14" },
{ 8, "1/8", "gi=18" },
{ 16, "1/16", "gi=116" },
{ 32, "1/32", "gi=132" },
{ 128, "1/128", "gi=1128" },
{ 19128, "19/128", "gi=19128" },
{ 19256, "19/256", "gi=19256" },
{ 999, trNOOP("auto"), "" },
{ -1, NULL, NULL }
};
static const tSatipParameterMap SatipRollOffValues[] = {
{ 0, trNOOP("auto"), "" },
{ 20, "0.20", "ro=0.20" },
{ 25, "0.25", "ro=0.25" },
{ 35, "0.35", "ro=0.35" },
{ -1, NULL, NULL }
};
static int SatipUserIndex(int valueP, const tSatipParameterMap *mapP)
{
const tSatipParameterMap *map = mapP;
while (map && map->userValue != -1) {
if (map->userValue == valueP)
return map - mapP;
map++;
}
return -1;
}
static int SatipMapToUser(int valueP, const tSatipParameterMap *mapP, const char **strP)
{
int n = SatipUserIndex(valueP, mapP);
if (n >= 0) {
if (strP)
*strP = tr(mapP[n].userString);
return mapP[n].userValue;
}
return -1;
}
// --- cMenuEditSatipItem -----------------------------------------------------
class cMenuEditSatipItem : public cMenuEditItem {
protected:
int *valueM;
const tSatipParameterMap *mapM;
const char *zeroStringM;
virtual void Set(void);
public:
cMenuEditSatipItem(const char *nameP, int *valueP, const tSatipParameterMap *mapP, const char *zeroStringP = NULL);
virtual eOSState ProcessKey(eKeys keyP);
};
cMenuEditSatipItem::cMenuEditSatipItem(const char *nameP, int *valueP, const tSatipParameterMap *mapP, const char *zeroStringP)
: cMenuEditItem(nameP)
{
valueM = valueP;
mapM = mapP;
zeroStringM = zeroStringP;
Set();
}
void cMenuEditSatipItem::Set(void)
{
const char *s = NULL;
int n = SatipMapToUser(*valueM, mapM, &s);
if (n == 0 && zeroStringM)
SetValue(zeroStringM);
else if (n >= 0) {
if (s)
SetValue(s);
else {
char buf[16];
snprintf(buf, sizeof(buf), "%d", n);
SetValue(buf);
}
}
else
SetValue("???");
}
eOSState cMenuEditSatipItem::ProcessKey(eKeys keyP)
{
eOSState state = cMenuEditItem::ProcessKey(keyP);
if (state == osUnknown) {
int newValue = *valueM;
int n = SatipUserIndex(*valueM, mapM);
if (NORMALKEY(keyP) == kLeft) { // TODO might want to increase the delta if repeated quickly?
if (n-- > 0)
newValue = mapM[n].userValue;
}
else if (NORMALKEY(keyP) == kRight) {
if (mapM[++n].userValue >= 0)
newValue = mapM[n].userValue;
}
else
return state;
if (newValue != *valueM) {
*valueM = newValue;
Set();
}
state = osContinue;
}
return state;
}
// --- cSatipTransponderParameters --------------------------------------------
cSatipTransponderParameters::cSatipTransponderParameters(const char *parametersP)
: polarizationM('H'),
bandwidthM(8),
coderateHM(0),
systemM(0),
modulationM(999),
transmissionM(8),
guardM(999),
rollOffM(0),
streamIdM(0),
t2SystemIdM(0),
sisoMisoM(999),
pilotTonesM(0),
signalSourceM(1)
{
Parse(parametersP);
}
int cSatipTransponderParameters::PrintParameter(char *ptrP, char nameP, int valueP) const
{
return (valueP >= 0 && valueP != 999) ? sprintf(ptrP, "%c%d", nameP, valueP) : 0;
}
int cSatipTransponderParameters::PrintString(char *ptrP, int valueP, const tSatipParameterMap *mapP)
{
int n = SatipUserIndex(valueP, mapP);
return (n >= 0) ? sprintf(ptrP, "&%s", tr(mapP[n].satipString)) : 0;
}
cString cSatipTransponderParameters::UrlParameters(char typeP)
{
char buffer[255];
char *q = buffer;
*q = 0;
#define ST(s) if (strchr(s, typeP) && (strchr(s, '0' + systemM + 1) || strchr(s, '*')))
ST("Z *") q += sprintf(q, "&src=%d", signalSourceM);
ST("Z *") q += sprintf(q, "&pol=%c", tolower(polarizationM));
ST(" Y2") q += sprintf(q, "&plp=%d", streamIdM);
ST(" Y2") q += sprintf(q, "&t2id=%d", t2SystemIdM);
ST(" Y*") q += PrintString(q, bandwidthM, SatipBandwidthValues);
ST(" Y*") q += PrintString(q, guardM, SatipGuardValues);
ST("ZY*") q += PrintString(q, coderateHM, SatipCodeRateValues);
ST("Z 2") q += PrintString(q, pilotTonesM, SatipPilotTonesValues);
ST("Z 2") q += PrintString(q, modulationM, SatipModulationValues);
ST(" Y*") q += PrintString(q, modulationM, SatipModulationValues);
ST("Z 2") q += PrintString(q, rollOffM, SatipRollOffValues);
ST("Z *") q += PrintString(q, systemM, SatipSystemValuesSat);
ST(" Y*") q += PrintString(q, systemM, SatipSystemValuesTerr);
ST(" Y*") q += PrintString(q, transmissionM, SatipTransmissionValues);
ST(" Y2") q += PrintString(q, sisoMisoM, SatipSisoMisoValues);
#undef ST
return buffer;
}
cString cSatipTransponderParameters::ToString(char typeP) const
{
char buffer[64];
char *q = buffer;
*q = 0;
#define ST(s) if (strchr(s, typeP) && (strchr(s, '0' + systemM + 1) || strchr(s, '*')))
ST("Z *") q += sprintf(q, "%c", polarizationM);
ST(" Y*") q += PrintParameter(q, 'B', bandwidthM);
ST("ZY*") q += PrintParameter(q, 'C', coderateHM);
ST(" Y*") q += PrintParameter(q, 'G', guardM);
ST("Z 2") q += PrintParameter(q, 'M', modulationM);
ST(" Y*") q += PrintParameter(q, 'M', modulationM);
ST("Z 2") q += PrintParameter(q, 'N', pilotTonesM);
ST("Z 2") q += PrintParameter(q, 'O', rollOffM);
ST(" Y2") q += PrintParameter(q, 'P', streamIdM);
ST(" Y2") q += PrintParameter(q, 'Q', t2SystemIdM);
ST("ZY*") q += PrintParameter(q, 'S', systemM);
ST(" Y*") q += PrintParameter(q, 'T', transmissionM);
ST(" Y2") q += PrintParameter(q, 'X', sisoMisoM);
ST("Z *") q += PrintParameter(q, 'Z', signalSourceM);
#undef ST
return buffer;
}
const char *cSatipTransponderParameters::ParseParameter(const char *strP, int &valueP)
{
if (*++strP) {
char *p = NULL;
errno = 0;
int n = strtol(strP, &p, 10);
if (!errno && p != strP) {
valueP = n;
if (valueP >= 0)
return p;
}
}
error("invalid value for parameter '%c'", *(strP - 1));
return NULL;
}
bool cSatipTransponderParameters::Parse(const char *strP)
{
while (strP && *strP) {
int ignoreThis;
switch (toupper(*strP)) {
case 'B': strP = ParseParameter(strP, bandwidthM); break;
case 'C': strP = ParseParameter(strP, coderateHM); break;
case 'G': strP = ParseParameter(strP, guardM); break;
case 'H': polarizationM = 'H'; strP++; break;
case 'L': polarizationM = 'L'; strP++; break;
case 'M': strP = ParseParameter(strP, modulationM); break;
case 'N': strP = ParseParameter(strP, pilotTonesM); break;
case 'O': strP = ParseParameter(strP, rollOffM); break;
case 'P': strP = ParseParameter(strP, streamIdM); break;
case 'Q': strP = ParseParameter(strP, t2SystemIdM); break;
case 'R': polarizationM = 'R'; strP++; break;
case 'S': strP = ParseParameter(strP, systemM); break;
case 'T': strP = ParseParameter(strP, transmissionM); break;
case 'V': polarizationM = 'V'; strP++; break;
case 'X': strP = ParseParameter(strP, sisoMisoM); break;
case 'Z': strP = ParseParameter(strP, signalSourceM); break;
case 'D': strP = ParseParameter(strP, ignoreThis); break; /* silently ignore coderate low priority */
case 'I': strP = ParseParameter(strP, ignoreThis); break; /* silently ignore inversion */
case 'Y': strP = ParseParameter(strP, ignoreThis); break; /* silently ignore hierarchy */
default: esyslog("ERROR: unknown parameter key '%c'", *strP);
return false;
}
}
return true;
}
// --- cSatipSourceParam ------------------------------------------------------
cSatipSourceParam::cSatipSourceParam(char sourceP, const char *descriptionP)
: cSourceParam(sourceP, descriptionP),
paramM(0),
nidM(0),
tidM(0),
ridM(0),
srateM(0),
dataM(),
stpM()
{
debug("cSatipSourceParam::%s(%c, %s)", __FUNCTION__, sourceP, descriptionP);
}
void cSatipSourceParam::SetData(cChannel *channelP)
{
debug("cSatipSourceParam::%s(%s)", __FUNCTION__, channelP->Parameters());
dataM = *channelP;
nidM = dataM.Nid();
tidM = dataM.Tid();
ridM = dataM.Rid();
srateM = dataM.Srate();
stpM.Parse(dataM.Parameters());
paramM = 0;
}
void cSatipSourceParam::GetData(cChannel *channelP)
{
debug("cSatipSourceParam::%s(%s)", __FUNCTION__, channelP->Parameters());
channelP->SetTransponderData(channelP->Source(), channelP->Frequency(), srateM, stpM.ToString(Source()), true);
channelP->SetId(nidM, tidM, channelP->Sid(), ridM);
}
cOsdItem *cSatipSourceParam::GetOsdItem(void)
{
char type = Source();
const tSatipParameterMap *SatipSystemValues = type == 'Z' ? SatipSystemValuesSat : SatipSystemValuesTerr;
#define ST(s) if (strchr(s, type))
switch (paramM++) {
case 0: return new cMenuEditIntItem( tr("Nid"), &nidM, 0);
case 1: return new cMenuEditIntItem( tr("Tid"), &tidM, 0);
case 2: return new cMenuEditIntItem( tr("Rid"), &ridM, 0);
case 3: ST("Z ") return new cMenuEditIntItem( trVDR("Srate"), &srateM); else return GetOsdItem();
case 4: ST("Z ") return new cMenuEditIntItem( tr("SignalSource"), &stpM.signalSourceM, 1, 255); else return GetOsdItem();
case 5: ST("Z ") return new cMenuEditChrItem( trVDR("Polarization"), &stpM.polarizationM, "HVLR"); else return GetOsdItem();
case 6: ST("Z ") return new cMenuEditSatipItem(trVDR("Rolloff"), &stpM.rollOffM, SatipRollOffValues); else return GetOsdItem();
case 7: ST("Z ") return new cMenuEditSatipItem( tr("PilotTones"), &stpM.pilotTonesM, SatipPilotTonesValues); else return GetOsdItem();
case 8: ST("ZY") return new cMenuEditSatipItem(trVDR("System"), &stpM.systemM, SatipSystemValues); else return GetOsdItem();
case 9: ST("ZY") return new cMenuEditSatipItem(trVDR("Modulation"), &stpM.modulationM, SatipModulationValues); else return GetOsdItem();
case 10: ST("ZY") return new cMenuEditSatipItem(trVDR("CoderateH"), &stpM.coderateHM, SatipCodeRateValues); else return GetOsdItem();
case 11: ST(" Y") return new cMenuEditSatipItem(trVDR("Bandwidth"), &stpM.bandwidthM, SatipBandwidthValues); else return GetOsdItem();
case 12: ST(" Y") return new cMenuEditSatipItem(trVDR("Transmission"), &stpM.transmissionM, SatipTransmissionValues); else return GetOsdItem();
case 13: ST(" Y") return new cMenuEditSatipItem(trVDR("Guard"), &stpM.guardM, SatipGuardValues); else return GetOsdItem();
case 14: ST(" Y") return new cMenuEditIntItem( trVDR("StreamId"), &stpM.streamIdM, 0, 255); else return GetOsdItem();
case 15: ST(" Y") return new cMenuEditIntItem( tr("T2SystemId"), &stpM.t2SystemIdM, 0, 65535); else return GetOsdItem();
case 16: ST(" Y") return new cMenuEditSatipItem( tr("SISO/MISO"), &stpM.sisoMisoM, SatipSisoMisoValues); else return GetOsdItem();
default: return NULL;
}
#undef ST
return NULL;
}

View File

@@ -1,93 +0,0 @@
/*
* source.h: SAT>IP plugin for the Video Disk Recorder
*
* See the README file for copyright information and how to reach the author.
*
*/
#ifndef __SATIP_SOURCE_H
#define __SATIP_SOURCE_H
#include <vdr/menuitems.h>
#include <vdr/sourceparams.h>
#include "common.h"
struct tSatipParameterMap {
int userValue;
const char *userString;
const char *satipString;
};
class cSatipTransponderParameters {
friend class cSatipSourceParam;
private:
char polarizationM;
int bandwidthM;
int coderateHM;
int systemM;
int modulationM;
int transmissionM;
int guardM;
int rollOffM;
int streamIdM;
int t2SystemIdM;
int sisoMisoM;
int pilotTonesM;
int signalSourceM;
int PrintParameter(char *ptrP, char nameP, int valueP) const;
int PrintString(char *ptrP, int valueP, const tSatipParameterMap *mapP);
const char *ParseParameter(const char *strP, int &valueP);
public:
cSatipTransponderParameters(const char *parametersP = NULL);
char Polarization(void) const { return polarizationM; }
int Bandwidth(void) const { return bandwidthM; }
int CoderateH(void) const { return coderateHM; }
int System(void) const { return systemM; }
int Modulation(void) const { return modulationM; }
int Transmission(void) const { return transmissionM; }
int Guard(void) const { return guardM; }
int RollOff(void) const { return rollOffM; }
int StreamId(void) const { return streamIdM; }
int T2SystemId(void) const { return t2SystemIdM; }
int SisoMiso(void) const { return sisoMisoM; }
int PilotTones(void) const { return pilotTonesM; }
int SignalSource(void) const { return signalSourceM; }
void SetPolarization(char polarizationP) { polarizationM = polarizationP; }
void SetBandwidth(int bandwidthP) { bandwidthM = bandwidthP; }
void SetCoderateH(int coderateHP) { coderateHM = coderateHP; }
void SetSystem(int systemP) { systemM = systemP; }
void SetModulation(int modulationP) { modulationM = modulationP; }
void SetTransmission(int transmissionP) { transmissionM = transmissionP; }
void SetGuard(int guardP) { guardM = guardP; }
void SetRollOff(int rollOffP) { rollOffM = rollOffP; }
void SetStreamId(int streamIdP) { streamIdM = streamIdP; }
void SetT2SystemId(int t2SystemIdP) { t2SystemIdM = t2SystemIdP; }
void SetSisoMiso(int sisoMisoP) { sisoMisoM = sisoMisoP; }
void SetPilotTones(int pilotTonesP) { pilotTonesM = pilotTonesP; }
void SetSignalSource(int signalSourceP) { signalSourceM = signalSourceP; }
cString UrlParameters(char typeP);
cString ToString(char typeP) const;
bool Parse(const char *strP);
};
class cSatipSourceParam : public cSourceParam
{
private:
int paramM;
int nidM;
int tidM;
int ridM;
int srateM;
cChannel dataM;
cSatipTransponderParameters stpM;
public:
cSatipSourceParam(char sourceP, const char *descriptionP);
virtual void SetData(cChannel *channelP);
virtual void GetData(cChannel *channelP);
virtual cOsdItem *GetOsdItem(void);
};
#endif // __SATIP_SOURCE_H

156
tuner.c
View File

@@ -7,6 +7,7 @@
#include "common.h"
#include "config.h"
#include "discover.h"
#include "tuner.h"
cSatipTuner::cSatipTuner(cSatipDeviceIf &deviceP, unsigned int packetLenP)
@@ -18,12 +19,15 @@ cSatipTuner::cSatipTuner(cSatipDeviceIf &deviceP, unsigned int packetLenP)
rtcpSocketM(new cSatipSocket()),
streamAddrM(""),
streamParamM(""),
currentServerM(NULL),
nextServerM(NULL),
mutexM(),
handleM(NULL),
headerListM(NULL),
keepAliveM(),
pidUpdateCacheM(),
timeoutM(eKeepAliveIntervalMs),
sessionM(),
timeoutM(eMinKeepAliveIntervalMs),
openedM(false),
tunedM(false),
hasLockM(false),
@@ -33,20 +37,20 @@ cSatipTuner::cSatipTuner(cSatipDeviceIf &deviceP, unsigned int packetLenP)
pidUpdatedM(false),
pidsM()
{
debug("cSatipTuner::%s(%d)", __FUNCTION__, packetBufferLenM);
debug("cSatipTuner::%s(%d) [device %d]", __FUNCTION__, packetBufferLenM, deviceM->GetId());
// Allocate packet buffer
packetBufferM = MALLOC(unsigned char, packetBufferLenM);
if (packetBufferM)
memset(packetBufferM, 0, packetBufferLenM);
else
error("MALLOC() failed for packet buffer");
error("MALLOC() failed for packet buffer [device %d]", deviceM->GetId());
// Start thread
Start();
}
cSatipTuner::~cSatipTuner()
{
debug("cSatipTuner::%s()", __FUNCTION__);
debug("cSatipTuner::%s() [device %d]", __FUNCTION__, deviceM->GetId());
// Stop thread
sleepM.Signal();
if (Running())
@@ -64,34 +68,36 @@ size_t cSatipTuner::HeaderCallback(void *ptrP, size_t sizeP, size_t nmembP, void
size_t len = sizeP * nmembP;
//debug("cSatipTuner::%s(%zu)", __FUNCTION__, len);
int id = -1, timeout = -1;
char *s, *p = (char *)ptrP;
char *r = strtok_r(p, "\r\n", &s);
while (r) {
while (obj && r) {
//debug("cSatipTuner::%s(%zu): %s", __FUNCTION__, len, r);
r = skipspace(r);
if (strstr(r, "com.ses.streamID")) {
if (sscanf(r, "com.ses.streamID: %11d", &id) != 1)
id = -1;
int streamid = -1;
if (sscanf(r, "com.ses.streamID:%11d", &streamid) == 1)
obj->SetStreamId(streamid);
}
else if (strstr(r, "Session:")) {
int session = -1;
if (sscanf(r, "Session: %11d;timeout=%11d", &session, &timeout) != 2)
timeout = -1;
int timeout = -1;
char *session = NULL;
if (sscanf(r, "Session:%m[^;];timeout=%11d", &session, &timeout) == 2)
obj->SetSessionTimeout(skipspace(session), timeout * 1000);
else if (sscanf(r, "Session:%m[^;]", &session) == 1)
obj->SetSessionTimeout(skipspace(session));
FREE_POINTER(session);
}
r = strtok_r(NULL, "\r\n", &s);
}
if (id >= 0 && obj)
obj->SetStreamInfo(id, timeout);
return len;
}
void cSatipTuner::Action(void)
{
debug("cSatipTuner::%s(): entering", __FUNCTION__);
cTimeMs timeout(0);
debug("cSatipTuner::%s(): entering [device %d]", __FUNCTION__, deviceM->GetId());
cTimeMs timeout(eReConnectTimeoutMs);
// Increase priority
SetPriority(-1);
// Do the thread loop
@@ -123,7 +129,7 @@ void cSatipTuner::Action(void)
}
else {
// Reconnect if necessary
if (openedM && !tunedM && timeout.TimedOut()) {
if (openedM && timeout.TimedOut()) {
Disconnect();
Connect();
timeout.Set(eReConnectTimeoutMs);
@@ -131,12 +137,12 @@ void cSatipTuner::Action(void)
sleepM.Wait(10); // to avoid busy loop and reduce cpu load
}
}
debug("cSatipTuner::%s(): exiting", __FUNCTION__);
debug("cSatipTuner::%s(): exiting [device %d]", __FUNCTION__, deviceM->GetId());
}
bool cSatipTuner::Open(void)
{
debug("cSatipTuner::%s()", __FUNCTION__);
debug("cSatipTuner::%s() [device %d]", __FUNCTION__, deviceM->GetId());
if (Connect()) {
openedM = true;
return true;
@@ -146,7 +152,7 @@ bool cSatipTuner::Open(void)
bool cSatipTuner::Close(void)
{
debug("cSatipTuner::%s()", __FUNCTION__);
debug("cSatipTuner::%s() [device %d]", __FUNCTION__, deviceM->GetId());
openedM = false;
Disconnect();
return true;
@@ -155,7 +161,7 @@ bool cSatipTuner::Close(void)
bool cSatipTuner::Connect(void)
{
cMutexLock MutexLock(&mutexM);
debug("cSatipTuner::%s()", __FUNCTION__);
debug("cSatipTuner::%s() [device %d]", __FUNCTION__, deviceM->GetId());
// Initialize the curl session
if (!handleM)
@@ -167,7 +173,7 @@ bool cSatipTuner::Connect(void)
// Just retune
if (tunedM && (streamIdM >= 0)) {
debug("cSatipTuner::%s(): retune", __FUNCTION__);
debug("cSatipTuner::%s(): retune [device %d]", __FUNCTION__, deviceM->GetId());
uri = cString::sprintf("rtsp://%s/stream=%d", *streamAddrM, streamIdM);
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_RTSP_STREAM_URI, *uri);
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_RTSP_REQUEST, (long)CURL_RTSPREQ_PLAY);
@@ -177,7 +183,6 @@ bool cSatipTuner::Connect(void)
// Flush any old content
if (rtpSocketM)
rtpSocketM->Flush();
keepAliveM.Set(eKeepAliveIntervalMs);
return true;
}
@@ -186,11 +191,6 @@ bool cSatipTuner::Connect(void)
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_VERBOSE, 1L);
#endif
// Set callback
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_HEADERFUNCTION, cSatipTuner::HeaderCallback);
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEHEADER, this);
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEDATA, this);
// No progress meter and no signaling
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_NOPROGRESS, 1L);
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_NOSIGNAL, 1L);
@@ -200,7 +200,7 @@ bool cSatipTuner::Connect(void)
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_CONNECTTIMEOUT_MS, (long)eConnectTimeoutMs);
// Set user-agent
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_USERAGENT, *cString::sprintf("vdr-%s/%s", PLUGIN_NAME_I18N, VERSION));
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_USERAGENT, *cString::sprintf("vdr-%s/%s (device %d)", PLUGIN_NAME_I18N, VERSION, deviceM->GetId()));
// Set URL
char *p = curl_easy_unescape(handleM, *streamAddrM, 0, NULL);
@@ -218,36 +218,53 @@ bool cSatipTuner::Connect(void)
rtcpSocketM->Close();
}
if ((rtpSocketM->Port() <= 0) || (rtcpSocketM->Port() <= 0)) {
error("Cannot open required ports!");
error("Cannot open required RTP/RTCP ports [device %d]", deviceM->GetId());
return false;
}
// Request server options: "&pids=all" for the whole mux
uri = cString::sprintf("rtsp://%s/?%s&pids=0", *streamAddrM, *streamParamM);
// Request server options
keepAliveM.Set(timeoutM);
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_RTSP_STREAM_URI, *uri);
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_RTSP_REQUEST, (long)CURL_RTSPREQ_OPTIONS);
SATIP_CURL_EASY_PERFORM(handleM);
if (!ValidateLatestResponse())
return false;
// Setup media stream
// Setup media stream: "&pids=all" for the whole mux
uri = cString::sprintf("rtsp://%s/?%s", *streamAddrM, *streamParamM);
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_RTSP_STREAM_URI, *uri);
transport = cString::sprintf("RTP/AVP;unicast;client_port=%d-%d", rtpSocketM->Port(), rtcpSocketM->Port());
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_RTSP_TRANSPORT, *transport);
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_RTSP_REQUEST, (long)CURL_RTSPREQ_SETUP);
// Set header callback for catching the session and timeout
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_HEADERFUNCTION, cSatipTuner::HeaderCallback);
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEHEADER, this);
SATIP_CURL_EASY_PERFORM(handleM);
// Session id is now known - disable header parsing
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_HEADERFUNCTION, NULL);
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEHEADER, NULL);
//SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_RTSP_SESSION_ID, *sessionM);
if (!ValidateLatestResponse())
return false;
// Start playing
uri = cString::sprintf("rtsp://%s/stream=%d", *streamAddrM, streamIdM);
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_RTSP_STREAM_URI, *uri);
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_RTSP_REQUEST, (long)CURL_RTSPREQ_PLAY);
SATIP_CURL_EASY_PERFORM(handleM);
if (!ValidateLatestResponse())
return false;
if (pidsM.Size()) {
uri = cString::sprintf("rtsp://%s/stream=%d?pids=", *streamAddrM, streamIdM);
for (int i = 0; i < pidsM.Size(); ++i)
uri = cString::sprintf("%s%d%s", *uri, pidsM[i], (i == (pidsM.Size() - 1)) ? "" : ",");
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_RTSP_STREAM_URI, *uri);
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_RTSP_REQUEST, (long)CURL_RTSPREQ_PLAY);
SATIP_CURL_EASY_PERFORM(handleM);
if (!ValidateLatestResponse())
return false;
}
keepAliveM.Set(eKeepAliveIntervalMs);
tunedM = true;
if (nextServerM) {
cSatipDiscover::GetInstance()->UseServer(nextServerM, true);
currentServerM = nextServerM;
nextServerM = NULL;
}
return true;
}
@@ -257,7 +274,7 @@ bool cSatipTuner::Connect(void)
bool cSatipTuner::Disconnect(void)
{
cMutexLock MutexLock(&mutexM);
debug("cSatipTuner::%s()", __FUNCTION__);
debug("cSatipTuner::%s() [device %d]", __FUNCTION__, deviceM->GetId());
// Terminate curl session
if (handleM) {
@@ -290,14 +307,18 @@ bool cSatipTuner::Disconnect(void)
signalStrengthM = -1;
signalQualityM = -1;
if (currentServerM)
cSatipDiscover::GetInstance()->UseServer(currentServerM, false);
tunedM = false;
timeoutM = eMinKeepAliveIntervalMs;
pidUpdatedM = false;
return true;
}
bool cSatipTuner::ValidateLatestResponse(void)
{
//debug("cSatipTuner::%s()", __FUNCTION__);
//debug("cSatipTuner::%s() [device %d]", __FUNCTION__, deviceM->GetId());
if (handleM) {
long rc = 0;
CURLcode res = CURLE_OK;
@@ -305,7 +326,7 @@ bool cSatipTuner::ValidateLatestResponse(void)
if (rc == 200)
return true;
else if (rc != 0)
error("Tuner detected invalid status code: %ld", rc);
error("Tuner detected invalid status code %ld [device %d]", rc, deviceM->GetId());
}
return false;
@@ -313,7 +334,7 @@ bool cSatipTuner::ValidateLatestResponse(void)
void cSatipTuner::ParseReceptionParameters(const char *paramP)
{
debug("cSatipTuner::%s(%s)", __FUNCTION__, paramP);
//debug("cSatipTuner::%s(%s) [device %d]", __FUNCTION__, paramP, deviceM->GetId());
// DVB-S2:
// ver=<major>.<minor>;src=<srcID>;tuner=<feID>,<level>,<lock>,<quality>,<frequency>,<polarisation>,<system>,<type>,<pilots>,<roll_off>,<symbol_rate>,<fec_inner>;pids=<pid0>,...,<pidn>
// DVB-T2:
@@ -357,20 +378,29 @@ void cSatipTuner::ParseReceptionParameters(const char *paramP)
}
}
void cSatipTuner::SetStreamInfo(int idP, int timeoutP)
void cSatipTuner::SetStreamId(int streamIdP)
{
cMutexLock MutexLock(&mutexM);
debug("cSatipTuner::%s(%d, %d)", __FUNCTION__, idP, timeoutP);
streamIdM = idP;
timeoutM = timeoutP > 0 ? timeoutP * 1000L : eKeepAliveIntervalMs;
debug("cSatipTuner::%s(%d) [device %d]", __FUNCTION__, streamIdP, deviceM->GetId());
streamIdM = streamIdP;
}
bool cSatipTuner::SetSource(const char* addressP, const char *parameterP, const int indexP)
void cSatipTuner::SetSessionTimeout(const char *sessionP, int timeoutP)
{
debug("cSatipTuner::%s(%s, %s, %d)", __FUNCTION__, addressP, parameterP, indexP);
if (!isempty(addressP) && !isempty(parameterP)) {
cMutexLock MutexLock(&mutexM);
debug("cSatipTuner::%s(%s, %d) [device %d]", __FUNCTION__, sessionP, timeoutP, deviceM->GetId());
sessionM = sessionP;
timeoutM = (timeoutP > eMinKeepAliveIntervalMs) ? timeoutP : eMinKeepAliveIntervalMs;
}
bool cSatipTuner::SetSource(cSatipServer *serverP, const char *parameterP, const int indexP)
{
debug("cSatipTuner::%s(%s, %d) [device %d]", __FUNCTION__, parameterP, indexP, deviceM->GetId());
cMutexLock MutexLock(&mutexM);
nextServerM = cSatipDiscover::GetInstance()->GetServer(serverP);
if (nextServerM && !isempty(nextServerM->Address()) && !isempty(parameterP)) {
// Update stream address and parameter
streamAddrM = addressP;
streamAddrM = nextServerM->Address();
streamParamM = parameterP;
// Reconnect
Connect();
@@ -380,7 +410,7 @@ bool cSatipTuner::SetSource(const char* addressP, const char *parameterP, const
bool cSatipTuner::SetPid(int pidP, int typeP, bool onP)
{
debug("cSatipTuner::%s(%d, %d, %d)", __FUNCTION__, pidP, typeP, onP);
//debug("cSatipTuner::%s(%d, %d, %d) [device %d]", __FUNCTION__, pidP, typeP, onP, deviceM->GetId());
cMutexLock MutexLock(&mutexM);
bool found = false;
for (int i = 0; i < pidsM.Size(); ++i) {
@@ -405,7 +435,7 @@ bool cSatipTuner::UpdatePids(void)
{
cMutexLock MutexLock(&mutexM);
if (pidUpdateCacheM.TimedOut() && pidUpdatedM && pidsM.Size() && tunedM && handleM && !isempty(*streamAddrM) && (streamIdM > 0)) {
debug("cSatipTuner::%s()", __FUNCTION__);
//debug("cSatipTuner::%s() [device %d]", __FUNCTION__, deviceM->GetId());
CURLcode res = CURLE_OK;
//cString uri = cString::sprintf("rtsp://%s/stream=%d?%spids=%d", *streamAddrM, streamIdM, onP ? "add" : "del", pidP);
cString uri = cString::sprintf("rtsp://%s/stream=%d?pids=", *streamAddrM, streamIdM);
@@ -416,10 +446,8 @@ bool cSatipTuner::UpdatePids(void)
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_RTSP_STREAM_URI, *uri);
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_RTSP_REQUEST, (long)CURL_RTSPREQ_PLAY);
SATIP_CURL_EASY_PERFORM(handleM);
if (ValidateLatestResponse()) {
keepAliveM.Set(eKeepAliveIntervalMs);
if (ValidateLatestResponse())
pidUpdatedM = false;
}
else
Disconnect();
@@ -433,7 +461,7 @@ bool cSatipTuner::KeepAlive(void)
{
cMutexLock MutexLock(&mutexM);
if (tunedM && handleM && keepAliveM.TimedOut()) {
debug("cSatipTuner::%s()", __FUNCTION__);
debug("cSatipTuner::%s() [device %d]", __FUNCTION__, deviceM->GetId());
CURLcode res = CURLE_OK;
cString uri = cString::sprintf("rtsp://%s/stream=%d", *streamAddrM, streamIdM);
@@ -441,7 +469,7 @@ bool cSatipTuner::KeepAlive(void)
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_RTSP_REQUEST, (long)CURL_RTSPREQ_OPTIONS);
SATIP_CURL_EASY_PERFORM(handleM);
if (ValidateLatestResponse())
keepAliveM.Set(eKeepAliveIntervalMs);
keepAliveM.Set(timeoutM);
else
Disconnect();
@@ -453,30 +481,30 @@ bool cSatipTuner::KeepAlive(void)
int cSatipTuner::SignalStrength(void)
{
//debug("cSatipTuner::%s()", __FUNCTION__);
//debug("cSatipTuner::%s() [device %d]", __FUNCTION__, deviceM->GetId());
return signalStrengthM;
}
int cSatipTuner::SignalQuality(void)
{
//debug("cSatipTuner::%s()", __FUNCTION__);
//debug("cSatipTuner::%s() [device %d]", __FUNCTION__, deviceM->GetId());
return signalQualityM;
}
bool cSatipTuner::HasLock(void)
{
//debug("cSatipTuner::%s()", __FUNCTION__);
//debug("cSatipTuner::%s() [device %d]", __FUNCTION__, deviceM->GetId());
return tunedM && hasLockM;
}
cString cSatipTuner::GetSignalStatus(void)
{
//debug("cSatipTuner::%s()", __FUNCTION__);
//debug("cSatipTuner::%s() [device %d]", __FUNCTION__, deviceM->GetId());
return cString::sprintf("lock=%d strength=%d quality=%d", HasLock(), SignalStrength(), SignalQuality());
}
cString cSatipTuner::GetInformation(void)
{
//debug("cSatipTuner::%s()", __FUNCTION__);
//debug("cSatipTuner::%s() [device %d]", __FUNCTION__, deviceM->GetId());
return tunedM ? cString::sprintf("rtsp://%s/?%s [stream=%d]", *streamAddrM, *streamParamM, streamIdM) : "connection failed";
}

17
tuner.h
View File

@@ -19,16 +19,17 @@
#include <vdr/tools.h>
#include "deviceif.h"
#include "server.h"
#include "statistics.h"
#include "socket.h"
class cSatipTuner : public cThread, public cSatipTunerStatistics {
private:
enum {
eConnectTimeoutMs = 1500, // in milliseconds
ePidUpdateIntervalMs = 100, // in milliseconds
eReConnectTimeoutMs = 5000, // in milliseconds
eKeepAliveIntervalMs = 600000 // in milliseconds
eConnectTimeoutMs = 1500, // in milliseconds
ePidUpdateIntervalMs = 100, // in milliseconds
eReConnectTimeoutMs = 5000, // in milliseconds
eMinKeepAliveIntervalMs = 30000 // in milliseconds
};
static size_t HeaderCallback(void *ptrP, size_t sizeP, size_t nmembP, void *dataP);
@@ -41,12 +42,15 @@ private:
cSatipSocket *rtcpSocketM;
cString streamAddrM;
cString streamParamM;
cSatipServer *currentServerM;
cSatipServer *nextServerM;
cMutex mutexM;
CURL *handleM;
struct curl_slist *headerListM;
cTimeMs keepAliveM;
cTimeMs signalInfoCacheM;
cTimeMs pidUpdateCacheM;
cString sessionM;
int timeoutM;
bool openedM;
bool tunedM;
@@ -61,7 +65,8 @@ private:
bool Disconnect(void);
bool ValidateLatestResponse(void);
void ParseReceptionParameters(const char *paramP);
void SetStreamInfo(int idP, int timeoutP);
void SetStreamId(int streamIdP);
void SetSessionTimeout(const char *sessionP, int timeoutP = 0);
bool KeepAlive(void);
bool UpdateSignalInfoCache(void);
bool UpdatePids(void);
@@ -73,7 +78,7 @@ public:
cSatipTuner(cSatipDeviceIf &deviceP, unsigned int packetLenP);
virtual ~cSatipTuner();
bool IsTuned(void) const { return tunedM; }
bool SetSource(const char* addressP, const char *parameterP, const int indexP);
bool SetSource(cSatipServer *serverP, const char *parameterP, const int indexP);
bool SetPid(int pidP, int typeP, bool onP);
bool Open(void);
bool Close(void);