mirror of
https://github.com/rofafor/vdr-plugin-satip.git
synced 2023-10-10 11:37:42 +00:00
Compare commits
29 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
6573c38fb6 | ||
|
581ac4966d | ||
|
99e366b261 | ||
|
3b89dd4b01 | ||
|
ee6ac0d48a | ||
|
e6c9776ec9 | ||
|
7aef2a3dff | ||
|
61b56db909 | ||
|
4c45787541 | ||
|
f65dca2910 | ||
|
db0c18ba33 | ||
|
0f9e0014df | ||
|
6bb7fb511b | ||
|
7815821824 | ||
|
bc481bcc4d | ||
|
7289da9f41 | ||
|
d5e0106d8e | ||
|
fe532e2248 | ||
|
b5483b9d77 | ||
|
fd23b0483a | ||
|
18c9b79533 | ||
|
e4f560c66e | ||
|
57ea119d03 | ||
|
ae8298d19a | ||
|
b755dbf318 | ||
|
8f12ce6f55 | ||
|
9d5f7cc703 | ||
|
c1a881ba94 | ||
|
165fd5b14a |
12
HISTORY
12
HISTORY
@ -144,3 +144,15 @@ VDR Plugin 'satip' Revision History
|
||||
- Reset the RTSP connection after any failed connect.
|
||||
- Added tweaks for minisatip and Schwaiger MS41IP.
|
||||
- Updated for vdr-2.3.1 (Thanks to Klaus Schmidinger).
|
||||
|
||||
2016-12-18: Version 2.2.4
|
||||
|
||||
- Updated German translation (Thanks to Frank Neumann).
|
||||
- Fixed Panasonic CXW804 support (Thanks to Tobias Grimm).
|
||||
- Fixed C++11 support (Thanks to Tobias Grimm).
|
||||
- Fixed server assigment with source validation (Thanks to Patrick Boettcher).
|
||||
- Added configurable RTP/RTCP ports (Thanks to chriszero).
|
||||
- Added support for X-SATIP-RTSP-Port header.
|
||||
- Added multicast and RTP-over-TCP support.
|
||||
- Added support for activating/deactivating server on-the-fly.
|
||||
- Extended command-line parameters for setting server quirks.
|
||||
|
20
README
20
README
@ -52,9 +52,15 @@ separated list of "<ipaddress>|<model>|<description>" entries. The model
|
||||
consists of a DVB system (DVBS2,DVBT2,DVBT,DVBC) and number of available
|
||||
frontends separated by a hyphen:
|
||||
|
||||
vdr -P 'satip -s <ipaddress>|<model>|<description>;...'
|
||||
vdr -P 'satip -s 192.168.0.1|DVBS2-2,DVBT2-2|Octo1'
|
||||
vdr -P 'satip -s 192.168.0.1|DVBS2-4|Octo1;192.168.0.2|DVBT2-4|Octo2'
|
||||
vdr -P 'satip -s <ipaddress>[:<port>]|<model>[:<filter>]|<description>[:<quirk>];...'
|
||||
vdr -P 'satip -s 192.168.0.1|DVBS2-2,DVBT2-2|OctopusNet'
|
||||
vdr -P 'satip -s 192.168.0.1|DVBS2-4|OctopusNet;192.168.0.2|DVBT2-4|minisatip:0x18'
|
||||
vdr -P 'satip -s 192.168.0.1:554|DVBS2-2:S19.2E|OctopusNet;192.168.0.2:8554|DVBS2-4:S19.2E,S1W|minisatip'
|
||||
|
||||
The plugin accepts a "--portrange" (-p) command-line parameter, that can
|
||||
be used to manually specify the RTP & RTCP port range and therefore
|
||||
enables using the plugin through a NAT (e.g. Docker bridged network).
|
||||
A minimum of 2 ports per device is required.
|
||||
|
||||
SAT>IP satellite positions (aka. signal sources) shall be defined via
|
||||
sources.conf. If the source description begins with a number, it's used
|
||||
@ -110,6 +116,11 @@ Setup menu:
|
||||
"Disable filter" options which allow you
|
||||
to disable the individual section filters.
|
||||
Valid range: "none" = 0 ... 7
|
||||
- Transport mode = unicast If you want to use the non-standard
|
||||
multicast RTP-over-TCP transport mode, set this option
|
||||
rtp-o-tcp accordingly. Otherwise, the transport
|
||||
mode will be RTP-over-UDP via unicast or
|
||||
multicast.
|
||||
- [Red:Scan] Forces network scanning of SAT>IP hardware.
|
||||
- [Yellow:Devices] Opens SAT>IP device status menu.
|
||||
- [Blue:Info] Opens SAT>IP information/statistics menu.
|
||||
@ -125,6 +136,9 @@ Information menu:
|
||||
|
||||
Notes:
|
||||
|
||||
- If you are having problems receiving DVB-S2 channels, make sure your
|
||||
channels.conf entry contains correct pilot tone setting.
|
||||
|
||||
- The stream id "-1" states about unsuccessful tuning. This might be a
|
||||
result of invalid channel parameters or lack of free SAT>IP tuners.
|
||||
|
||||
|
22
common.h
22
common.h
@ -13,9 +13,11 @@
|
||||
#include <vdr/config.h>
|
||||
#include <vdr/i18n.h>
|
||||
|
||||
#define SATIP_DEFAULT_RTSP_PORT 554
|
||||
|
||||
#define SATIP_MAX_DEVICES MAXDEVICES
|
||||
|
||||
#define SATIP_BUFFER_SIZE KILOBYTE(1024)
|
||||
#define SATIP_BUFFER_SIZE KILOBYTE(2048)
|
||||
|
||||
#define SATIP_DEVICE_INFO_ALL 0
|
||||
#define SATIP_DEVICE_INFO_GENERAL 1
|
||||
@ -48,15 +50,15 @@
|
||||
esyslog("curl_easy_perform() [%s,%d] failed: %s (%d)", __FILE__, __LINE__, curl_easy_strerror(res), res); \
|
||||
}
|
||||
|
||||
#define ERROR_IF_FUNC(exp, errstr, func, ret) \
|
||||
do { \
|
||||
if (exp) { \
|
||||
char tmp[64]; \
|
||||
esyslog("[%s,%d]: "errstr": %s", __FILE__, __LINE__, \
|
||||
strerror_r(errno, tmp, sizeof(tmp))); \
|
||||
func; \
|
||||
ret; \
|
||||
} \
|
||||
#define ERROR_IF_FUNC(exp, errstr, func, ret) \
|
||||
do { \
|
||||
if (exp) { \
|
||||
char tmp[64]; \
|
||||
esyslog("[%s,%d]: " errstr ": %s", __FILE__, __LINE__, \
|
||||
strerror_r(errno, tmp, sizeof(tmp))); \
|
||||
func; \
|
||||
ret; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
|
||||
|
3
config.c
3
config.c
@ -17,6 +17,9 @@ cSatipConfig::cSatipConfig(void)
|
||||
ciExtensionM(0),
|
||||
eitScanM(1),
|
||||
useBytesM(1),
|
||||
portRangeStartM(0),
|
||||
portRangeStopM(0),
|
||||
transportModeM(eTransportModeUnicast),
|
||||
detachedModeM(false),
|
||||
disableServerQuirksM(false),
|
||||
useSingleModelServersM(false)
|
||||
|
18
config.h
18
config.h
@ -19,6 +19,9 @@ private:
|
||||
unsigned int ciExtensionM;
|
||||
unsigned int eitScanM;
|
||||
unsigned int useBytesM;
|
||||
unsigned int portRangeStartM;
|
||||
unsigned int portRangeStopM;
|
||||
unsigned int transportModeM;
|
||||
bool detachedModeM;
|
||||
bool disableServerQuirksM;
|
||||
bool useSingleModelServersM;
|
||||
@ -34,6 +37,12 @@ public:
|
||||
eOperatingModeHigh,
|
||||
eOperatingModeCount
|
||||
};
|
||||
enum eTransportMode {
|
||||
eTransportModeUnicast = 0,
|
||||
eTransportModeMulticast,
|
||||
eTransportModeRtpOverTcp,
|
||||
eTransportModeCount
|
||||
};
|
||||
enum eTraceMode {
|
||||
eTraceModeNormal = 0x0000,
|
||||
eTraceModeDebug1 = 0x0001,
|
||||
@ -67,6 +76,10 @@ public:
|
||||
int GetCICAM(unsigned int indexP) const;
|
||||
unsigned int GetEITScan(void) const { return eitScanM; }
|
||||
unsigned int GetUseBytes(void) const { return useBytesM; }
|
||||
unsigned int GetTransportMode(void) const { return transportModeM; }
|
||||
bool IsTransportModeUnicast(void) const { return (transportModeM == eTransportModeUnicast); }
|
||||
bool IsTransportModeRtpOverTcp(void) const { return (transportModeM == eTransportModeRtpOverTcp); }
|
||||
bool IsTransportModeMulticast(void) const { return (transportModeM == eTransportModeMulticast); }
|
||||
bool GetDetachedMode(void) const { return detachedModeM; }
|
||||
bool GetDisableServerQuirks(void) const { return disableServerQuirksM; }
|
||||
bool GetUseSingleModelServers(void) const { return useSingleModelServersM; }
|
||||
@ -74,6 +87,8 @@ public:
|
||||
int GetDisabledSources(unsigned int indexP) const;
|
||||
unsigned int GetDisabledFiltersCount(void) const;
|
||||
int GetDisabledFilters(unsigned int indexP) const;
|
||||
unsigned int GetPortRangeStart(void) const { return portRangeStartM; }
|
||||
unsigned int GetPortRangeStop(void) const { return portRangeStopM; }
|
||||
|
||||
void SetOperatingMode(unsigned int operatingModeP) { operatingModeM = operatingModeP; }
|
||||
void SetTraceMode(unsigned int modeP) { traceModeM = (modeP & eTraceModeMask); }
|
||||
@ -81,11 +96,14 @@ public:
|
||||
void SetCICAM(unsigned int indexP, int cicamP);
|
||||
void SetEITScan(unsigned int onOffP) { eitScanM = onOffP; }
|
||||
void SetUseBytes(unsigned int onOffP) { useBytesM = onOffP; }
|
||||
void SetTransportMode(unsigned int transportModeP) { transportModeM = transportModeP; }
|
||||
void SetDetachedMode(bool onOffP) { detachedModeM = onOffP; }
|
||||
void SetDisableServerQuirks(bool onOffP) { disableServerQuirksM = onOffP; }
|
||||
void SetUseSingleModelServers(bool onOffP) { useSingleModelServersM = onOffP; }
|
||||
void SetDisabledSources(unsigned int indexP, int sourceP);
|
||||
void SetDisabledFilters(unsigned int indexP, int numberP);
|
||||
void SetPortRangeStart(unsigned int rangeStartP) { portRangeStartM = rangeStartP; }
|
||||
void SetPortRangeStop(unsigned int rangeStopP) { portRangeStopM = rangeStopP; }
|
||||
};
|
||||
|
||||
extern cSatipConfig SatipConfig;
|
||||
|
22
device.c
22
device.c
@ -120,8 +120,12 @@ cString cSatipDevice::GetSatipStatus(void)
|
||||
info = cString::sprintf("%sCardIndex: %d HasLock: yes Strength: %d Quality: %d%s\n", *info, device->CardIndex(), device->SignalStrength(), device->SignalQuality(), live ? " Live: yes" : "");
|
||||
else
|
||||
info = cString::sprintf("%sCardIndex: %d HasLock: no\n", *info, device->CardIndex());
|
||||
if (channel && channel->Number() > 0)
|
||||
info = cString::sprintf("%sTransponder: %d Channel: %s\n", *info, (channel && channel->Number() > 0) ? channel->Transponder() : 0, (channel && channel->Number() > 0) ? channel->Name() : "---");
|
||||
if (channel) {
|
||||
if (channel->Number() > 0 && device->Receiving())
|
||||
info = cString::sprintf("%sTransponder: %d Channel: %s\n", *info, channel->Transponder(), channel->Name());
|
||||
else
|
||||
info = cString::sprintf("%sTransponder: %d\n", *info, channel->Transponder());
|
||||
}
|
||||
if (timers)
|
||||
info = cString::sprintf("%sRecording: %d timer%s\n", *info, timers, (timers > 1) ? "s" : "");
|
||||
info = cString::sprintf("%s\n", *info);
|
||||
@ -136,7 +140,7 @@ cString cSatipDevice::GetGeneralInformation(void)
|
||||
#if defined(APIVERSNUM) && APIVERSNUM >= 20301
|
||||
LOCK_CHANNELS_READ;
|
||||
#endif
|
||||
return cString::sprintf("SAT>IP device: %d\nCardIndex: %d\nStream: %s\nSignal: %s\nStream bitrate: %s\n%sChannel: %s",
|
||||
return cString::sprintf("SAT>IP device: %d\nCardIndex: %d\nStream: %s\nSignal: %s\nStream bitrate: %s\n%sChannel: %s\n",
|
||||
deviceIndexM, CardIndex(),
|
||||
pTunerM ? *pTunerM->GetInformation() : "",
|
||||
pTunerM ? *pTunerM->GetSignalStatus() : "",
|
||||
@ -206,6 +210,8 @@ cString cSatipDevice::DeviceType(void) const
|
||||
cString cSatipDevice::DeviceName(void) const
|
||||
{
|
||||
debug16("%s [device %u]", __PRETTY_FUNCTION__, deviceIndexM);
|
||||
if (!Receiving())
|
||||
return cString::sprintf("%s %d", *DeviceType(), deviceIndexM);
|
||||
return deviceNameM;
|
||||
}
|
||||
|
||||
@ -355,6 +361,7 @@ bool cSatipDevice::SetChannelDevice(const cChannel *channelP, bool liveViewP)
|
||||
}
|
||||
else if (pTunerM) {
|
||||
pTunerM->SetSource(NULL, 0, NULL, deviceIndexM);
|
||||
deviceNameM = cString::sprintf("%s %d", *DeviceType(), deviceIndexM);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@ -366,7 +373,7 @@ bool cSatipDevice::SetPid(cPidHandle *handleP, int typeP, bool onP)
|
||||
if (pTunerM && handleP && handleP->pid >= 0) {
|
||||
if (onP)
|
||||
return pTunerM->SetPid(handleP->pid, typeP, true);
|
||||
else if (!handleP->used)
|
||||
else if (!handleP->used && pSectionFilterHandlerM && !pSectionFilterHandlerM->Exists(handleP->pid))
|
||||
return pTunerM->SetPid(handleP->pid, typeP, false);
|
||||
}
|
||||
return true;
|
||||
@ -472,6 +479,13 @@ int cSatipDevice::GetCISlot(void)
|
||||
return slot;
|
||||
}
|
||||
|
||||
cString cSatipDevice::GetTnrParameterString(void)
|
||||
{
|
||||
if (channelM.Ca())
|
||||
return GetTnrUrlParameters(&channelM);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool cSatipDevice::IsIdle(void)
|
||||
{
|
||||
return !Receiving();
|
||||
|
1
device.h
1
device.h
@ -110,6 +110,7 @@ public:
|
||||
virtual int GetId(void);
|
||||
virtual int GetPmtPid(void);
|
||||
virtual int GetCISlot(void);
|
||||
virtual cString GetTnrParameterString(void);
|
||||
virtual bool IsIdle(void);
|
||||
};
|
||||
|
||||
|
@ -16,6 +16,7 @@ public:
|
||||
virtual int GetId(void) = 0;
|
||||
virtual int GetPmtPid(void) = 0;
|
||||
virtual int GetCISlot(void) = 0;
|
||||
virtual cString GetTnrParameterString(void) = 0;
|
||||
virtual bool IsIdle(void) = 0;
|
||||
|
||||
private:
|
||||
|
77
discover.c
77
discover.c
@ -32,7 +32,7 @@ bool cSatipDiscover::Initialize(cSatipDiscoverServers *serversP)
|
||||
if (instanceS) {
|
||||
if (serversP) {
|
||||
for (cSatipDiscoverServer *s = serversP->First(); s; s = serversP->Next(s))
|
||||
instanceS->AddServer(s->IpAddress(), s->Model(), s->Description());
|
||||
instanceS->AddServer(s->IpAddress(), s->IpPort(), s->Model(), s->Filters(), s->Description(), s->Quirk());
|
||||
}
|
||||
else
|
||||
instanceS->Activate();
|
||||
@ -47,6 +47,18 @@ void cSatipDiscover::Destroy(void)
|
||||
instanceS->Deactivate();
|
||||
}
|
||||
|
||||
size_t cSatipDiscover::HeaderCallback(char *ptrP, size_t sizeP, size_t nmembP, void *dataP)
|
||||
{
|
||||
cSatipDiscover *obj = reinterpret_cast<cSatipDiscover *>(dataP);
|
||||
size_t len = sizeP * nmembP;
|
||||
debug16("%s len=%zu", __PRETTY_FUNCTION__, len);
|
||||
|
||||
if (obj && (len > 0))
|
||||
obj->headerBufferM.Add(ptrP, len);
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
size_t cSatipDiscover::DataCallback(char *ptrP, size_t sizeP, size_t nmembP, void *dataP)
|
||||
{
|
||||
cSatipDiscover *obj = reinterpret_cast<cSatipDiscover *>(dataP);
|
||||
@ -91,6 +103,7 @@ int cSatipDiscover::DebugCallback(CURL *handleP, curl_infotype typeP, char *data
|
||||
cSatipDiscover::cSatipDiscover()
|
||||
: cThread("SATIP discover"),
|
||||
mutexM(),
|
||||
headerBufferM(),
|
||||
dataBufferM(),
|
||||
msearchM(*this),
|
||||
probeUrlListM(),
|
||||
@ -176,7 +189,9 @@ void cSatipDiscover::Fetch(const char *urlP)
|
||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_DEBUGFUNCTION, cSatipDiscover::DebugCallback);
|
||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_DEBUGDATA, this);
|
||||
|
||||
// Set callback
|
||||
// Set header and data callbacks
|
||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_HEADERFUNCTION, cSatipDiscover::HeaderCallback);
|
||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEHEADER, this);
|
||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEFUNCTION, cSatipDiscover::DataCallback);
|
||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEDATA, this);
|
||||
|
||||
@ -199,7 +214,8 @@ void cSatipDiscover::Fetch(const char *urlP)
|
||||
SATIP_CURL_EASY_GETINFO(handleM, CURLINFO_RESPONSE_CODE, &rc);
|
||||
SATIP_CURL_EASY_GETINFO(handleM, CURLINFO_PRIMARY_IP, &addr);
|
||||
if (rc == 200) {
|
||||
ParseDeviceInfo(addr);
|
||||
ParseDeviceInfo(addr, ParseRtspPort());
|
||||
headerBufferM.Reset();
|
||||
dataBufferM.Reset();
|
||||
}
|
||||
else
|
||||
@ -207,9 +223,32 @@ void cSatipDiscover::Fetch(const char *urlP)
|
||||
}
|
||||
}
|
||||
|
||||
void cSatipDiscover::ParseDeviceInfo(const char *addrP)
|
||||
int cSatipDiscover::ParseRtspPort(void)
|
||||
{
|
||||
debug1("%s (%s)", __PRETTY_FUNCTION__, addrP);
|
||||
debug1("%s", __PRETTY_FUNCTION__);
|
||||
char *s, *p = headerBufferM.Data();
|
||||
char *r = strtok_r(p, "\r\n", &s);
|
||||
int port = SATIP_DEFAULT_RTSP_PORT;
|
||||
|
||||
while (r) {
|
||||
debug16("%s (%zu): %s", __PRETTY_FUNCTION__, headerBufferM.Size(), r);
|
||||
r = skipspace(r);
|
||||
if (strstr(r, "X-SATIP-RTSP-Port")) {
|
||||
int tmp = -1;
|
||||
if (sscanf(r, "X-SATIP-RTSP-Port:%11d", &tmp) == 1) {
|
||||
port = tmp;
|
||||
break;
|
||||
}
|
||||
}
|
||||
r = strtok_r(NULL, "\r\n", &s);
|
||||
}
|
||||
|
||||
return port;
|
||||
}
|
||||
|
||||
void cSatipDiscover::ParseDeviceInfo(const char *addrP, const int portP)
|
||||
{
|
||||
debug1("%s (%s, %d)", __PRETTY_FUNCTION__, addrP, portP);
|
||||
const char *desc = NULL, *model = NULL;
|
||||
#ifdef USE_TINYXML
|
||||
TiXmlDocument doc;
|
||||
@ -232,12 +271,12 @@ void cSatipDiscover::ParseDeviceInfo(const char *addrP)
|
||||
model = modelNode.text().as_string("DVBS2-1");
|
||||
}
|
||||
#endif
|
||||
AddServer(addrP, model, desc);
|
||||
AddServer(addrP, portP, model, NULL, desc, cSatipServer::eSatipQuirkNone);
|
||||
}
|
||||
|
||||
void cSatipDiscover::AddServer(const char *addrP, const char *modelP, const char * descP)
|
||||
void cSatipDiscover::AddServer(const char *addrP, const int portP, const char *modelP, const char *filtersP, const char *descP, const int quirkP)
|
||||
{
|
||||
debug1("%s (%s, %s, %s)", __PRETTY_FUNCTION__, addrP, modelP, descP);
|
||||
debug1("%s (%s, %d, %s, %s, %s, %d)", __PRETTY_FUNCTION__, addrP, portP, modelP, filtersP, descP, quirkP);
|
||||
cMutexLock MutexLock(&mutexM);
|
||||
if (SatipConfig.GetUseSingleModelServers() && modelP && !isempty(modelP)) {
|
||||
int n = 0;
|
||||
@ -246,9 +285,9 @@ void cSatipDiscover::AddServer(const char *addrP, const char *modelP, const char
|
||||
while (r) {
|
||||
r = skipspace(r);
|
||||
cString desc = cString::sprintf("%s #%d", !isempty(descP) ? descP : "MyBrokenHardware", n++);
|
||||
cSatipServer *tmp = new cSatipServer(addrP, r, desc);
|
||||
cSatipServer *tmp = new cSatipServer(addrP, portP, r, filtersP, desc, quirkP);
|
||||
if (!serversM.Update(tmp)) {
|
||||
info("Adding server '%s|%s|%s' CI: %s Quirks: %s", tmp->Address(), tmp->Model(), tmp->Description(), tmp->HasCI() ? "yes" : "no", tmp->HasQuirk() ? tmp->Quirks() : "none");
|
||||
info("Adding server '%s|%s|%s' Filters: %s CI: %s Quirks: %s", tmp->Address(), tmp->Model(), tmp->Description(), !isempty(tmp->Filters()) ? tmp->Filters() : "none", tmp->HasCI() ? "yes" : "no", tmp->HasQuirk() ? tmp->Quirks() : "none");
|
||||
serversM.Add(tmp);
|
||||
}
|
||||
else
|
||||
@ -258,9 +297,9 @@ void cSatipDiscover::AddServer(const char *addrP, const char *modelP, const char
|
||||
FREE_POINTER(p);
|
||||
}
|
||||
else {
|
||||
cSatipServer *tmp = new cSatipServer(addrP, modelP, descP);
|
||||
cSatipServer *tmp = new cSatipServer(addrP, portP, modelP, filtersP, descP, quirkP);
|
||||
if (!serversM.Update(tmp)) {
|
||||
info("Adding server '%s|%s|%s' CI: %s Quirks: %s", tmp->Address(), tmp->Model(), tmp->Description(), tmp->HasCI() ? "yes" : "no", tmp->HasQuirk() ? tmp->Quirks() : "none");
|
||||
info("Adding server '%s|%s|%s' Filters: %s CI: %s Quirks: %s", tmp->Address(), tmp->Model(), tmp->Description(), !isempty(tmp->Filters()) ? tmp->Filters() : "none", tmp->HasCI() ? "yes" : "no", tmp->HasQuirk() ? tmp->Quirks() : "none");
|
||||
serversM.Add(tmp);
|
||||
}
|
||||
else
|
||||
@ -317,6 +356,13 @@ cString cSatipDiscover::GetServerList(void)
|
||||
return serversM.List();
|
||||
}
|
||||
|
||||
void cSatipDiscover::ActivateServer(cSatipServer *serverP, bool onOffP)
|
||||
{
|
||||
debug16("%s (, %d)", __PRETTY_FUNCTION__, onOffP);
|
||||
cMutexLock MutexLock(&mutexM);
|
||||
serversM.Activate(serverP, onOffP);
|
||||
}
|
||||
|
||||
void cSatipDiscover::AttachServer(cSatipServer *serverP, int deviceIdP, int transponderP)
|
||||
{
|
||||
debug16("%s (, %d, %d)", __PRETTY_FUNCTION__, deviceIdP, transponderP);
|
||||
@ -352,6 +398,13 @@ cString cSatipDiscover::GetServerAddress(cSatipServer *serverP)
|
||||
return serversM.GetAddress(serverP);
|
||||
}
|
||||
|
||||
int cSatipDiscover::GetServerPort(cSatipServer *serverP)
|
||||
{
|
||||
debug16("%s", __PRETTY_FUNCTION__);
|
||||
cMutexLock MutexLock(&mutexM);
|
||||
return serversM.GetPort(serverP);
|
||||
}
|
||||
|
||||
int cSatipDiscover::NumProvidedSystems(void)
|
||||
{
|
||||
debug16("%s", __PRETTY_FUNCTION__);
|
||||
|
19
discover.h
19
discover.h
@ -21,16 +21,22 @@
|
||||
|
||||
class cSatipDiscoverServer : public cListObject {
|
||||
private:
|
||||
int ipPortM;
|
||||
int quirkM;
|
||||
cString ipAddressM;
|
||||
cString descriptionM;
|
||||
cString modelM;
|
||||
cString filtersM;
|
||||
public:
|
||||
cSatipDiscoverServer(const char *ipAddressP, const char *modelP, const char *descriptionP)
|
||||
cSatipDiscoverServer(const char *ipAddressP, const int ipPortP, const char *modelP, const char *filtersP, const char *descriptionP, const int quirkP)
|
||||
{
|
||||
ipAddressM = ipAddressP; modelM = modelP; descriptionM = descriptionP;
|
||||
ipAddressM = ipAddressP; ipPortM = ipPortP; modelM = modelP; filtersM = filtersP; descriptionM = descriptionP; quirkM = quirkP;
|
||||
}
|
||||
int IpPort(void) { return ipPortM; }
|
||||
int Quirk(void) { return quirkM; }
|
||||
const char *IpAddress(void) { return *ipAddressM; }
|
||||
const char *Model(void) { return *modelM; }
|
||||
const char *Filters(void) { return *filtersM; }
|
||||
const char *Description(void) { return *descriptionM; }
|
||||
};
|
||||
|
||||
@ -47,9 +53,11 @@ private:
|
||||
eCleanupTimeoutMs = 124000 // in milliseoonds
|
||||
};
|
||||
static cSatipDiscover *instanceS;
|
||||
static size_t HeaderCallback(char *ptrP, size_t sizeP, size_t nmembP, void *dataP);
|
||||
static size_t DataCallback(char *ptrP, size_t sizeP, size_t nmembP, void *dataP);
|
||||
static int DebugCallback(CURL *handleP, curl_infotype typeP, char *dataP, size_t sizeP, void *userPtrP);
|
||||
cMutex mutexM;
|
||||
cSatipMemoryBuffer headerBufferM;
|
||||
cSatipMemoryBuffer dataBufferM;
|
||||
cSatipMsearch msearchM;
|
||||
cStringList probeUrlListM;
|
||||
@ -59,8 +67,9 @@ private:
|
||||
cSatipServers serversM;
|
||||
void Activate(void);
|
||||
void Deactivate(void);
|
||||
void ParseDeviceInfo(const char *addrP);
|
||||
void AddServer(const char *addrP, const char *modelP, const char *descP);
|
||||
int ParseRtspPort(void);
|
||||
void ParseDeviceInfo(const char *addrP, const int portP);
|
||||
void AddServer(const char *addrP, const int portP, const char *modelP, const char *filtersP, const char *descP, const int quirkP);
|
||||
void Fetch(const char *urlP);
|
||||
// constructor
|
||||
cSatipDiscover();
|
||||
@ -83,11 +92,13 @@ public:
|
||||
cSatipServer *GetServer(cSatipServer *serverP);
|
||||
cSatipServers *GetServers(void);
|
||||
cString GetServerString(cSatipServer *serverP);
|
||||
void ActivateServer(cSatipServer *serverP, bool onOffP);
|
||||
void AttachServer(cSatipServer *serverP, int deviceIdP, int transponderP);
|
||||
void DetachServer(cSatipServer *serverP, int deviceIdP, int transponderP);
|
||||
bool IsServerQuirk(cSatipServer *serverP, int quirkP);
|
||||
bool HasServerCI(cSatipServer *serverP);
|
||||
cString GetServerAddress(cSatipServer *serverP);
|
||||
int GetServerPort(cSatipServer *serverP);
|
||||
cString GetServerList(void);
|
||||
int NumProvidedSystems(void);
|
||||
|
||||
|
@ -29,7 +29,7 @@ cSatipMsearch::cSatipMsearch(cSatipDiscoverIf &discoverP)
|
||||
memset(bufferM, 0, bufferLenM);
|
||||
else
|
||||
error("Cannot create Msearch buffer!");
|
||||
if (!Open(eDiscoveryPort))
|
||||
if (!Open(eDiscoveryPort, true))
|
||||
error("Cannot open Msearch port!");
|
||||
}
|
||||
|
||||
@ -100,6 +100,11 @@ void cSatipMsearch::Process(void)
|
||||
}
|
||||
}
|
||||
|
||||
void cSatipMsearch::Process(unsigned char *dataP, int lengthP)
|
||||
{
|
||||
debug16("%s", __PRETTY_FUNCTION__);
|
||||
}
|
||||
|
||||
cString cSatipMsearch::ToString(void) const
|
||||
{
|
||||
return "MSearch";
|
||||
|
@ -34,6 +34,7 @@ public:
|
||||
public:
|
||||
virtual int GetFd(void);
|
||||
virtual void Process(void);
|
||||
virtual void Process(unsigned char *dataP, int lengthP);
|
||||
virtual cString ToString(void) const;
|
||||
};
|
||||
|
||||
|
344
param.c
344
param.c
@ -163,34 +163,344 @@ cString GetTransponderUrlParameters(const cChannel *channelP)
|
||||
dtp.SetModulation(QPSK);
|
||||
dtp.SetRollOff(ROLLOFF_35);
|
||||
}
|
||||
if ((channelP->Rid() % 100) > 0)
|
||||
q += snprintf(q, STBUFLEFT, "&fe=%d", channelP->Rid() % 100);
|
||||
ST(" S *") q += snprintf(q, STBUFLEFT, "src=%d&", ((src > 0) && (src <= 255)) ? src : 1);
|
||||
q += snprintf(q, STBUFLEFT, "freq=%s", *dtoa(freq, "%lg"));
|
||||
ST(" S *") q += snprintf(q, STBUFLEFT, "&src=%d", ((src > 0) && (src <= 255)) ? src : 1);
|
||||
ST(" S *") q += snprintf(q, STBUFLEFT, "&sr=%d", channelP->Srate());
|
||||
ST("C 1") q += snprintf(q, STBUFLEFT, "&sr=%d", channelP->Srate());
|
||||
ST(" S *") q += snprintf(q, STBUFLEFT, "&pol=%c", tolower(dtp.Polarization()));
|
||||
ST("C T2") q += snprintf(q, STBUFLEFT, "&plp=%d", dtp.StreamId());
|
||||
ST(" T2") q += snprintf(q, STBUFLEFT, "&t2id=%d", dtp.T2SystemId());
|
||||
ST(" S *") q += PrintUrlString(q, STBUFLEFT, dtp.RollOff(), SatipRollOffValues);
|
||||
ST("C 2") q += snprintf(q, STBUFLEFT, "&c2tft=%d", C2TuningFrequencyType);
|
||||
ST("C 2") q += snprintf(q, STBUFLEFT, "&ds=%d", DataSlice);
|
||||
ST("C 1") q += PrintUrlString(q, STBUFLEFT, dtp.Inversion(), SatipInversionValues);
|
||||
ST(" T2") q += PrintUrlString(q, STBUFLEFT, dtp.SisoMiso(), SatipSisoMisoValues);
|
||||
ST(" T*") q += PrintUrlString(q, STBUFLEFT, dtp.Bandwidth(), SatipBandwidthValues);
|
||||
ST("C 2") q += PrintUrlString(q, STBUFLEFT, dtp.Bandwidth(), SatipBandwidthValues);
|
||||
ST(" T*") q += PrintUrlString(q, STBUFLEFT, dtp.Guard(), SatipGuardValues);
|
||||
ST("CST*") q += PrintUrlString(q, STBUFLEFT, dtp.CoderateH(), SatipCodeRateValues);
|
||||
ST(" S *") q += PrintUrlString(q, STBUFLEFT, dtp.Pilot(), SatipPilotValues);
|
||||
ST(" S *") q += PrintUrlString(q, STBUFLEFT, dtp.Modulation(), SatipModulationValues);
|
||||
ST(" T*") q += PrintUrlString(q, STBUFLEFT, dtp.Modulation(), SatipModulationValues);
|
||||
ST("C 1") q += PrintUrlString(q, STBUFLEFT, dtp.Modulation(), SatipModulationValues);
|
||||
ST(" S *") q += PrintUrlString(q, STBUFLEFT, dtp.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);
|
||||
if ((channelP->Rid() % 100) > 0)
|
||||
snprintf(q, STBUFLEFT, "&fe=%d", channelP->Rid() % 100);
|
||||
ST(" S *") q += PrintUrlString(q, STBUFLEFT, dtp.Modulation(), SatipModulationValues);
|
||||
ST(" T*") q += PrintUrlString(q, STBUFLEFT, dtp.Modulation(), SatipModulationValues);
|
||||
ST("C 1") q += PrintUrlString(q, STBUFLEFT, dtp.Modulation(), SatipModulationValues);
|
||||
ST(" S *") q += PrintUrlString(q, STBUFLEFT, dtp.Pilot(), SatipPilotValues);
|
||||
ST(" S *") q += snprintf(q, STBUFLEFT, "&sr=%d", channelP->Srate());
|
||||
ST("C 1") q += snprintf(q, STBUFLEFT, "&sr=%d", channelP->Srate());
|
||||
ST(" T*") q += PrintUrlString(q, STBUFLEFT, dtp.Guard(), SatipGuardValues);
|
||||
ST("CST*") q += PrintUrlString(q, STBUFLEFT, dtp.CoderateH(), SatipCodeRateValues);
|
||||
ST("C 2") q += snprintf(q, STBUFLEFT, "&ds=%d", DataSlice);
|
||||
ST("C T2") q += snprintf(q, STBUFLEFT, "&plp=%d", dtp.StreamId());
|
||||
ST(" T2") q += snprintf(q, STBUFLEFT, "&t2id=%d", dtp.T2SystemId());
|
||||
ST(" T2") q += PrintUrlString(q, STBUFLEFT, dtp.SisoMiso(), SatipSisoMisoValues);
|
||||
ST("C 1") q += PrintUrlString(q, STBUFLEFT, dtp.Inversion(), SatipInversionValues);
|
||||
#undef ST
|
||||
return buffer;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
cString GetTnrUrlParameters(const cChannel *channelP)
|
||||
{
|
||||
if (channelP) {
|
||||
cDvbTransponderParameters dtp(channelP->Parameters());
|
||||
eTrackType track = cDevice::PrimaryDevice()->GetCurrentAudioTrack();
|
||||
|
||||
// TunerType: Byte;
|
||||
// 0 = cable, 1 = satellite, 2 = terrestrial, 3 = atsc, 4 = iptv, 5 = stream (URL, DVBViewer GE)
|
||||
int TunerType = 0;
|
||||
if (channelP->IsCable())
|
||||
TunerType = 0;
|
||||
else if (channelP->IsSat())
|
||||
TunerType = 1;
|
||||
else if (channelP->IsTerr())
|
||||
TunerType = 2;
|
||||
else if (channelP->IsAtsc())
|
||||
TunerType = 3;
|
||||
|
||||
// Frequency: DWord;
|
||||
// DVB-S: MHz if < 1000000, kHz if >= 1000000
|
||||
// DVB-T/C, ATSC: kHz
|
||||
// IPTV: IP address Byte3.Byte2.Byte1.Byte0
|
||||
int Frequency = channelP->Frequency() / 1000;
|
||||
|
||||
// Symbolrate: DWord;
|
||||
// DVB S/C: in kSym/s
|
||||
// DVB-T, ATSC: 0
|
||||
// IPTV: Port
|
||||
int Symbolrate = (channelP->IsSat() || channelP->IsCable()) ? channelP->Srate() : 0;
|
||||
|
||||
// LNB_LOF: Word;
|
||||
// DVB-S: Local oscillator frequency of the LNB
|
||||
// DVB-T/C, ATSC: 0
|
||||
// IPTV: Byte0 and Byte1 of Source IP
|
||||
int LNB_LOF = channelP->IsSat() ? Setup.LnbSLOF : 0;
|
||||
|
||||
// Tone: Byte;
|
||||
// 0 = off, 1 = 22 khz
|
||||
int Tone = (channelP->Frequency() < Setup.LnbSLOF) ? 0 : 1;
|
||||
|
||||
// Polarity: Byte;
|
||||
// DVB-S polarity: 0 = horizontal, 1 = vertical, 2 = circular left, 3 = circular right
|
||||
// DVB-C modulation: 0 = Auto, 1 = 16QAM, 2 = 32QAM, 3 = 64QAM, 4 = 128QAM, 5 = 256 QAM
|
||||
// DVB-T bandwidth: 0 = 6 MHz, 1 = 7 MHz, 2 = 8 MHz
|
||||
// IPTV: Byte3 of SourceIP
|
||||
int Polarity = 0;
|
||||
if (channelP->IsSat()) {
|
||||
switch (tolower(dtp.Polarization())) {
|
||||
case 'h':
|
||||
Polarity = 0;
|
||||
break;
|
||||
case 'v':
|
||||
Polarity = 1;
|
||||
break;
|
||||
case 'l':
|
||||
Polarity = 2;
|
||||
break;
|
||||
case 'r':
|
||||
Polarity = 3;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (channelP->IsCable()) {
|
||||
switch (dtp.Modulation()) {
|
||||
case 999:
|
||||
Polarity = 0;
|
||||
break;
|
||||
case 16:
|
||||
Polarity = 1;
|
||||
break;
|
||||
case 32:
|
||||
Polarity = 2;
|
||||
break;
|
||||
case 64:
|
||||
Polarity = 3;
|
||||
break;
|
||||
case 128:
|
||||
Polarity = 4;
|
||||
break;
|
||||
case 256:
|
||||
Polarity = 5;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (channelP->IsTerr()) {
|
||||
switch (dtp.Bandwidth()) {
|
||||
case 6:
|
||||
Polarity = 0;
|
||||
break;
|
||||
case 7:
|
||||
Polarity = 1;
|
||||
break;
|
||||
case 8:
|
||||
Polarity = 2;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// DiSEqC: Byte;
|
||||
// 0 = None
|
||||
// 1 = Pos A (mostly translated to PosA/OptA)
|
||||
// 2 = Pos B (mostly translated to PosB/OptA)
|
||||
// 3 = PosA/OptA
|
||||
// 4 = PosB/OptA
|
||||
// 5 = PosA/OptB
|
||||
// 6 = PosB/OptB
|
||||
// 7 = Preset Position (DiSEqC 1.2, see DiSEqCExt)
|
||||
// 8 = Angular Position (DiSEqC 1.2, see DiSEqCExt)
|
||||
// 9 = DiSEqC Command Sequence (see DiSEqCExt)
|
||||
int DiSEqC = 0;
|
||||
|
||||
// FEC: Byte;
|
||||
// 0 = Auto
|
||||
// 1 = 1/2
|
||||
// 2 = 2/3
|
||||
// 3 = 3/4
|
||||
// 4 = 5/6
|
||||
// 5 = 7/8
|
||||
// 6 = 8/9
|
||||
// 7 = 3/5
|
||||
// 8 = 4/5
|
||||
// 9 = 9/10
|
||||
// IPTV: Byte2 of SourceIP
|
||||
// DVB C/T, ATSC: 0
|
||||
int FEC = 0;
|
||||
if (channelP->IsSat()) {
|
||||
switch (dtp.CoderateH()) {
|
||||
case 999:
|
||||
FEC = 0;
|
||||
break;
|
||||
case 12:
|
||||
FEC = 1;
|
||||
break;
|
||||
case 23:
|
||||
FEC = 2;
|
||||
break;
|
||||
case 34:
|
||||
FEC = 3;
|
||||
break;
|
||||
case 56:
|
||||
FEC = 4;
|
||||
break;
|
||||
case 78:
|
||||
FEC = 5;
|
||||
break;
|
||||
case 89:
|
||||
FEC = 6;
|
||||
break;
|
||||
case 35:
|
||||
FEC = 7;
|
||||
break;
|
||||
case 45:
|
||||
FEC = 8;
|
||||
break;
|
||||
case 910:
|
||||
FEC = 9;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Audio_PID: Word;
|
||||
int Audio_PID = channelP->Apid(0);
|
||||
if (IS_AUDIO_TRACK(track))
|
||||
Audio_PID = channelP->Apid(int(track - ttAudioFirst));
|
||||
else if (IS_DOLBY_TRACK(track))
|
||||
Audio_PID = channelP->Dpid(int(track - ttDolbyFirst));
|
||||
|
||||
// Video_PID: Word;
|
||||
int Video_PID = channelP->Vpid();
|
||||
|
||||
// PMT_PID: Word;
|
||||
int PMT_PID = channelP->Ppid();
|
||||
|
||||
// Service_ID: Word;
|
||||
int Service_ID = channelP->Sid();
|
||||
|
||||
// SatModulation: Byte;
|
||||
// Bit 0..1: satellite modulation. 0 = Auto, 1 = QPSK, 2 = 8PSK, 3 = 16QAM or APSK for DVB-S2
|
||||
// Bit 2: modulation system. 0 = DVB-S/T/C, 1 = DVB-S2/T2/C2
|
||||
// Bit 3..4: DVB-S2: roll-off. 0 = 0.35, 1 = 0.25, 2 = 0.20, 3 = reserved
|
||||
// Bit 5..6: spectral inversion, 0 = undefined, 1 = auto, 2 = normal, 3 = inverted
|
||||
// Bit 7: DVB-S2: pilot symbols, 0 = off, 1 = on
|
||||
// DVB-T2: DVB-T2 Lite, 0 = off, 1 = on
|
||||
int SatModulation = 0;
|
||||
if (channelP->IsSat() && dtp.System()) {
|
||||
switch (dtp.Modulation()) {
|
||||
case 999:
|
||||
SatModulation |= (0 & 0x3) << 0;
|
||||
break;
|
||||
case 2:
|
||||
SatModulation |= (1 & 0x3) << 0;
|
||||
break;
|
||||
case 5:
|
||||
SatModulation |= (2 & 0x3) << 0;
|
||||
break;
|
||||
case 6:
|
||||
SatModulation |= (3 & 0x3) << 0;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
SatModulation |= (dtp.System() & 0x1) << 2;
|
||||
if (channelP->IsSat() && dtp.System()) {
|
||||
switch (dtp.RollOff()) {
|
||||
case 35:
|
||||
SatModulation |= (0 & 0x3) << 3;
|
||||
break;
|
||||
case 25:
|
||||
SatModulation |= (1 & 0x3) << 3;
|
||||
break;
|
||||
case 20:
|
||||
SatModulation |= (2 & 0x3) << 3;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
switch (dtp.Inversion()) {
|
||||
case 999:
|
||||
SatModulation |= (1 & 0x3) << 5;
|
||||
break;
|
||||
case 0:
|
||||
SatModulation |= (2 & 0x3) << 5;
|
||||
break;
|
||||
case 1:
|
||||
SatModulation |= (3 & 0x3) << 5;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (channelP->IsSat() && dtp.System()) {
|
||||
switch (dtp.Pilot()) {
|
||||
case 0:
|
||||
SatModulation |= (0 & 0x1) << 7;
|
||||
break;
|
||||
case 1:
|
||||
SatModulation |= (1 & 0x1) << 7;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// DiSEqCExt: Word;
|
||||
// DiSEqC Extension, meaning depends on DiSEqC
|
||||
// DiSEqC = 0..6: 0
|
||||
// DiSEqC = 7: Preset Position (DiSEqC 1.2)
|
||||
// DiSEqC = 8: Orbital Position (DiSEqC 1.2, USALS, for calculating motor angle)
|
||||
// Same format as OrbitalPos above
|
||||
// DiSEQC = 9: Orbital Position referencing DiSEqC sequence defined in DiSEqC.xml/ini
|
||||
// Same format as OrbitalPos above
|
||||
int DiSEqCExt = 0;
|
||||
|
||||
// Flags: Byte;
|
||||
// Bit 0: 1 = encrypted channel
|
||||
// Bit 1: reserved, set to 0
|
||||
// Bit 2: 1 = channel broadcasts RDS data
|
||||
// Bit 3: 1 = channel is a video service (even if the Video PID is temporarily = 0)
|
||||
// Bit 4: 1 = channel is an audio service (even if the Audio PID is temporarily = 0)
|
||||
// Bit 5: 1 = audio has a different samplerate than 48 KHz
|
||||
// Bit 6: 1 = bandstacking, internally polarisation is always set to H
|
||||
// Bit 7: 1 = channel entry is an additional audio track of the preceding
|
||||
// channel with bit 7 = 0
|
||||
int Flags = (channelP->Ca() > 0xFF) ? 1 : 0;
|
||||
|
||||
// ChannelGroup: Byte;
|
||||
// 0 = Group A, 1 = Group B, 2 = Group C etc.
|
||||
int ChannelGroup = 0;
|
||||
|
||||
// TransportStream_ID: Word;
|
||||
int TransportStream_ID = channelP->Tid();
|
||||
|
||||
// OriginalNetwork_ID: Word;
|
||||
int OriginalNetwork_ID = channelP->Nid();
|
||||
|
||||
// Substream: Word;
|
||||
// DVB-S/C/T, ATSC, IPTV: 0
|
||||
// DVB-T2: 0 = PLP_ID not set, 1..256: PLP_ID + 1, 257... reserved
|
||||
int Substream = (channelP->IsTerr() && dtp.System()) ? dtp.StreamId() - 1 : 0;
|
||||
|
||||
// OrbitalPos: Word;
|
||||
// DVB-S: orbital position x 10, 0 = undefined, 1..1800 east, 1801..3599 west (1°W = 3599)
|
||||
// DVB-C: 4000..4999
|
||||
// DVB-T: 5000..5999
|
||||
// ATSC: 6000..6999
|
||||
// IPTV: 7000..7999
|
||||
// Stream: 8000..8999
|
||||
int OrbitalPos = 0;
|
||||
if (channelP->IsSat()) {
|
||||
OrbitalPos = cSource::Position(channelP->Source());
|
||||
if (OrbitalPos != 3600)
|
||||
OrbitalPos += 1800;
|
||||
}
|
||||
|
||||
return cString::sprintf("%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d",
|
||||
TunerType, Frequency, Symbolrate, LNB_LOF, Tone, Polarity, DiSEqC, FEC, Audio_PID, Video_PID, PMT_PID, Service_ID,
|
||||
SatModulation, DiSEqCExt, Flags, ChannelGroup, TransportStream_ID, OriginalNetwork_ID, Substream, OrbitalPos);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
1
param.h
1
param.h
@ -11,5 +11,6 @@
|
||||
#include "common.h"
|
||||
|
||||
cString GetTransponderUrlParameters(const cChannel *channelP);
|
||||
cString GetTnrUrlParameters(const cChannel *channelP);
|
||||
|
||||
#endif // __SATIP_PARAM_H
|
||||
|
26
po/ca_ES.po
26
po/ca_ES.po
@ -1,14 +1,14 @@
|
||||
# VDR plugin language source file.
|
||||
# Copyright (C) 2007-2015 Rolf Ahrenberg
|
||||
# Copyright (C) 2007-2016 Rolf Ahrenberg
|
||||
# This file is distributed under the same license as the satip package.
|
||||
# Gabriel Bonich, 2014-2015
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: vdr-satip 2.2.3\n"
|
||||
"Project-Id-Version: vdr-satip 2.2.4\n"
|
||||
"Report-Msgid-Bugs-To: <see README>\n"
|
||||
"POT-Creation-Date: 2015-04-26 04:26+0300\n"
|
||||
"PO-Revision-Date: 2015-04-26 04:26+0300\n"
|
||||
"POT-Creation-Date: 2016-12-18 12:18+0200\n"
|
||||
"PO-Revision-Date: 2016-12-18 12:18+0200\n"
|
||||
"Last-Translator: Gabriel Bonich <gbonich@gmail.com>\n"
|
||||
"Language-Team: Catalan <vdr@linuxtv.org>\n"
|
||||
"Language: ca\n"
|
||||
@ -85,6 +85,15 @@ msgstr "Normal"
|
||||
msgid "high"
|
||||
msgstr "Alt"
|
||||
|
||||
msgid "Unicast"
|
||||
msgstr ""
|
||||
|
||||
msgid "Multicast"
|
||||
msgstr ""
|
||||
|
||||
msgid "RTP-over-TCP"
|
||||
msgstr ""
|
||||
|
||||
msgid "Button$Devices"
|
||||
msgstr "Dispositius"
|
||||
|
||||
@ -178,6 +187,15 @@ msgstr "Filtra"
|
||||
msgid "Define an ill-behaving filter to be blacklisted."
|
||||
msgstr "Definir un filtre mal comportar a la llista negra."
|
||||
|
||||
msgid "Transport mode"
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
"Define which transport mode shall be used.\n"
|
||||
"\n"
|
||||
"Unicast, Multicast, RTP-over-TCP"
|
||||
msgstr ""
|
||||
|
||||
msgid "Active SAT>IP servers:"
|
||||
msgstr "Activa SAT>IP servers:"
|
||||
|
||||
|
39
po/de_DE.po
39
po/de_DE.po
@ -1,14 +1,14 @@
|
||||
# VDR plugin language source file.
|
||||
# Copyright (C) 2007-2015 Rolf Ahrenberg
|
||||
# Copyright (C) 2007-2016 Rolf Ahrenberg
|
||||
# This file is distributed under the same license as the satip package.
|
||||
# Frank Neumann, 2014-2015
|
||||
# Frank Neumann, 2014-2016
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: vdr-satip 2.2.3\n"
|
||||
"Project-Id-Version: vdr-satip 2.2.4\n"
|
||||
"Report-Msgid-Bugs-To: <see README>\n"
|
||||
"POT-Creation-Date: 2015-04-26 04:26+0300\n"
|
||||
"PO-Revision-Date: 2015-04-26 04:26+0300\n"
|
||||
"POT-Creation-Date: 2016-12-18 12:18+0200\n"
|
||||
"PO-Revision-Date: 2016-12-18 12:18+0200\n"
|
||||
"Last-Translator: Frank Neumann <fnu@yavdr.org>\n"
|
||||
"Language-Team: German <vdr@linuxtv.org>\n"
|
||||
"Language: de\n"
|
||||
@ -85,11 +85,20 @@ msgstr "normal"
|
||||
msgid "high"
|
||||
msgstr "hoch"
|
||||
|
||||
msgid "Unicast"
|
||||
msgstr "Unicast"
|
||||
|
||||
msgid "Multicast"
|
||||
msgstr "Multicast"
|
||||
|
||||
msgid "RTP-over-TCP"
|
||||
msgstr "RTP-over-TCP"
|
||||
|
||||
msgid "Button$Devices"
|
||||
msgstr "Geräte"
|
||||
|
||||
msgid "Operating mode"
|
||||
msgstr "Betriebsmodus"
|
||||
msgstr "Betriebsart"
|
||||
|
||||
msgid ""
|
||||
"Define the used operating mode for all SAT>IP devices:\n"
|
||||
@ -99,7 +108,7 @@ msgid ""
|
||||
"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"
|
||||
"Bestimme die Betriebsart für alle SAT>IP Geräte:\n"
|
||||
"\n"
|
||||
"aus - Geräte sind abgeschaltet\n"
|
||||
"niedrig - Geräte arbeiten mit geringster Priorität\n"
|
||||
@ -170,13 +179,25 @@ msgid ""
|
||||
msgstr ""
|
||||
"Bestimme die Anzahl der Abschnittsfilter die deaktiviert werden sollen.\n"
|
||||
"\n"
|
||||
"Bestimmte Abschnittsfilter können unerwünschtes Verhalten mit VDR, z.B. falsche Zeit-Synchronisation, verursachen. Durch das Ausblenden einzelner Filter können nützliche Daten dieser Abschnitte für den VDR erhalten werden."
|
||||
"Bestimmte Abschnittsfilter können unerwünschtes Verhalten mit VDR, z.B. falsche Zeit-Synchronisation, verursachen. Durch das Ausblenden einzelner Filter können nützliche Daten dieser Abschnitte für den VDR erhalten bleiben."
|
||||
|
||||
msgid "Filter"
|
||||
msgstr "Filter"
|
||||
|
||||
msgid "Define an ill-behaving filter to be blacklisted."
|
||||
msgstr "Bestimme einen fehlerhaften Filter der ausgeblendet werden soll."
|
||||
msgstr "Bestimme fehlerhafte Filter die ausgeblendet werden sollen."
|
||||
|
||||
msgid "Transport mode"
|
||||
msgstr "Übertragungsart"
|
||||
|
||||
msgid ""
|
||||
"Define which transport mode shall be used.\n"
|
||||
"\n"
|
||||
"Unicast, Multicast, RTP-over-TCP"
|
||||
msgstr ""
|
||||
"Lege die gewünschte Übertragungsart fest.\n"
|
||||
"\n"
|
||||
"Unicast, Multicast, RTP-over-TCP"
|
||||
|
||||
msgid "Active SAT>IP servers:"
|
||||
msgstr "Aktive SAT>IP Server:"
|
||||
|
26
po/es_ES.po
26
po/es_ES.po
@ -1,14 +1,14 @@
|
||||
# VDR plugin language source file.
|
||||
# Copyright (C) 2007-2015 Rolf Ahrenberg
|
||||
# Copyright (C) 2007-2016 Rolf Ahrenberg
|
||||
# This file is distributed under the same license as the satip package.
|
||||
# Gabriel Bonich, 2014-2015
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: vdr-satip 2.2.3\n"
|
||||
"Project-Id-Version: vdr-satip 2.2.4\n"
|
||||
"Report-Msgid-Bugs-To: <see README>\n"
|
||||
"POT-Creation-Date: 2015-04-26 04:26+0300\n"
|
||||
"PO-Revision-Date: 2015-04-26 04:26+0300\n"
|
||||
"POT-Creation-Date: 2016-12-18 12:18+0200\n"
|
||||
"PO-Revision-Date: 2016-12-18 12:18+0200\n"
|
||||
"Last-Translator: Gabriel Bonich <gbonich@gmail.com>\n"
|
||||
"Language-Team: Spanish <vdr@linuxtv.org>\n"
|
||||
"Language: es\n"
|
||||
@ -85,6 +85,15 @@ msgstr "Normal"
|
||||
msgid "high"
|
||||
msgstr "Alto"
|
||||
|
||||
msgid "Unicast"
|
||||
msgstr ""
|
||||
|
||||
msgid "Multicast"
|
||||
msgstr ""
|
||||
|
||||
msgid "RTP-over-TCP"
|
||||
msgstr ""
|
||||
|
||||
msgid "Button$Devices"
|
||||
msgstr "Dispositivos"
|
||||
|
||||
@ -178,6 +187,15 @@ msgstr "Filtra"
|
||||
msgid "Define an ill-behaving filter to be blacklisted."
|
||||
msgstr "Define un filtro para poner en la lista negra."
|
||||
|
||||
msgid "Transport mode"
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
"Define which transport mode shall be used.\n"
|
||||
"\n"
|
||||
"Unicast, Multicast, RTP-over-TCP"
|
||||
msgstr ""
|
||||
|
||||
msgid "Active SAT>IP servers:"
|
||||
msgstr "Activa SAT>IP servers:"
|
||||
|
||||
|
31
po/fi_FI.po
31
po/fi_FI.po
@ -1,14 +1,14 @@
|
||||
# VDR plugin language source file.
|
||||
# Copyright (C) 2007-2015 Rolf Ahrenberg
|
||||
# Copyright (C) 2007-2016 Rolf Ahrenberg
|
||||
# This file is distributed under the same license as the satip package.
|
||||
# Rolf Ahrenberg, 2015
|
||||
# Rolf Ahrenberg, 2015-2016
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: vdr-satip 2.2.3\n"
|
||||
"Project-Id-Version: vdr-satip 2.2.4\n"
|
||||
"Report-Msgid-Bugs-To: <see README>\n"
|
||||
"POT-Creation-Date: 2015-04-26 04:26+0300\n"
|
||||
"PO-Revision-Date: 2015-04-26 04:26+0300\n"
|
||||
"POT-Creation-Date: 2016-12-18 12:18+0200\n"
|
||||
"PO-Revision-Date: 2016-12-18 12:18+0200\n"
|
||||
"Last-Translator: Rolf Ahrenberg\n"
|
||||
"Language-Team: Finnish <vdr@linuxtv.org>\n"
|
||||
"Language: fi\n"
|
||||
@ -85,6 +85,15 @@ msgstr "normaali"
|
||||
msgid "high"
|
||||
msgstr "korkea"
|
||||
|
||||
msgid "Unicast"
|
||||
msgstr "Unicast"
|
||||
|
||||
msgid "Multicast"
|
||||
msgstr "Multicast"
|
||||
|
||||
msgid "RTP-over-TCP"
|
||||
msgstr "RTP-over-TCP"
|
||||
|
||||
msgid "Button$Devices"
|
||||
msgstr "Laitteet"
|
||||
|
||||
@ -177,6 +186,18 @@ msgstr "Suodatin"
|
||||
msgid "Define an ill-behaving filter to be blacklisted."
|
||||
msgstr "Määrittele käytöstä poistettava suodatin, joka lisätään mustalle listalle."
|
||||
|
||||
msgid "Transport mode"
|
||||
msgstr "Siirtoyhteystapa"
|
||||
|
||||
msgid ""
|
||||
"Define which transport mode shall be used.\n"
|
||||
"\n"
|
||||
"Unicast, Multicast, RTP-over-TCP"
|
||||
msgstr ""
|
||||
"Määrittele käytettävä siirtoyhteystapa.\n"
|
||||
"\n"
|
||||
"Unicast, Multicast, RTP-over-TCP"
|
||||
|
||||
msgid "Active SAT>IP servers:"
|
||||
msgstr "Aktiiviset SAT>IP-palvelimet:"
|
||||
|
||||
|
2
poller.c
2
poller.c
@ -79,7 +79,7 @@ void cSatipPoller::Action(void)
|
||||
// Do the thread loop
|
||||
while (Running()) {
|
||||
int nfds = epoll_wait(fdM, events, eMaxFileDescriptors, -1);
|
||||
ERROR_IF_FUNC((nfds == -1), "epoll_wait() failed", break, ;);
|
||||
ERROR_IF_FUNC((nfds == -1 && errno != EINTR), "epoll_wait() failed", break, ;);
|
||||
for (int i = 0; i < nfds; ++i) {
|
||||
cSatipPollerIf* poll = reinterpret_cast<cSatipPollerIf *>(events[i].data.ptr);
|
||||
if (poll) {
|
||||
|
@ -14,6 +14,7 @@ public:
|
||||
virtual ~cSatipPollerIf() {}
|
||||
virtual int GetFd(void) = 0;
|
||||
virtual void Process(void) = 0;
|
||||
virtual void Process(unsigned char *dataP, int lengthP) = 0;
|
||||
virtual cString ToString(void) const = 0;
|
||||
|
||||
private:
|
||||
|
10
rtcp.c
10
rtcp.c
@ -92,6 +92,16 @@ void cSatipRtcp::Process(void)
|
||||
}
|
||||
}
|
||||
|
||||
void cSatipRtcp::Process(unsigned char *dataP, int lengthP)
|
||||
{
|
||||
debug16("%s [device %d]", __PRETTY_FUNCTION__, tunerM.GetId());
|
||||
if (dataP && lengthP > 0) {
|
||||
int offset = GetApplicationOffset(&lengthP);
|
||||
if (offset >= 0)
|
||||
tunerM.ProcessApplicationData(dataP + offset, lengthP);
|
||||
}
|
||||
}
|
||||
|
||||
cString cSatipRtcp::ToString(void) const
|
||||
{
|
||||
return cString::sprintf("RTCP [device %d]", tunerM.GetId());
|
||||
|
1
rtcp.h
1
rtcp.h
@ -30,6 +30,7 @@ public:
|
||||
public:
|
||||
virtual int GetFd(void);
|
||||
virtual void Process(void);
|
||||
virtual void Process(unsigned char *dataP, int lengthP);
|
||||
virtual cString ToString(void) const;
|
||||
};
|
||||
|
||||
|
16
rtp.c
16
rtp.c
@ -142,6 +142,22 @@ void cSatipRtp::Process(void)
|
||||
}
|
||||
}
|
||||
|
||||
void cSatipRtp::Process(unsigned char *dataP, int lengthP)
|
||||
{
|
||||
debug16("%s [device %d]", __PRETTY_FUNCTION__, tunerM.GetId());
|
||||
if (dataP && lengthP > 0) {
|
||||
uint64_t elapsed;
|
||||
cTimeMs processing(0);
|
||||
int headerlen = GetHeaderLength(dataP, lengthP);
|
||||
if ((headerlen >= 0) && (headerlen < lengthP))
|
||||
tunerM.ProcessVideoData(dataP + headerlen, lengthP - headerlen);
|
||||
|
||||
elapsed = processing.Elapsed();
|
||||
if (elapsed > 1)
|
||||
debug6("%s %d read(s) took %" PRIu64 " ms [device %d]", __PRETTY_FUNCTION__, lengthP, elapsed, tunerM.GetId());
|
||||
}
|
||||
}
|
||||
|
||||
cString cSatipRtp::ToString(void) const
|
||||
{
|
||||
return cString::sprintf("RTP [device %d]", tunerM.GetId());
|
||||
|
1
rtp.h
1
rtp.h
@ -36,6 +36,7 @@ public:
|
||||
public:
|
||||
virtual int GetFd(void);
|
||||
virtual void Process(void);
|
||||
virtual void Process(unsigned char *dataP, int lengthP);
|
||||
virtual cString ToString(void) const;
|
||||
};
|
||||
|
||||
|
105
rtsp.c
105
rtsp.c
@ -17,12 +17,14 @@ cSatipRtsp::cSatipRtsp(cSatipTunerIf &tunerP)
|
||||
: tunerM(tunerP),
|
||||
headerBufferM(),
|
||||
dataBufferM(),
|
||||
modeM(cmUnicast),
|
||||
handleM(NULL),
|
||||
headerListM(NULL),
|
||||
errorNoMoreM(""),
|
||||
errorOutOfRangeM(""),
|
||||
errorCheckSyntaxM("")
|
||||
errorCheckSyntaxM(""),
|
||||
modeM(cSatipConfig::eTransportModeUnicast),
|
||||
interleavedRtpIdM(0),
|
||||
interleavedRtcpIdM(1)
|
||||
{
|
||||
debug1("%s [device %d]", __PRETTY_FUNCTION__, tunerM.GetId());
|
||||
Create();
|
||||
@ -58,6 +60,30 @@ size_t cSatipRtsp::DataCallback(char *ptrP, size_t sizeP, size_t nmembP, void *d
|
||||
return len;
|
||||
}
|
||||
|
||||
size_t cSatipRtsp::InterleaveCallback(char *ptrP, size_t sizeP, size_t nmembP, void *dataP)
|
||||
{
|
||||
cSatipRtsp *obj = reinterpret_cast<cSatipRtsp *>(dataP);
|
||||
size_t len = sizeP * nmembP;
|
||||
debug16("%s len=%zu", __PRETTY_FUNCTION__, len);
|
||||
|
||||
if (obj && ptrP && len > 0) {
|
||||
char tag = ptrP[0] & 0xFF;
|
||||
if (tag == '$') {
|
||||
int count = ((ptrP[2] & 0xFF) << 8) | (ptrP[3] & 0xFF);
|
||||
if (count > 0) {
|
||||
unsigned int channel = ptrP[1] & 0xFF;
|
||||
u_char *data = (u_char *)&ptrP[4];
|
||||
if (channel == obj->interleavedRtpIdM)
|
||||
obj->tunerM.ProcessRtpData(data, count);
|
||||
else if (channel == obj->interleavedRtcpIdM)
|
||||
obj->tunerM.ProcessRtcpData(data, count);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
int cSatipRtsp::DebugCallback(CURL *handleP, curl_infotype typeP, char *dataP, size_t sizeP, void *userPtrP)
|
||||
{
|
||||
cSatipRtsp *obj = reinterpret_cast<cSatipRtsp *>(userPtrP);
|
||||
@ -87,6 +113,21 @@ int cSatipRtsp::DebugCallback(CURL *handleP, curl_infotype typeP, char *dataP, s
|
||||
return 0;
|
||||
}
|
||||
|
||||
cString cSatipRtsp::GetActiveMode(void)
|
||||
{
|
||||
switch (modeM) {
|
||||
case cSatipConfig::eTransportModeUnicast:
|
||||
return "Unicast";
|
||||
case cSatipConfig::eTransportModeMulticast:
|
||||
return "Multicast";
|
||||
case cSatipConfig::eTransportModeRtpOverTcp:
|
||||
return "RTP-over-TCP";
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
cString cSatipRtsp::RtspUnescapeString(const char *strP)
|
||||
{
|
||||
debug1("%s (%s) [device %d]", __PRETTY_FUNCTION__, strP, tunerM.GetId());
|
||||
@ -123,6 +164,9 @@ void cSatipRtsp::Create(void)
|
||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_TIMEOUT_MS, (long)eConnectTimeoutMs);
|
||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_CONNECTTIMEOUT_MS, (long)eConnectTimeoutMs);
|
||||
|
||||
// Limit download speed (bytes/s)
|
||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_MAX_RECV_SPEED_LARGE, eMaxDownloadSpeedMBits * 131072L);
|
||||
|
||||
// Set user-agent
|
||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_USERAGENT, *cString::sprintf("vdr-%s/%s (device %d)", PLUGIN_NAME_I18N, VERSION, tunerM.GetId()));
|
||||
}
|
||||
@ -171,9 +215,9 @@ bool cSatipRtsp::Options(const char *uriP)
|
||||
return result;
|
||||
}
|
||||
|
||||
bool cSatipRtsp::Setup(const char *uriP, int rtpPortP, int rtcpPortP)
|
||||
bool cSatipRtsp::Setup(const char *uriP, int rtpPortP, int rtcpPortP, bool useTcpP)
|
||||
{
|
||||
debug1("%s (%s, %d, %d) [device %d]", __PRETTY_FUNCTION__, uriP, rtpPortP, rtcpPortP, tunerM.GetId());
|
||||
debug1("%s (%s, %d, %d, %d) [device %d]", __PRETTY_FUNCTION__, uriP, rtpPortP, rtcpPortP, useTcpP, tunerM.GetId());
|
||||
bool result = false;
|
||||
|
||||
if (handleM && !isempty(uriP)) {
|
||||
@ -182,15 +226,18 @@ bool cSatipRtsp::Setup(const char *uriP, int rtpPortP, int rtcpPortP)
|
||||
cTimeMs processing(0);
|
||||
CURLcode res = CURLE_OK;
|
||||
|
||||
switch (modeM) {
|
||||
case cmMulticast:
|
||||
// RTP/AVP;multicast;destination=<IP multicast address>;port=<RTP port>-<RTCP port>;ttl=<ttl>
|
||||
transport = cString::sprintf("RTP/AVP;multicast;port=%d-%d", rtpPortP, rtcpPortP);
|
||||
switch (SatipConfig.GetTransportMode()) {
|
||||
case cSatipConfig::eTransportModeMulticast:
|
||||
// RTP/AVP;multicast;destination=<multicast group address>;port=<RTP port>-<RTCP port>;ttl=<ttl>[;source=<multicast source address>]
|
||||
transport = cString::sprintf("RTP/AVP;multicast");
|
||||
break;
|
||||
default:
|
||||
case cmUnicast:
|
||||
// RTP/AVP;unicast;client_port=<client RTP port>-<client RTCP port>
|
||||
transport = cString::sprintf("RTP/AVP;unicast;client_port=%d-%d", rtpPortP, rtcpPortP);
|
||||
// RTP/AVP/TCP;unicast;client_port=<client RTP port>-<client RTCP port>
|
||||
if (useTcpP)
|
||||
transport = cString::sprintf("RTP/AVP/TCP;unicast;interleaved=%u-%u", interleavedRtpIdM, interleavedRtcpIdM);
|
||||
else
|
||||
transport = cString::sprintf("RTP/AVP;unicast;client_port=%d-%d", rtpPortP, rtcpPortP);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -203,6 +250,9 @@ bool cSatipRtsp::Setup(const char *uriP, int rtpPortP, int rtcpPortP)
|
||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEHEADER, this);
|
||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEFUNCTION, cSatipRtsp::DataCallback);
|
||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEDATA, this);
|
||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_INTERLEAVEFUNCTION, NULL);
|
||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_INTERLEAVEDATA, NULL);
|
||||
|
||||
SATIP_CURL_EASY_PERFORM(handleM);
|
||||
// Session id is now known - disable header parsing
|
||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_HEADERFUNCTION, NULL);
|
||||
@ -310,6 +360,8 @@ bool cSatipRtsp::Teardown(const char *uriP)
|
||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_RTSP_REQUEST, (long)CURL_RTSPREQ_TEARDOWN);
|
||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEFUNCTION, cSatipRtsp::DataCallback);
|
||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEDATA, this);
|
||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_INTERLEAVEFUNCTION, NULL);
|
||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_INTERLEAVEDATA, NULL);
|
||||
SATIP_CURL_EASY_PERFORM(handleM);
|
||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEFUNCTION, NULL);
|
||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEDATA, NULL);
|
||||
@ -351,6 +403,35 @@ void cSatipRtsp::ParseHeader(void)
|
||||
tunerM.SetSessionTimeout(skipspace(session), -1);
|
||||
FREE_POINTER(session);
|
||||
}
|
||||
else if (strstr(r, "Transport:")) {
|
||||
CURLcode res = CURLE_OK;
|
||||
int rtp = -1, rtcp = -1, ttl = -1;
|
||||
char *tmp = NULL, *destination = NULL, *source = NULL;
|
||||
interleavedRtpIdM = 0;
|
||||
interleavedRtcpIdM = 1;
|
||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_INTERLEAVEFUNCTION, NULL);
|
||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_INTERLEAVEDATA, NULL);
|
||||
if (sscanf(r, "Transport:%m[^;];unicast;client_port=%11d-%11d", &tmp, &rtp, &rtcp) == 3) {
|
||||
modeM = cSatipConfig::eTransportModeUnicast;
|
||||
tunerM.SetupTransport(rtp, rtcp, NULL, NULL);
|
||||
}
|
||||
else if (sscanf(r, "Transport:%m[^;];multicast;destination=%m[^;];port=%11d-%11d;ttl=%11d;source=%m[^;]", &tmp, &destination, &rtp, &rtcp, &ttl, &source) == 6 ||
|
||||
sscanf(r, "Transport:%m[^;];multicast;destination=%m[^;];port=%11d-%11d;ttl=%11d", &tmp, &destination, &rtp, &rtcp, &ttl) == 5) {
|
||||
modeM = cSatipConfig::eTransportModeMulticast;
|
||||
tunerM.SetupTransport(rtp, rtcp, destination, source);
|
||||
}
|
||||
else if (sscanf(r, "Transport:%m[^;];interleaved=%11d-%11d", &tmp, &rtp, &rtcp) == 3) {
|
||||
interleavedRtpIdM = rtp;
|
||||
interleavedRtcpIdM = rtcp;
|
||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_INTERLEAVEFUNCTION, cSatipRtsp::InterleaveCallback);
|
||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_INTERLEAVEDATA, this);
|
||||
modeM = cSatipConfig::eTransportModeRtpOverTcp;
|
||||
tunerM.SetupTransport(-1, -1, NULL, NULL);
|
||||
}
|
||||
FREE_POINTER(tmp);
|
||||
FREE_POINTER(destination);
|
||||
FREE_POINTER(source);
|
||||
}
|
||||
r = strtok_r(NULL, "\r\n", &s);
|
||||
}
|
||||
}
|
||||
@ -418,10 +499,12 @@ bool cSatipRtsp::ValidateLatestResponse(long *rcP)
|
||||
// SETUP PLAY TEARDOWN
|
||||
// The message body of the response may contain the "Out-of-Range:" parameter followed
|
||||
// by a space-separated list of the attribute names that are not understood:
|
||||
// "src" "fe" "freq" "pol" "msys" "mtype" "plts" "ro" "sr" "fec" "pids" "addpids" "delpids" "mcast
|
||||
// "src" "fe" "freq" "pol" "msys" "mtype" "plts" "ro" "sr" "fec" "pids" "addpids" "delpids" "mcast"
|
||||
if (!isempty(*errorOutOfRangeM)) {
|
||||
SATIP_CURL_EASY_GETINFO(handleM, CURLINFO_EFFECTIVE_URL, &url);
|
||||
error("Out of range: %s (error code %ld: %s) [device %d]", *errorOutOfRangeM, rc, url, tunerM.GetId());
|
||||
// Reseting the connection wouldn't help anything due to invalid channel configuration, so let it be successful
|
||||
result = true;
|
||||
break;
|
||||
}
|
||||
case 503:
|
||||
|
12
rtsp.h
12
rtsp.h
@ -22,22 +22,25 @@ class cSatipRtsp {
|
||||
private:
|
||||
static size_t HeaderCallback(char *ptrP, size_t sizeP, size_t nmembP, void *dataP);
|
||||
static size_t DataCallback(char *ptrP, size_t sizeP, size_t nmembP, void *dataP);
|
||||
static size_t InterleaveCallback(char *ptrP, size_t sizeP, size_t nmembP, void *dataP);
|
||||
static int DebugCallback(CURL *handleP, curl_infotype typeP, char *dataP, size_t sizeP, void *userPtrP);
|
||||
|
||||
enum {
|
||||
eConnectTimeoutMs = 1500, // in milliseconds
|
||||
eConnectTimeoutMs = 1500, // in milliseconds
|
||||
eMaxDownloadSpeedMBits = 20, // in megabits per second
|
||||
};
|
||||
enum eCommunicationMode { cmUnicast, cmMulticast };
|
||||
|
||||
cSatipTunerIf &tunerM;
|
||||
cSatipMemoryBuffer headerBufferM;
|
||||
cSatipMemoryBuffer dataBufferM;
|
||||
eCommunicationMode modeM;
|
||||
CURL *handleM;
|
||||
struct curl_slist *headerListM;
|
||||
cString errorNoMoreM;
|
||||
cString errorOutOfRangeM;
|
||||
cString errorCheckSyntaxM;
|
||||
int modeM;
|
||||
unsigned int interleavedRtpIdM;
|
||||
unsigned int interleavedRtcpIdM;
|
||||
|
||||
void Create(void);
|
||||
void Destroy(void);
|
||||
@ -53,10 +56,11 @@ public:
|
||||
explicit cSatipRtsp(cSatipTunerIf &tunerP);
|
||||
virtual ~cSatipRtsp();
|
||||
|
||||
cString GetActiveMode(void);
|
||||
cString RtspUnescapeString(const char *strP);
|
||||
void Reset(void);
|
||||
bool Options(const char *uriP);
|
||||
bool Setup(const char *uriP, int rtpPortP, int rtcpPortP);
|
||||
bool Setup(const char *uriP, int rtpPortP, int rtcpPortP, bool useTcpP);
|
||||
bool SetSession(const char *sessionP);
|
||||
bool Describe(const char *uriP);
|
||||
bool Play(const char *uriP);
|
||||
|
80
satip.c
80
satip.c
@ -27,7 +27,7 @@
|
||||
#define GITVERSION ""
|
||||
#endif
|
||||
|
||||
const char VERSION[] = "2.2.3" GITVERSION;
|
||||
const char VERSION[] = "2.2.4" GITVERSION;
|
||||
static const char DESCRIPTION[] = trNOOP("SAT>IP Devices");
|
||||
|
||||
class cPluginSatip : public cPlugin {
|
||||
@ -35,6 +35,7 @@ private:
|
||||
unsigned int deviceCountM;
|
||||
cSatipDiscoverServers *serversM;
|
||||
void ParseServer(const char *paramP);
|
||||
void ParsePortRange(const char *paramP);
|
||||
int ParseCicams(const char *valueP, int *cicamsP);
|
||||
int ParseSources(const char *valueP, int *sourcesP);
|
||||
int ParseFilters(const char *valueP, int *filtersP);
|
||||
@ -83,11 +84,13 @@ const char *cPluginSatip::CommandLineHelp(void)
|
||||
// Return a string that describes all known command line options.
|
||||
return " -d <num>, --devices=<number> set number of devices to be created\n"
|
||||
" -t <mode>, --trace=<mode> set the tracing mode\n"
|
||||
" -s <ipaddr>|<model>|<desc>, --server=<ipaddr1>|<model1>|<desc1>;<ipaddr2>|<model2>|<desc2>\n"
|
||||
" -s <ipaddr>|<model>|<desc>, --server=<ipaddr1>|<model1>|<desc1>;<ipaddr2>:<port>|<model2>:<filter>|<desc2>:<quirk>\n"
|
||||
" define hard-coded SAT>IP server(s)\n"
|
||||
" -D, --detach set the detached mode on\n"
|
||||
" -S, --single set the single model server mode on\n"
|
||||
" -n, --noquirks disable all the server quirks\n";
|
||||
" -n, --noquirks disable autodetection of the server quirks\n"
|
||||
" -p, --portrange=<start>-<end> set a range of ports used for the RT[C]P server\n"
|
||||
" a minimum of 2 ports per device is required.\n";
|
||||
}
|
||||
|
||||
bool cPluginSatip::ProcessArgs(int argc, char *argv[])
|
||||
@ -98,6 +101,7 @@ bool cPluginSatip::ProcessArgs(int argc, char *argv[])
|
||||
{ "devices", required_argument, NULL, 'd' },
|
||||
{ "trace", required_argument, NULL, 't' },
|
||||
{ "server", required_argument, NULL, 's' },
|
||||
{ "portrange",required_argument, NULL, 'p' },
|
||||
{ "detach", no_argument, NULL, 'D' },
|
||||
{ "single", no_argument, NULL, 'S' },
|
||||
{ "noquirks", no_argument, NULL, 'n' },
|
||||
@ -105,8 +109,9 @@ bool cPluginSatip::ProcessArgs(int argc, char *argv[])
|
||||
};
|
||||
|
||||
cString server;
|
||||
cString portrange;
|
||||
int c;
|
||||
while ((c = getopt_long(argc, argv, "d:t:s:DSn", long_options, NULL)) != -1) {
|
||||
while ((c = getopt_long(argc, argv, "d:t:s:p:DSn", long_options, NULL)) != -1) {
|
||||
switch (c) {
|
||||
case 'd':
|
||||
deviceCountM = strtol(optarg, NULL, 0);
|
||||
@ -126,10 +131,15 @@ bool cPluginSatip::ProcessArgs(int argc, char *argv[])
|
||||
case 'n':
|
||||
SatipConfig.SetDisableServerQuirks(true);
|
||||
break;
|
||||
case 'p':
|
||||
portrange = optarg;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (!isempty(*portrange))
|
||||
ParsePortRange(portrange);
|
||||
// this must be done after all parameters are parsed
|
||||
if (!isempty(*server))
|
||||
ParseServer(*server);
|
||||
@ -222,7 +232,9 @@ void cPluginSatip::ParseServer(const char *paramP)
|
||||
while (r) {
|
||||
r = skipspace(r);
|
||||
debug3("%s server[%d]=%s", __PRETTY_FUNCTION__, n, r);
|
||||
cString serverAddr, serverModel, serverDescription;
|
||||
cString serverAddr, serverModel, serverFilters, serverDescription;
|
||||
int serverQuirk = cSatipServer::eSatipQuirkNone;
|
||||
int serverPort = SATIP_DEFAULT_RTSP_PORT;
|
||||
int n2 = 0;
|
||||
char *s2, *p2 = r;
|
||||
char *r2 = strtok_r(p2, "|", &s2);
|
||||
@ -230,13 +242,34 @@ void cPluginSatip::ParseServer(const char *paramP)
|
||||
debug3("%s param[%d]=%s", __PRETTY_FUNCTION__, n2, r2);
|
||||
switch (n2++) {
|
||||
case 0:
|
||||
{
|
||||
serverAddr = r2;
|
||||
char *r3 = strchr(r2, ':');
|
||||
if (r3) {
|
||||
serverPort = strtol(r3 + 1, NULL, 0);
|
||||
serverAddr = serverAddr.Truncate(r3 - r2);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
{
|
||||
serverModel = r2;
|
||||
char *r3 = strchr(r2, ':');
|
||||
if (r3) {
|
||||
serverFilters = r3 + 1;
|
||||
serverModel = serverModel.Truncate(r3 - r2);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
{
|
||||
serverDescription = r2;
|
||||
char *r3 = strchr(r2, ':');
|
||||
if (r3) {
|
||||
serverQuirk = strtol(r3 + 1, NULL, 0);
|
||||
serverDescription = serverDescription.Truncate(r3 - r2);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@ -244,10 +277,10 @@ void cPluginSatip::ParseServer(const char *paramP)
|
||||
r2 = strtok_r(NULL, "|", &s2);
|
||||
}
|
||||
if (*serverAddr && *serverModel && *serverDescription) {
|
||||
debug1("%s ipaddr=%s model=%s desc=%s", __PRETTY_FUNCTION__, *serverAddr, *serverModel, *serverDescription);
|
||||
debug1("%s ipaddr=%s port=%d model=%s (%s) desc=%s (%d)", __PRETTY_FUNCTION__, *serverAddr, serverPort, *serverModel, *serverFilters, *serverDescription, serverQuirk);
|
||||
if (!serversM)
|
||||
serversM = new cSatipDiscoverServers();
|
||||
serversM->Add(new cSatipDiscoverServer(*serverAddr, *serverModel, *serverDescription));
|
||||
serversM->Add(new cSatipDiscoverServer(*serverAddr, serverPort, *serverModel, *serverFilters, *serverDescription, serverQuirk));
|
||||
}
|
||||
++n;
|
||||
r = strtok_r(NULL, ";", &s);
|
||||
@ -255,6 +288,37 @@ void cPluginSatip::ParseServer(const char *paramP)
|
||||
FREE_POINTER(p);
|
||||
}
|
||||
|
||||
void cPluginSatip::ParsePortRange(const char *paramP)
|
||||
{
|
||||
char *s, *p = skipspace(paramP);
|
||||
char *r = strtok_r(p, "-", &s);
|
||||
unsigned int rangeStart = 0;
|
||||
unsigned int rangeStop = 0;
|
||||
if (r) {
|
||||
rangeStart = strtol(r, NULL, 0);
|
||||
r = strtok_r(NULL, "-", &s);
|
||||
}
|
||||
if (r)
|
||||
rangeStop = strtol(r, NULL, 0);
|
||||
else {
|
||||
error("Port range argument not valid '%s'", paramP);
|
||||
rangeStart = 0;
|
||||
rangeStop = 0;
|
||||
}
|
||||
if (rangeStart % 2) {
|
||||
error("The given range start port must be even!");
|
||||
rangeStart = 0;
|
||||
rangeStop = 0;
|
||||
}
|
||||
else if (rangeStop - rangeStart + 1 < deviceCountM * 2) {
|
||||
error("The given port range is to small: %d < %d!", rangeStop - rangeStart + 1, deviceCountM * 2);
|
||||
rangeStart = 0;
|
||||
rangeStop = 0;
|
||||
}
|
||||
SatipConfig.SetPortRangeStart(rangeStart);
|
||||
SatipConfig.SetPortRangeStop(rangeStop);
|
||||
}
|
||||
|
||||
int cPluginSatip::ParseCicams(const char *valueP, int *cicamsP)
|
||||
{
|
||||
debug1("%s (%s,)", __PRETTY_FUNCTION__, valueP);
|
||||
@ -342,6 +406,8 @@ bool cPluginSatip::SetupParse(const char *nameP, const char *valueP)
|
||||
for (unsigned int i = 0; i < DisabledFiltersCount; ++i)
|
||||
SatipConfig.SetDisabledFilters(i, DisabledFilters[i]);
|
||||
}
|
||||
else if (!strcasecmp(nameP, "TransportMode"))
|
||||
SatipConfig.SetTransportMode(atoi(valueP));
|
||||
else
|
||||
return false;
|
||||
return true;
|
||||
|
@ -338,6 +338,19 @@ cString cSatipSectionFilterHandler::GetInformation(void)
|
||||
return s;
|
||||
}
|
||||
|
||||
bool cSatipSectionFilterHandler::Exists(u_short pidP)
|
||||
{
|
||||
debug16("%s (%d) [device %d]", __PRETTY_FUNCTION__, pidP, deviceIndexM);
|
||||
cMutexLock MutexLock(&mutexM);
|
||||
for (unsigned int i = 0; i < eMaxSecFilterCount; ++i) {
|
||||
if (filtersM[i] && (pidP == filtersM[i]->GetPid())) {
|
||||
debug12("%s (%d) Found [device %d]", __PRETTY_FUNCTION__, pidP, deviceIndexM);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool cSatipSectionFilterHandler::Delete(unsigned int indexP)
|
||||
{
|
||||
debug16("%s (%d) [device %d]", __PRETTY_FUNCTION__, indexP, deviceIndexM);
|
||||
|
@ -80,6 +80,7 @@ public:
|
||||
cSatipSectionFilterHandler(int deviceIndexP, unsigned int bufferLenP);
|
||||
virtual ~cSatipSectionFilterHandler();
|
||||
cString GetInformation(void);
|
||||
bool Exists(u_short pidP);
|
||||
int Open(u_short pidP, u_char tidP, u_char maskP);
|
||||
void Close(int handleP);
|
||||
int GetPid(int handleP);
|
||||
|
196
server.c
196
server.c
@ -80,16 +80,38 @@ bool cSatipFrontends::Detach(int deviceIdP, int transponderP)
|
||||
|
||||
// --- cSatipServer -----------------------------------------------------------
|
||||
|
||||
cSatipServer::cSatipServer(const char *addressP, const char *modelP, const char *descriptionP)
|
||||
cSatipServer::cSatipServer(const char *addressP, const int portP, const char *modelP, const char *filtersP, const char *descriptionP, const int quirkP)
|
||||
: addressM((addressP && *addressP) ? addressP : "0.0.0.0"),
|
||||
modelM((modelP && *modelP) ? modelP : "DVBS-1"),
|
||||
filtersM((filtersP && *filtersP) ? filtersP : ""),
|
||||
descriptionM(!isempty(descriptionP) ? descriptionP : "MyBrokenHardware"),
|
||||
quirksM(""),
|
||||
quirkM(eSatipQuirkNone),
|
||||
portM(portP),
|
||||
quirkM(quirkP),
|
||||
hasCiM(false),
|
||||
activeM(true),
|
||||
createdM(time(NULL)),
|
||||
lastSeenM(0)
|
||||
{
|
||||
memset(sourceFiltersM, 0, sizeof(sourceFiltersM));
|
||||
if (!isempty(*filtersM)) {
|
||||
char *s, *p = strdup(*filtersM);
|
||||
char *r = strtok_r(p, ",", &s);
|
||||
unsigned int i = 0;
|
||||
while (r) {
|
||||
int t = cSource::FromString(skipspace(r));
|
||||
if (t && i < ELEMENTS(sourceFiltersM))
|
||||
sourceFiltersM[i++] = t;
|
||||
r = strtok_r(NULL, ",", &s);
|
||||
}
|
||||
if (i) {
|
||||
filtersM = "";
|
||||
for (unsigned int j = 0; j < i; ++j)
|
||||
filtersM = cString::sprintf("%s%s%s", *filtersM, isempty(*filtersM) ? "" : ",", *cSource::ToString(sourceFiltersM[j]));
|
||||
debug3("%s filters=%s", __PRETTY_FUNCTION__, *filtersM);
|
||||
}
|
||||
FREE_POINTER(p);
|
||||
}
|
||||
if (!SatipConfig.GetDisableServerQuirks()) {
|
||||
// These devices contain a session id bug:
|
||||
// Inverto Airscreen Server IDL 400 ?
|
||||
@ -97,28 +119,61 @@ cSatipServer::cSatipServer(const char *addressP, const char *modelP, const char
|
||||
if (strstr(*descriptionM, "GSSBOX") || // Grundig Sat Systems GSS.box DSI 400
|
||||
strstr(*descriptionM, "DIGIBIT") || // Telestar Digibit R1
|
||||
strstr(*descriptionM, "Triax SatIP Converter") // Triax TSS 400
|
||||
) {
|
||||
)
|
||||
quirkM |= eSatipQuirkSessionId;
|
||||
quirksM = cString::sprintf("%s%sSessionId", *quirksM, isempty(*quirksM) ? "" : ",");
|
||||
}
|
||||
// These devices contain support for RTP over TCP:
|
||||
if (strstr(*descriptionM, "minisatip") || // minisatip server
|
||||
strstr(*descriptionM, "DVBViewer") || // DVBViewer Media Server
|
||||
strstr(*descriptionM, "GSSBOX") || // Grundig Sat Systems GSS.box DSI 400
|
||||
strstr(*descriptionM, "DIGIBIT") || // Telestar Digibit R1
|
||||
strstr(*descriptionM, "Triax SatIP Converter") // Triax TSS 400
|
||||
)
|
||||
quirkM |= eSatipQuirkRtpOverTcp;
|
||||
// These devices contain a play (add/delpids) parameter bug:
|
||||
if (strstr(*descriptionM, "fritzdvbc") // Fritz!WLAN Repeater DVB-C
|
||||
) {
|
||||
)
|
||||
quirkM |= eSatipQuirkPlayPids;
|
||||
quirksM = cString::sprintf("%s%sPlayPids", *quirksM, isempty(*quirksM) ? "" : ",");
|
||||
}
|
||||
// These devices contain a frontend locking bug:
|
||||
if (strstr(*descriptionM, "fritzdvbc") || // Fritz!WLAN Repeater DVB-C
|
||||
strstr(*descriptionM, "Schwaiger Sat>IP Server") // Schwaiger MS41IP
|
||||
) {
|
||||
)
|
||||
quirkM |= eSatipQuirkForceLock;
|
||||
quirksM = cString::sprintf("%s%sForceLock", *quirksM, isempty(*quirksM) ? "" : ",");
|
||||
}
|
||||
debug3("%s description=%s quirks=%s", __PRETTY_FUNCTION__, *descriptionM, *quirksM);
|
||||
// These devices support the X_PMT protocol extension
|
||||
if (strstr(*descriptionM, "OctopusNet") || // Digital Devices OctopusNet
|
||||
strstr(*descriptionM, "minisatip") // minisatip server
|
||||
)
|
||||
quirkM |= eSatipQuirkCiXpmt;
|
||||
// These devices support the TNR protocol extension
|
||||
if (strstr(*descriptionM, "DVBViewer") // DVBViewer Media Server
|
||||
)
|
||||
quirkM |= eSatipQuirkCiTnr;
|
||||
// These devices don't support auto-detection of pilot tones
|
||||
if (strstr(*descriptionM, "GSSBOX") || // Grundig Sat Systems GSS.box DSI 400
|
||||
strstr(*descriptionM, "DIGIBIT") || // Telestar Digibit R1
|
||||
strstr(*descriptionM, "Triax SatIP Converter") // Triax TSS 400
|
||||
// Kathrein ExIP 414/E
|
||||
)
|
||||
quirkM |= eSatipQuirkForcePilot;
|
||||
}
|
||||
// These devices support the X_PMT protocol extension
|
||||
if ((quirkM & eSatipQuirkMask) & eSatipQuirkSessionId)
|
||||
quirksM = cString::sprintf("%s%sSessionId", *quirksM, isempty(*quirksM) ? "" : ",");
|
||||
if ((quirkM & eSatipQuirkMask) & eSatipQuirkPlayPids)
|
||||
quirksM = cString::sprintf("%s%sPlayPids", *quirksM, isempty(*quirksM) ? "" : ",");
|
||||
if ((quirkM & eSatipQuirkMask) & eSatipQuirkForceLock)
|
||||
quirksM = cString::sprintf("%s%sForceLock", *quirksM, isempty(*quirksM) ? "" : ",");
|
||||
if ((quirkM & eSatipQuirkMask) & eSatipQuirkRtpOverTcp)
|
||||
quirksM = cString::sprintf("%s%sRtpOverTcp", *quirksM, isempty(*quirksM) ? "" : ",");
|
||||
if ((quirkM & eSatipQuirkMask) & eSatipQuirkCiXpmt)
|
||||
quirksM = cString::sprintf("%s%sCiXpmt", *quirksM, isempty(*quirksM) ? "" : ",");
|
||||
if ((quirkM & eSatipQuirkMask) & eSatipQuirkCiTnr)
|
||||
quirksM = cString::sprintf("%s%sCiTnr", *quirksM, isempty(*quirksM) ? "" : ",");
|
||||
if ((quirkM & eSatipQuirkMask) & eSatipQuirkForcePilot)
|
||||
quirksM = cString::sprintf("%s%sForcePilot", *quirksM, isempty(*quirksM) ? "" : ",");
|
||||
debug3("%s description=%s quirks=%s", __PRETTY_FUNCTION__, *descriptionM, *quirksM);
|
||||
// These devices support external CI
|
||||
if (strstr(*descriptionM, "OctopusNet") || // Digital Devices OctopusNet
|
||||
strstr(*descriptionM, "minisatip") // minisatip server
|
||||
strstr(*descriptionM, "minisatip") || // minisatip server
|
||||
strstr(*descriptionM, "DVBViewer") // DVBViewer Media Server
|
||||
) {
|
||||
hasCiM = true;
|
||||
}
|
||||
@ -153,7 +208,7 @@ cSatipServer::cSatipServer(const char *addressP, const char *modelP, const char
|
||||
}
|
||||
r = strtok_r(NULL, ",", &s);
|
||||
}
|
||||
free(p);
|
||||
FREE_POINTER(p);
|
||||
}
|
||||
|
||||
cSatipServer::~cSatipServer()
|
||||
@ -172,53 +227,72 @@ int cSatipServer::Compare(const cListObject &listObjectP) const
|
||||
return result;
|
||||
}
|
||||
|
||||
bool cSatipServer::IsValidSource(int sourceP)
|
||||
{
|
||||
if (sourceFiltersM[0]) {
|
||||
for (unsigned int i = 0; i < ELEMENTS(sourceFiltersM); ++i) {
|
||||
if (sourceP == sourceFiltersM[i]) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool cSatipServer::Assign(int deviceIdP, int sourceP, int systemP, int transponderP)
|
||||
{
|
||||
bool result = false;
|
||||
if (cSource::IsType(sourceP, 'S'))
|
||||
result = frontendsM[eSatipFrontendDVBS2].Assign(deviceIdP, transponderP);
|
||||
else if (cSource::IsType(sourceP, 'T')) {
|
||||
if (systemP)
|
||||
result = frontendsM[eSatipFrontendDVBT2].Assign(deviceIdP, transponderP);
|
||||
else
|
||||
result = frontendsM[eSatipFrontendDVBT].Assign(deviceIdP, transponderP) || frontendsM[eSatipFrontendDVBT2].Assign(deviceIdP, transponderP);
|
||||
}
|
||||
else if (cSource::IsType(sourceP, 'C')) {
|
||||
if (systemP)
|
||||
result = frontendsM[eSatipFrontendDVBC2].Assign(deviceIdP, transponderP);
|
||||
else
|
||||
result = frontendsM[eSatipFrontendDVBC].Assign(deviceIdP, transponderP) || frontendsM[eSatipFrontendDVBC2].Assign(deviceIdP, transponderP);
|
||||
if (IsValidSource(sourceP)) {
|
||||
if (cSource::IsType(sourceP, 'S'))
|
||||
result = frontendsM[eSatipFrontendDVBS2].Assign(deviceIdP, transponderP);
|
||||
else if (cSource::IsType(sourceP, 'T')) {
|
||||
if (systemP)
|
||||
result = frontendsM[eSatipFrontendDVBT2].Assign(deviceIdP, transponderP);
|
||||
else
|
||||
result = frontendsM[eSatipFrontendDVBT].Assign(deviceIdP, transponderP) || frontendsM[eSatipFrontendDVBT2].Assign(deviceIdP, transponderP);
|
||||
}
|
||||
else if (cSource::IsType(sourceP, 'C')) {
|
||||
if (systemP)
|
||||
result = frontendsM[eSatipFrontendDVBC2].Assign(deviceIdP, transponderP);
|
||||
else
|
||||
result = frontendsM[eSatipFrontendDVBC].Assign(deviceIdP, transponderP) || frontendsM[eSatipFrontendDVBC2].Assign(deviceIdP, transponderP);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
bool cSatipServer::Matches(int sourceP)
|
||||
{
|
||||
if (cSource::IsType(sourceP, 'S'))
|
||||
return GetModulesDVBS2();
|
||||
else if (cSource::IsType(sourceP, 'T'))
|
||||
return GetModulesDVBT() || GetModulesDVBT2();
|
||||
else if (cSource::IsType(sourceP, 'C'))
|
||||
return GetModulesDVBC() || GetModulesDVBC2();
|
||||
if (IsValidSource(sourceP)) {
|
||||
if (cSource::IsType(sourceP, 'S'))
|
||||
return GetModulesDVBS2();
|
||||
else if (cSource::IsType(sourceP, 'T'))
|
||||
return GetModulesDVBT() || GetModulesDVBT2();
|
||||
else if (cSource::IsType(sourceP, 'C'))
|
||||
return GetModulesDVBC() || GetModulesDVBC2();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool cSatipServer::Matches(int deviceIdP, int sourceP, int systemP, int transponderP)
|
||||
{
|
||||
bool result = false;
|
||||
if (cSource::IsType(sourceP, 'S'))
|
||||
result = frontendsM[eSatipFrontendDVBS2].Matches(deviceIdP, transponderP);
|
||||
else if (cSource::IsType(sourceP, 'T')) {
|
||||
if (systemP)
|
||||
result = frontendsM[eSatipFrontendDVBT2].Matches(deviceIdP, transponderP);
|
||||
else
|
||||
result = frontendsM[eSatipFrontendDVBT].Matches(deviceIdP, transponderP) || frontendsM[eSatipFrontendDVBT2].Matches(deviceIdP, transponderP);
|
||||
}
|
||||
else if (cSource::IsType(sourceP, 'C')) {
|
||||
if (systemP)
|
||||
result = frontendsM[eSatipFrontendDVBC2].Matches(deviceIdP, transponderP);
|
||||
else
|
||||
result = frontendsM[eSatipFrontendDVBC].Matches(deviceIdP, transponderP) || frontendsM[eSatipFrontendDVBC2].Matches(deviceIdP, transponderP);
|
||||
if (IsValidSource(sourceP)) {
|
||||
if (cSource::IsType(sourceP, 'S'))
|
||||
result = frontendsM[eSatipFrontendDVBS2].Matches(deviceIdP, transponderP);
|
||||
else if (cSource::IsType(sourceP, 'T')) {
|
||||
if (systemP)
|
||||
result = frontendsM[eSatipFrontendDVBT2].Matches(deviceIdP, transponderP);
|
||||
else
|
||||
result = frontendsM[eSatipFrontendDVBT].Matches(deviceIdP, transponderP) || frontendsM[eSatipFrontendDVBT2].Matches(deviceIdP, transponderP);
|
||||
}
|
||||
else if (cSource::IsType(sourceP, 'C')) {
|
||||
if (systemP)
|
||||
result = frontendsM[eSatipFrontendDVBC2].Matches(deviceIdP, transponderP);
|
||||
else
|
||||
result = frontendsM[eSatipFrontendDVBC].Matches(deviceIdP, transponderP) || frontendsM[eSatipFrontendDVBC2].Matches(deviceIdP, transponderP);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@ -287,11 +361,11 @@ cSatipServer *cSatipServers::Find(int sourceP)
|
||||
cSatipServer *cSatipServers::Assign(int deviceIdP, int sourceP, int transponderP, int systemP)
|
||||
{
|
||||
for (cSatipServer *s = First(); s; s = Next(s)) {
|
||||
if (s->Matches(deviceIdP, sourceP, systemP, transponderP))
|
||||
if (s->IsActive() && s->Matches(deviceIdP, sourceP, systemP, transponderP))
|
||||
return s;
|
||||
}
|
||||
for (cSatipServer *s = First(); s; s = Next(s)) {
|
||||
if (s->Assign(deviceIdP, sourceP, systemP, transponderP))
|
||||
if (s->IsActive() && s->Assign(deviceIdP, sourceP, systemP, transponderP))
|
||||
return s;
|
||||
}
|
||||
return NULL;
|
||||
@ -308,6 +382,16 @@ cSatipServer *cSatipServers::Update(cSatipServer *serverP)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void cSatipServers::Activate(cSatipServer *serverP, bool onOffP)
|
||||
{
|
||||
for (cSatipServer *s = First(); s; s = Next(s)) {
|
||||
if (s == serverP) {
|
||||
s->Activate(onOffP);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void cSatipServers::Attach(cSatipServer *serverP, int deviceIdP, int transponderP)
|
||||
{
|
||||
for (cSatipServer *s = First(); s; s = Next(s)) {
|
||||
@ -374,6 +458,18 @@ cString cSatipServers::GetAddress(cSatipServer *serverP)
|
||||
return address;
|
||||
}
|
||||
|
||||
int cSatipServers::GetPort(cSatipServer *serverP)
|
||||
{
|
||||
int port = SATIP_DEFAULT_RTSP_PORT;
|
||||
for (cSatipServer *s = First(); s; s = Next(s)) {
|
||||
if (s == serverP) {
|
||||
port = s->Port();
|
||||
break;
|
||||
}
|
||||
}
|
||||
return port;
|
||||
}
|
||||
|
||||
cString cSatipServers::GetString(cSatipServer *serverP)
|
||||
{
|
||||
cString list = "";
|
||||
@ -390,7 +486,7 @@ 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());
|
||||
list = cString::sprintf("%s%c %s|%s|%s\n", *list, s->IsActive() ? '+' : '-', s->Address(), s->Model(), s->Description());
|
||||
return list;
|
||||
}
|
||||
|
||||
|
30
server.h
30
server.h
@ -54,25 +54,37 @@ private:
|
||||
eSatipFrontendDVBC2,
|
||||
eSatipFrontendCount
|
||||
};
|
||||
enum {
|
||||
eSatipMaxSourceFilters = 16
|
||||
};
|
||||
cString addressM;
|
||||
cString modelM;
|
||||
cString filtersM;
|
||||
cString descriptionM;
|
||||
cString quirksM;
|
||||
cSatipFrontends frontendsM[eSatipFrontendCount];
|
||||
int sourceFiltersM[eSatipMaxSourceFilters];
|
||||
int portM;
|
||||
int quirkM;
|
||||
bool hasCiM;
|
||||
bool activeM;
|
||||
time_t createdM;
|
||||
cTimeMs lastSeenM;
|
||||
bool IsValidSource(int sourceP);
|
||||
|
||||
public:
|
||||
enum eSatipQuirk {
|
||||
eSatipQuirkNone = 0x00,
|
||||
eSatipQuirkSessionId = 0x01,
|
||||
eSatipQuirkPlayPids = 0x02,
|
||||
eSatipQuirkForceLock = 0x04,
|
||||
eSatipQuirkMask = 0x0F
|
||||
eSatipQuirkNone = 0x00,
|
||||
eSatipQuirkSessionId = 0x01,
|
||||
eSatipQuirkPlayPids = 0x02,
|
||||
eSatipQuirkForceLock = 0x04,
|
||||
eSatipQuirkRtpOverTcp = 0x08,
|
||||
eSatipQuirkCiXpmt = 0x10,
|
||||
eSatipQuirkCiTnr = 0x20,
|
||||
eSatipQuirkForcePilot = 0x40,
|
||||
eSatipQuirkMask = 0xFF
|
||||
};
|
||||
cSatipServer(const char *addressP, const char *modelP, const char *descriptionP);
|
||||
cSatipServer(const char *addressP, const int portP, const char *modelP, const char *filtersP, const char *descriptionP, const int quirkP);
|
||||
virtual ~cSatipServer();
|
||||
virtual int Compare(const cListObject &listObjectP) const;
|
||||
bool Assign(int deviceIdP, int sourceP, int systemP, int transponderP);
|
||||
@ -85,13 +97,17 @@ public:
|
||||
int GetModulesDVBT2(void);
|
||||
int GetModulesDVBC(void);
|
||||
int GetModulesDVBC2(void);
|
||||
void Activate(bool onOffP) { activeM = onOffP; }
|
||||
const char *Address(void) { return *addressM; }
|
||||
const char *Model(void) { return *modelM; }
|
||||
const char *Filters(void) { return *filtersM; }
|
||||
const char *Description(void) { return *descriptionM; }
|
||||
const char *Quirks(void) { return *quirksM; }
|
||||
int Port(void) { return portM; }
|
||||
bool Quirk(int quirkP) { return ((quirkP & eSatipQuirkMask) & quirkM); }
|
||||
bool HasQuirk(void) { return (quirkM != eSatipQuirkNone); }
|
||||
bool HasCI(void) { return hasCiM; }
|
||||
bool IsActive(void) { return activeM; }
|
||||
void Update(void) { lastSeenM.Set(); }
|
||||
uint64_t LastSeen(void) { return lastSeenM.Elapsed(); }
|
||||
time_t Created(void) { return createdM; }
|
||||
@ -105,6 +121,7 @@ public:
|
||||
cSatipServer *Find(int sourceP);
|
||||
cSatipServer *Assign(int deviceIdP, int sourceP, int transponderP, int systemP);
|
||||
cSatipServer *Update(cSatipServer *serverP);
|
||||
void Activate(cSatipServer *serverP, bool onOffP);
|
||||
void Attach(cSatipServer *serverP, int deviceIdP, int transponderP);
|
||||
void Detach(cSatipServer *serverP, int deviceIdP, int transponderP);
|
||||
bool IsQuirk(cSatipServer *serverP, int quirkP);
|
||||
@ -112,6 +129,7 @@ public:
|
||||
void Cleanup(uint64_t intervalMsP = 0);
|
||||
cString GetAddress(cSatipServer *serverP);
|
||||
cString GetString(cSatipServer *serverP);
|
||||
int GetPort(cSatipServer *serverP);
|
||||
cString List(void);
|
||||
int NumProvidedSystems(void);
|
||||
};
|
||||
|
28
setup.c
28
setup.c
@ -86,6 +86,8 @@ eOSState cSatipEditSrcItem::ProcessKey(eKeys Key)
|
||||
class cSatipServerInfo : public cOsdMenu
|
||||
{
|
||||
private:
|
||||
cSatipServer *serverM;
|
||||
int activeM;
|
||||
cString addressM;
|
||||
cString modelM;
|
||||
cString descriptionM;
|
||||
@ -101,6 +103,8 @@ public:
|
||||
|
||||
cSatipServerInfo::cSatipServerInfo(cSatipServer *serverP)
|
||||
: cOsdMenu(tr("SAT>IP Server"), 20),
|
||||
serverM(serverP),
|
||||
activeM(serverP && serverP->IsActive()),
|
||||
addressM(serverP ? serverP->Address() : "---"),
|
||||
modelM(serverP ? serverP->Model() : "---"),
|
||||
descriptionM(serverP ? serverP->Description() : "---"),
|
||||
@ -118,6 +122,7 @@ cSatipServerInfo::~cSatipServerInfo()
|
||||
|
||||
void cSatipServerInfo::Setup(void)
|
||||
{
|
||||
Add(new cMenuEditBoolItem(trVDR("Active"), &activeM));
|
||||
Add(new cOsdItem(cString::sprintf("%s:\t%s", tr("Address"), *addressM), osUnknown, false));
|
||||
Add(new cOsdItem(cString::sprintf("%s:\t%s", tr("Model"), *modelM), osUnknown, false));
|
||||
Add(new cOsdItem(cString::sprintf("%s:\t%s", tr("Description"), *descriptionM), osUnknown, false));
|
||||
@ -127,6 +132,7 @@ void cSatipServerInfo::Setup(void)
|
||||
|
||||
eOSState cSatipServerInfo::ProcessKey(eKeys keyP)
|
||||
{
|
||||
int oldActive = activeM;
|
||||
eOSState state = cOsdMenu::ProcessKey(keyP);
|
||||
|
||||
if (state == osUnknown) {
|
||||
@ -135,6 +141,12 @@ eOSState cSatipServerInfo::ProcessKey(eKeys keyP)
|
||||
default: state = osContinue; break;
|
||||
}
|
||||
}
|
||||
|
||||
if (keyP != kNone && oldActive != activeM) {
|
||||
cSatipDiscover::GetInstance()->ActivateServer(serverM, activeM);
|
||||
Setup();
|
||||
}
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
@ -155,7 +167,7 @@ cSatipServerItem::cSatipServerItem(cSatipServer *serverP)
|
||||
{
|
||||
SetSelectable(true);
|
||||
// Must begin with a '#' character!
|
||||
SetText(*cString::sprintf("# %s (%s)\t%s", serverM->Address(), serverM->Model(), serverM->Description()));
|
||||
SetText(*cString::sprintf("%s %s (%s)\t%s", serverM->IsActive() ? "+" : "-", serverM->Address(), serverM->Model(), serverM->Description()));
|
||||
}
|
||||
|
||||
void cSatipServerItem::SetMenuItem(cSkinDisplayMenu *displayMenuP, int indexP, bool currentP, bool selectableP)
|
||||
@ -333,6 +345,7 @@ cSatipPluginSetup::cSatipPluginSetup()
|
||||
: detachedModeM(SatipConfig.GetDetachedMode()),
|
||||
deviceCountM(0),
|
||||
operatingModeM(SatipConfig.GetOperatingMode()),
|
||||
transportModeM(SatipConfig.GetTransportMode()),
|
||||
ciExtensionM(SatipConfig.GetCIExtension()),
|
||||
eitScanM(SatipConfig.GetEITScan()),
|
||||
numDisabledSourcesM(SatipConfig.GetDisabledSourcesCount()),
|
||||
@ -343,6 +356,9 @@ cSatipPluginSetup::cSatipPluginSetup()
|
||||
operatingModeTextsM[cSatipConfig::eOperatingModeLow] = tr("low");
|
||||
operatingModeTextsM[cSatipConfig::eOperatingModeNormal] = tr("normal");
|
||||
operatingModeTextsM[cSatipConfig::eOperatingModeHigh] = tr("high");
|
||||
transportModeTextsM[cSatipConfig::eTransportModeUnicast] = tr("Unicast");
|
||||
transportModeTextsM[cSatipConfig::eTransportModeMulticast] = tr("Multicast");
|
||||
transportModeTextsM[cSatipConfig::eTransportModeRtpOverTcp] = tr("RTP-over-TCP");
|
||||
for (unsigned int i = 0; i < ELEMENTS(cicamsM); ++i)
|
||||
cicamsM[i] = SatipConfig.GetCICAM(i);
|
||||
for (unsigned int i = 0; i < ELEMENTS(ca_systems_table); ++i)
|
||||
@ -400,6 +416,8 @@ void cSatipPluginSetup::Setup(void)
|
||||
helpM.Append(tr("Define an ill-behaving filter to be blacklisted."));
|
||||
}
|
||||
}
|
||||
Add(new cMenuEditStraItem(tr("Transport mode"), &transportModeM, ELEMENTS(transportModeTextsM), transportModeTextsM));
|
||||
helpM.Append(tr("Define which transport mode shall be used.\n\nUnicast, Multicast, RTP-over-TCP"));
|
||||
Add(new cOsdItem(tr("Active SAT>IP servers:"), osUnknown, false));
|
||||
helpM.Append("");
|
||||
|
||||
@ -465,10 +483,12 @@ eOSState cSatipPluginSetup::ProcessKey(eKeys keyP)
|
||||
int oldNumDisabledFilters = numDisabledFiltersM;
|
||||
eOSState state = cMenuSetupPage::ProcessKey(keyP);
|
||||
|
||||
// Ugly hack with hardcoded '#' character :(
|
||||
// Ugly hack with hardcoded '+/-' characters :(
|
||||
const char *p = Get(Current())->Text();
|
||||
if (!hadSubMenu && !HasSubMenu() && (*p == '#') && (keyP == kOk))
|
||||
if (!hadSubMenu && !HasSubMenu() && p && (*p == '+' || *p == '-') && (keyP == kOk))
|
||||
return DeviceInfo();
|
||||
if (hadSubMenu && !HasSubMenu())
|
||||
Setup();
|
||||
|
||||
if (state == osUnknown) {
|
||||
switch (keyP) {
|
||||
@ -547,6 +567,7 @@ void cSatipPluginSetup::Store(void)
|
||||
{
|
||||
// Store values into setup.conf
|
||||
SetupStore("OperatingMode", operatingModeM);
|
||||
SetupStore("TransportMode", transportModeM);
|
||||
SetupStore("EnableCIExtension", ciExtensionM);
|
||||
SetupStore("EnableEITScan", eitScanM);
|
||||
StoreCicams("CICAM", cicamsM);
|
||||
@ -554,6 +575,7 @@ void cSatipPluginSetup::Store(void)
|
||||
StoreFilters("DisabledFilters", disabledFilterIndexesM);
|
||||
// Update global config
|
||||
SatipConfig.SetOperatingMode(operatingModeM);
|
||||
SatipConfig.SetTransportMode(transportModeM);
|
||||
SatipConfig.SetCIExtension(ciExtensionM);
|
||||
SatipConfig.SetEITScan(eitScanM);
|
||||
for (int i = 0; i < MAX_CICAM_COUNT; ++i)
|
||||
|
2
setup.h
2
setup.h
@ -18,7 +18,9 @@ private:
|
||||
bool detachedModeM;
|
||||
int deviceCountM;
|
||||
int operatingModeM;
|
||||
int transportModeM;
|
||||
const char *operatingModeTextsM[cSatipConfig::eOperatingModeCount];
|
||||
const char *transportModeTextsM[cSatipConfig::eTransportModeCount];
|
||||
int ciExtensionM;
|
||||
int cicamsM[MAX_CICAM_COUNT];
|
||||
const char *cicamTextsM[CA_SYSTEMS_TABLE_SIZE];
|
||||
|
155
socket.c
155
socket.c
@ -21,7 +21,11 @@
|
||||
|
||||
cSatipSocket::cSatipSocket()
|
||||
: socketPortM(0),
|
||||
socketDescM(-1)
|
||||
socketDescM(-1),
|
||||
isMulticastM(false),
|
||||
useSsmM(false),
|
||||
streamAddrM(htonl(INADDR_ANY)),
|
||||
sourceAddrM(htonl(INADDR_ANY))
|
||||
{
|
||||
debug1("%s", __PRETTY_FUNCTION__);
|
||||
memset(&sockAddrM, 0, sizeof(sockAddrM));
|
||||
@ -34,10 +38,17 @@ cSatipSocket::~cSatipSocket()
|
||||
Close();
|
||||
}
|
||||
|
||||
bool cSatipSocket::Open(const int portP)
|
||||
bool cSatipSocket::Open(const int portP, const bool reuseP)
|
||||
{
|
||||
// If socket is there already and it is bound to a different port, it must
|
||||
// be closed first
|
||||
if (portP != socketPortM) {
|
||||
debug1("%s (%d, %d) Socket tear-down", __PRETTY_FUNCTION__, portP, reuseP);
|
||||
Close();
|
||||
}
|
||||
// Bind to the socket if it is not active already
|
||||
if (socketDescM < 0) {
|
||||
int yes;
|
||||
socklen_t len = sizeof(sockAddrM);
|
||||
// Create socket
|
||||
socketDescM = socket(PF_INET, SOCK_DGRAM, 0);
|
||||
@ -46,9 +57,19 @@ bool cSatipSocket::Open(const int portP)
|
||||
ERROR_IF_FUNC(fcntl(socketDescM, F_SETFL, O_NONBLOCK), "fcntl(O_NONBLOCK)",
|
||||
Close(), return false);
|
||||
// Allow multiple sockets to use the same PORT number
|
||||
int yes = 1;
|
||||
yes = reuseP;
|
||||
ERROR_IF_FUNC(setsockopt(socketDescM, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) < 0,
|
||||
"setsockopt(SO_REUSEADDR)", Close(), return false);
|
||||
yes = reuseP;
|
||||
#ifdef SO_REUSEPORT
|
||||
ERROR_IF_FUNC(setsockopt(socketDescM, SOL_SOCKET, SO_REUSEPORT, &yes, sizeof(yes)) < 0 && errno != ENOPROTOOPT,
|
||||
"setsockopt(SO_REUSEPORT)", Close(), return false);
|
||||
#endif
|
||||
#ifndef __FreeBSD__
|
||||
// Allow packet information to be fetched
|
||||
ERROR_IF_FUNC(setsockopt(socketDescM, SOL_IP, IP_PKTINFO, &yes, sizeof(yes)) < 0,
|
||||
"setsockopt(IP_PKTINFO)", Close(), return false);
|
||||
#endif // __FreeBSD__
|
||||
// Bind socket
|
||||
memset(&sockAddrM, 0, sizeof(sockAddrM));
|
||||
sockAddrM.sin_family = AF_INET;
|
||||
@ -57,23 +78,41 @@ bool cSatipSocket::Open(const int portP)
|
||||
ERROR_IF_FUNC(bind(socketDescM, (struct sockaddr *)&sockAddrM, sizeof(sockAddrM)) < 0,
|
||||
"bind()", Close(), return false);
|
||||
// Update socket port
|
||||
ERROR_IF_FUNC(getsockname(socketDescM,(struct sockaddr*)&sockAddrM, &len) < 0,
|
||||
ERROR_IF_FUNC(getsockname(socketDescM, (struct sockaddr*)&sockAddrM, &len) < 0,
|
||||
"getsockname()", Close(), return false);
|
||||
socketPortM = ntohs(sockAddrM.sin_port);
|
||||
isMulticastM = false;
|
||||
}
|
||||
debug1("%s (%d) socketPort=%d", __PRETTY_FUNCTION__, portP, socketPortM);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool cSatipSocket::OpenMulticast(const int portP, const char *streamAddrP, const char *sourceAddrP)
|
||||
{
|
||||
debug1("%s (%d, %s, %s)", __PRETTY_FUNCTION__, portP, streamAddrP, sourceAddrP);
|
||||
if (Open(portP)) {
|
||||
CheckAddress(streamAddrP, &streamAddrM);
|
||||
if (!isempty(sourceAddrP))
|
||||
useSsmM = CheckAddress(sourceAddrP, &sourceAddrM);
|
||||
return Join();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void cSatipSocket::Close(void)
|
||||
{
|
||||
debug1("%s sockerPort=%d", __PRETTY_FUNCTION__, socketPortM);
|
||||
// Check if socket exists
|
||||
if (socketDescM >= 0) {
|
||||
Leave();
|
||||
close(socketDescM);
|
||||
socketDescM = -1;
|
||||
socketPortM = 0;
|
||||
memset(&sockAddrM, 0, sizeof(sockAddrM));
|
||||
streamAddrM = htonl(INADDR_ANY);
|
||||
sourceAddrM = htonl(INADDR_ANY);
|
||||
isMulticastM = false;
|
||||
useSsmM = false;
|
||||
}
|
||||
}
|
||||
|
||||
@ -96,6 +135,96 @@ bool cSatipSocket::Flush(void)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool cSatipSocket::CheckAddress(const char *addrP, in_addr_t *inAddrP)
|
||||
{
|
||||
if (inAddrP) {
|
||||
// First try only the IP address
|
||||
*inAddrP = inet_addr(addrP);
|
||||
if (*inAddrP == htonl(INADDR_NONE)) {
|
||||
debug1("%s (%s, ) Cannot convert to address", __PRETTY_FUNCTION__, addrP);
|
||||
// It may be a host name, get the name
|
||||
struct hostent *host = gethostbyname(addrP);
|
||||
if (!host) {
|
||||
char tmp[64];
|
||||
error("gethostbyname() failed: %s is not valid address: %s", addrP,
|
||||
strerror_r(h_errno, tmp, sizeof(tmp)));
|
||||
return false;
|
||||
}
|
||||
*inAddrP = inet_addr(*host->h_addr_list);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool cSatipSocket::Join(void)
|
||||
{
|
||||
debug1("%s", __PRETTY_FUNCTION__);
|
||||
// Check if socket exists
|
||||
if (socketDescM >= 0 && !isMulticastM) {
|
||||
// Join a new multicast group
|
||||
if (useSsmM) {
|
||||
// Source-specific multicast (SSM) is used
|
||||
struct group_source_req gsr;
|
||||
struct sockaddr_in *grp;
|
||||
struct sockaddr_in *src;
|
||||
gsr.gsr_interface = 0; // if_nametoindex("any") ?
|
||||
grp = (struct sockaddr_in*)&gsr.gsr_group;
|
||||
grp->sin_family = AF_INET;
|
||||
grp->sin_addr.s_addr = streamAddrM;
|
||||
grp->sin_port = 0;
|
||||
src = (struct sockaddr_in*)&gsr.gsr_source;
|
||||
src->sin_family = AF_INET;
|
||||
src->sin_addr.s_addr = sourceAddrM;
|
||||
src->sin_port = 0;
|
||||
ERROR_IF_RET(setsockopt(socketDescM, SOL_IP, MCAST_JOIN_SOURCE_GROUP, &gsr, sizeof(gsr)) < 0, "setsockopt(MCAST_JOIN_SOURCE_GROUP)", return false);
|
||||
}
|
||||
else {
|
||||
struct ip_mreq mreq;
|
||||
mreq.imr_multiaddr.s_addr = streamAddrM;
|
||||
mreq.imr_interface.s_addr = htonl(INADDR_ANY);
|
||||
ERROR_IF_RET(setsockopt(socketDescM, SOL_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0, "setsockopt(IP_ADD_MEMBERSHIP)", return false);
|
||||
}
|
||||
// Update multicasting flag
|
||||
isMulticastM = true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool cSatipSocket::Leave(void)
|
||||
{
|
||||
debug1("%s", __PRETTY_FUNCTION__);
|
||||
// Check if socket exists
|
||||
if (socketDescM >= 0 && isMulticastM) {
|
||||
// Leave the existing multicast group
|
||||
if (useSsmM) {
|
||||
// Source-specific multicast (SSM) is used
|
||||
struct group_source_req gsr;
|
||||
struct sockaddr_in *grp;
|
||||
struct sockaddr_in *src;
|
||||
gsr.gsr_interface = 0; // if_nametoindex("any") ?
|
||||
grp = (struct sockaddr_in*)&gsr.gsr_group;
|
||||
grp->sin_family = AF_INET;
|
||||
grp->sin_addr.s_addr = streamAddrM;
|
||||
grp->sin_port = 0;
|
||||
src = (struct sockaddr_in*)&gsr.gsr_source;
|
||||
src->sin_family = AF_INET;
|
||||
src->sin_addr.s_addr = sourceAddrM;
|
||||
src->sin_port = 0;
|
||||
ERROR_IF_RET(setsockopt(socketDescM, SOL_IP, MCAST_LEAVE_SOURCE_GROUP, &gsr, sizeof(gsr)) < 0, "setsockopt(MCAST_LEAVE_SOURCE_GROUP)", return false);
|
||||
}
|
||||
else {
|
||||
struct ip_mreq mreq;
|
||||
mreq.imr_multiaddr.s_addr = streamAddrM;
|
||||
mreq.imr_interface.s_addr = htonl(INADDR_ANY);
|
||||
ERROR_IF_RET(setsockopt(socketDescM, SOL_IP, IP_DROP_MEMBERSHIP, &mreq, sizeof(mreq)) < 0, "setsockopt(IP_DROP_MEMBERSHIP)", return false);
|
||||
}
|
||||
// Update multicasting flag
|
||||
isMulticastM = false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
int cSatipSocket::Read(unsigned char *bufferAddrP, unsigned int bufferLenP)
|
||||
{
|
||||
debug16("%s (, %d)", __PRETTY_FUNCTION__, bufferLenP);
|
||||
@ -126,8 +255,22 @@ int cSatipSocket::Read(unsigned char *bufferAddrP, unsigned int bufferLenP)
|
||||
|
||||
if (socketDescM && bufferAddrP && (bufferLenP > 0))
|
||||
len = (int)recvmsg(socketDescM, &msgh, MSG_DONTWAIT);
|
||||
if (len > 0)
|
||||
return len;
|
||||
if (len > 0) {
|
||||
#ifndef __FreeBSD__
|
||||
if (isMulticastM) {
|
||||
// Process auxiliary received data and validate source address
|
||||
for (struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msgh); cmsg != NULL; cmsg = CMSG_NXTHDR(&msgh, cmsg)) {
|
||||
if ((cmsg->cmsg_level == SOL_IP) && (cmsg->cmsg_type == IP_PKTINFO)) {
|
||||
struct in_pktinfo *i = (struct in_pktinfo *)CMSG_DATA(cmsg);
|
||||
if ((i->ipi_addr.s_addr == streamAddrM) || (htonl(INADDR_ANY) == streamAddrM))
|
||||
return len;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif // __FreeBSD__
|
||||
return len;
|
||||
}
|
||||
} while (len > 0);
|
||||
ERROR_IF_RET(len < 0 && errno != EAGAIN && errno != EWOULDBLOCK, "recvmsg()", return -1);
|
||||
return 0;
|
||||
|
11
socket.h
11
socket.h
@ -15,14 +15,23 @@ private:
|
||||
int socketPortM;
|
||||
int socketDescM;
|
||||
struct sockaddr_in sockAddrM;
|
||||
bool isMulticastM;
|
||||
bool useSsmM;
|
||||
in_addr_t streamAddrM;
|
||||
in_addr_t sourceAddrM;
|
||||
bool CheckAddress(const char *addrP, in_addr_t *inAddrP);
|
||||
bool Join(void);
|
||||
bool Leave(void);
|
||||
|
||||
public:
|
||||
cSatipSocket();
|
||||
virtual ~cSatipSocket();
|
||||
bool Open(const int portP = 0);
|
||||
bool Open(const int portP = 0, const bool reuseP = false);
|
||||
bool OpenMulticast(const int portP, const char *streamAddrP, const char *sourceAddrP);
|
||||
virtual void Close(void);
|
||||
int Fd(void) { return socketDescM; }
|
||||
int Port(void) { return socketPortM; }
|
||||
bool IsMulticast(void) { return isMulticastM; }
|
||||
bool IsOpen(void) { return (socketDescM >= 0); }
|
||||
bool Flush(void);
|
||||
int Read(unsigned char *bufferAddrP, unsigned int bufferLenP);
|
||||
|
117
tuner.c
117
tuner.c
@ -25,6 +25,8 @@ cSatipTuner::cSatipTuner(cSatipDeviceIf &deviceP, unsigned int packetLenP)
|
||||
rtcpM(*this),
|
||||
streamAddrM(""),
|
||||
streamParamM(""),
|
||||
tnrParamM(""),
|
||||
streamPortM(SATIP_DEFAULT_RTSP_PORT),
|
||||
currentServerM(NULL, deviceP.GetId(), 0),
|
||||
nextServerM(NULL, deviceP.GetId(), 0),
|
||||
mutexM(),
|
||||
@ -50,12 +52,16 @@ cSatipTuner::cSatipTuner(cSatipDeviceIf &deviceP, unsigned int packetLenP)
|
||||
debug1("%s (, %d) [device %d]", __PRETTY_FUNCTION__, packetLenP, deviceIdM);
|
||||
|
||||
// Open sockets
|
||||
int i = 100;
|
||||
int i = SatipConfig.GetPortRangeStart() ? SatipConfig.GetPortRangeStop() - SatipConfig.GetPortRangeStart() - 1 : 100;
|
||||
int port = SatipConfig.GetPortRangeStart();
|
||||
while (i-- > 0) {
|
||||
if (rtpM.Open(0) && rtcpM.Open(rtpM.Port() + 1))
|
||||
// RTP must use an even port number
|
||||
if (rtpM.Open(port) && (rtpM.Port() % 2 == 0) && rtcpM.Open(rtpM.Port() + 1))
|
||||
break;
|
||||
rtpM.Close();
|
||||
rtcpM.Close();
|
||||
if (SatipConfig.GetPortRangeStart())
|
||||
port += 2;
|
||||
}
|
||||
if ((rtpM.Port() <= 0) || (rtcpM.Port() <= 0)) {
|
||||
error("Cannot open required RTP/RTCP ports [device %d]", deviceIdM);
|
||||
@ -205,7 +211,8 @@ bool cSatipTuner::Connect(void)
|
||||
debug1("%s [device %d]", __PRETTY_FUNCTION__, deviceIdM);
|
||||
|
||||
if (!isempty(*streamAddrM)) {
|
||||
cString connectionUri = cString::sprintf("rtsp://%s/", *streamAddrM);
|
||||
cString connectionUri = GetBaseUrl(*streamAddrM, streamPortM);
|
||||
tnrParamM = "";
|
||||
// Just retune
|
||||
if (streamIdM >= 0) {
|
||||
cString uri = cString::sprintf("%sstream=%d?%s", *connectionUri, streamIdM, *streamParamM);
|
||||
@ -217,10 +224,11 @@ bool cSatipTuner::Connect(void)
|
||||
}
|
||||
else if (rtspM.Options(*connectionUri)) {
|
||||
cString uri = cString::sprintf("%s?%s", *connectionUri, *streamParamM);
|
||||
bool useTcp = SatipConfig.IsTransportModeRtpOverTcp() && nextServerM.IsValid() && nextServerM.IsQuirk(cSatipServer::eSatipQuirkRtpOverTcp);
|
||||
// Flush any old content
|
||||
//rtpM.Flush();
|
||||
//rtcpM.Flush();
|
||||
if (rtspM.Setup(*uri, rtpM.Port(), rtcpM.Port())) {
|
||||
if (rtspM.Setup(*uri, rtpM.Port(), rtcpM.Port(), useTcp)) {
|
||||
keepAliveM.Set(timeoutM);
|
||||
if (nextServerM.IsValid()) {
|
||||
currentServerM = nextServerM;
|
||||
@ -244,7 +252,7 @@ bool cSatipTuner::Disconnect(void)
|
||||
debug1("%s [device %d]", __PRETTY_FUNCTION__, deviceIdM);
|
||||
|
||||
if (!isempty(*streamAddrM) && (streamIdM >= 0)) {
|
||||
cString uri = cString::sprintf("rtsp://%s/stream=%d", *streamAddrM, streamIdM);
|
||||
cString uri = cString::sprintf("%sstream=%d", *GetBaseUrl(*streamAddrM, streamPortM), streamIdM);
|
||||
rtspM.Teardown(*uri);
|
||||
// some devices requires a teardown for TCP connection also
|
||||
rtspM.Reset();
|
||||
@ -289,6 +297,11 @@ void cSatipTuner::ProcessVideoData(u_char *bufferP, int lengthP)
|
||||
reConnectM.Set(eConnectTimeoutMs);
|
||||
}
|
||||
|
||||
void cSatipTuner::ProcessRtpData(u_char *bufferP, int lengthP)
|
||||
{
|
||||
rtpM.Process(bufferP, lengthP);
|
||||
}
|
||||
|
||||
void cSatipTuner::ProcessApplicationData(u_char *bufferP, int lengthP)
|
||||
{
|
||||
debug16("%s (%d) [device %d]", __PRETTY_FUNCTION__, lengthP, deviceIdM);
|
||||
@ -342,6 +355,11 @@ void cSatipTuner::ProcessApplicationData(u_char *bufferP, int lengthP)
|
||||
reConnectM.Set(eConnectTimeoutMs);
|
||||
}
|
||||
|
||||
void cSatipTuner::ProcessRtcpData(u_char *bufferP, int lengthP)
|
||||
{
|
||||
rtcpM.Process(bufferP, lengthP);
|
||||
}
|
||||
|
||||
void cSatipTuner::SetStreamId(int streamIdP)
|
||||
{
|
||||
cMutexLock MutexLock(&mutexM);
|
||||
@ -359,6 +377,47 @@ void cSatipTuner::SetSessionTimeout(const char *sessionP, int timeoutP)
|
||||
timeoutM = (timeoutP > eMinKeepAliveIntervalMs) ? timeoutP : eMinKeepAliveIntervalMs;
|
||||
}
|
||||
|
||||
void cSatipTuner::SetupTransport(int rtpPortP, int rtcpPortP, const char *streamAddrP, const char *sourceAddrP)
|
||||
{
|
||||
cMutexLock MutexLock(&mutexM);
|
||||
debug1("%s (%d, %d, %s, %s) [device %d]", __PRETTY_FUNCTION__, rtpPortP, rtcpPortP, streamAddrP, sourceAddrP, deviceIdM);
|
||||
bool multicast = !isempty(streamAddrP);
|
||||
// Adapt RTP to any transport media change
|
||||
if (multicast != rtpM.IsMulticast() || rtpPortP != rtpM.Port()) {
|
||||
cSatipPoller::GetInstance()->Unregister(rtpM);
|
||||
rtpM.Close();
|
||||
if (rtpPortP >= 0) {
|
||||
if (multicast)
|
||||
rtpM.OpenMulticast(rtpPortP, streamAddrP, sourceAddrP);
|
||||
else
|
||||
rtpM.Open(rtpPortP);
|
||||
cSatipPoller::GetInstance()->Register(rtpM);
|
||||
}
|
||||
}
|
||||
// Adapt RTCP to any transport media change
|
||||
if (multicast != rtcpM.IsMulticast() || rtcpPortP != rtcpM.Port()) {
|
||||
cSatipPoller::GetInstance()->Unregister(rtcpM);
|
||||
rtcpM.Close();
|
||||
if (rtcpPortP >= 0) {
|
||||
if (multicast)
|
||||
rtcpM.OpenMulticast(rtpPortP, streamAddrP, sourceAddrP);
|
||||
else
|
||||
rtcpM.Open(rtpPortP);
|
||||
cSatipPoller::GetInstance()->Register(rtcpM);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cString cSatipTuner::GetBaseUrl(const char *addressP, const int portP)
|
||||
{
|
||||
debug16("%s (%s, %d) [device %d]", __PRETTY_FUNCTION__, addressP, portP, deviceIdM);
|
||||
|
||||
if (portP != SATIP_DEFAULT_RTSP_PORT)
|
||||
return cString::sprintf("rtsp://%s:%d/", addressP, portP);
|
||||
|
||||
return cString::sprintf("rtsp://%s/", addressP);
|
||||
}
|
||||
|
||||
int cSatipTuner::GetId(void)
|
||||
{
|
||||
debug16("%s [device %d]", __PRETTY_FUNCTION__, deviceIdM);
|
||||
@ -375,6 +434,10 @@ bool cSatipTuner::SetSource(cSatipServer *serverP, const int transponderP, const
|
||||
// Update stream address and parameter
|
||||
streamAddrM = rtspM.RtspUnescapeString(*nextServerM.GetAddress());
|
||||
streamParamM = rtspM.RtspUnescapeString(parameterP);
|
||||
streamPortM = nextServerM.GetPort();
|
||||
// Modify parameter if required
|
||||
if (nextServerM.IsQuirk(cSatipServer::eSatipQuirkForcePilot) && strstr(parameterP, "msys=dvbs2") && !strstr(parameterP, "plts="))
|
||||
streamParamM = rtspM.RtspUnescapeString(*cString::sprintf("%s&plts=on", parameterP));
|
||||
// Reconnect
|
||||
RequestState(tsSet, smExternal);
|
||||
}
|
||||
@ -413,7 +476,7 @@ bool cSatipTuner::UpdatePids(bool forceP)
|
||||
cMutexLock MutexLock(&mutexM);
|
||||
if (((forceP && pidsM.Size()) || (pidUpdateCacheM.TimedOut() && (addPidsM.Size() || delPidsM.Size()))) &&
|
||||
!isempty(*streamAddrM) && (streamIdM > 0)) {
|
||||
cString uri = cString::sprintf("rtsp://%s/stream=%d", *streamAddrM, streamIdM);
|
||||
cString uri = cString::sprintf("%sstream=%d", *GetBaseUrl(*streamAddrM, streamPortM), streamIdM);
|
||||
bool useci = (SatipConfig.GetCIExtension() && currentServerM.HasCI());
|
||||
bool usedummy = currentServerM.IsQuirk(cSatipServer::eSatipQuirkPlayPids);
|
||||
if (forceP || usedummy) {
|
||||
@ -429,20 +492,30 @@ bool cSatipTuner::UpdatePids(bool forceP)
|
||||
uri = cString::sprintf("%s%sdelpids=%s", *uri, addPidsM.Size() ? "&" : "?", *delPidsM.ListPids());
|
||||
}
|
||||
if (useci) {
|
||||
// CI extension parameters:
|
||||
// - x_pmt : specifies the PMT of the service you want the CI to decode
|
||||
// - x_ci : specfies which CI slot (1..n) to use
|
||||
// value 0 releases the CI slot
|
||||
// CI slot released automatically if the stream is released,
|
||||
// but not when used retuning to another channel
|
||||
int pid = deviceM->GetPmtPid();
|
||||
if ((pid > 0) && (pid != pmtPidM)) {
|
||||
int slot = deviceM->GetCISlot();
|
||||
uri = cString::sprintf("%s&x_pmt=%d", *uri, pid);
|
||||
if (slot > 0)
|
||||
uri = cString::sprintf("%s&x_ci=%d", *uri, slot);
|
||||
if (currentServerM.IsQuirk(cSatipServer::eSatipQuirkCiXpmt)) {
|
||||
// CI extension parameters:
|
||||
// - x_pmt : specifies the PMT of the service you want the CI to decode
|
||||
// - x_ci : specfies which CI slot (1..n) to use
|
||||
// value 0 releases the CI slot
|
||||
// CI slot released automatically if the stream is released,
|
||||
// but not when used retuning to another channel
|
||||
int pid = deviceM->GetPmtPid();
|
||||
if ((pid > 0) && (pid != pmtPidM)) {
|
||||
int slot = deviceM->GetCISlot();
|
||||
uri = cString::sprintf("%s&x_pmt=%d", *uri, pid);
|
||||
if (slot > 0)
|
||||
uri = cString::sprintf("%s&x_ci=%d", *uri, slot);
|
||||
}
|
||||
pmtPidM = pid;
|
||||
}
|
||||
else if (currentServerM.IsQuirk(cSatipServer::eSatipQuirkCiTnr)) {
|
||||
// CI extension parameters:
|
||||
// - tnr : specifies a channel config entry
|
||||
cString param = deviceM->GetTnrParameterString();
|
||||
if (!isempty(*param) && strcmp(*tnrParamM, *param) != 0)
|
||||
uri = cString::sprintf("%s&tnr=%s", *uri, *param);
|
||||
tnrParamM = param;
|
||||
}
|
||||
pmtPidM = pid;
|
||||
}
|
||||
pidUpdateCacheM.Set(ePidUpdateIntervalMs);
|
||||
if (!rtspM.Play(*uri))
|
||||
@ -463,7 +536,7 @@ bool cSatipTuner::KeepAlive(bool forceP)
|
||||
forceP = true;
|
||||
}
|
||||
if (forceP && !isempty(*streamAddrM)) {
|
||||
cString uri = cString::sprintf("rtsp://%s/", *streamAddrM);
|
||||
cString uri = GetBaseUrl(*streamAddrM, streamPortM);
|
||||
if (!rtspM.Options(*uri))
|
||||
return false;
|
||||
}
|
||||
@ -480,7 +553,7 @@ bool cSatipTuner::ReadReceptionStatus(bool forceP)
|
||||
forceP = true;
|
||||
}
|
||||
if (forceP && !isempty(*streamAddrM) && (streamIdM > 0)) {
|
||||
cString uri = cString::sprintf("rtsp://%s/stream=%d", *streamAddrM, streamIdM);
|
||||
cString uri = cString::sprintf("%sstream=%d", *GetBaseUrl(*streamAddrM, streamPortM), streamIdM);
|
||||
if (rtspM.Describe(*uri))
|
||||
return true;
|
||||
}
|
||||
@ -615,5 +688,5 @@ cString cSatipTuner::GetSignalStatus(void)
|
||||
cString cSatipTuner::GetInformation(void)
|
||||
{
|
||||
debug16("%s [device %d]", __PRETTY_FUNCTION__, deviceIdM);
|
||||
return (currentStateM >= tsTuned) ? cString::sprintf("rtsp://%s/?%s [stream=%d]", *streamAddrM, *streamParamM, streamIdM) : "connection failed";
|
||||
return (currentStateM >= tsTuned) ? cString::sprintf("%s?%s (%s) [stream=%d]", *GetBaseUrl(*streamAddrM, streamPortM), *streamParamM, *rtspM.GetActiveMode(), streamIdM) : "connection failed";
|
||||
}
|
||||
|
7
tuner.h
7
tuner.h
@ -69,6 +69,7 @@ public:
|
||||
void Set(cSatipServer *serverP, const int transponderP) { serverM = serverP; transponderM = transponderP; }
|
||||
void Reset(void) { serverM = NULL; transponderM = 0; }
|
||||
cString GetAddress(void) { return serverM ? cSatipDiscover::GetInstance()->GetServerAddress(serverM) : ""; }
|
||||
int GetPort(void) { return serverM ? cSatipDiscover::GetInstance()->GetServerPort(serverM) : SATIP_DEFAULT_RTSP_PORT; }
|
||||
cString GetInfo(void) { return cString::sprintf("server=%s deviceid=%d transponder=%d", serverM ? "assigned" : "null", deviceIdM, transponderM); }
|
||||
};
|
||||
|
||||
@ -98,6 +99,8 @@ private:
|
||||
cSatipRtcp rtcpM;
|
||||
cString streamAddrM;
|
||||
cString streamParamM;
|
||||
cString tnrParamM;
|
||||
int streamPortM;
|
||||
cSatipTunerServer currentServerM;
|
||||
cSatipTunerServer nextServerM;
|
||||
cMutex mutexM;
|
||||
@ -130,6 +133,7 @@ private:
|
||||
bool RequestState(eTunerState stateP, eStateMode modeP);
|
||||
const char *StateModeString(eStateMode modeP);
|
||||
const char *TunerStateString(eTunerState stateP);
|
||||
cString GetBaseUrl(const char *addressP, const int portP);
|
||||
|
||||
protected:
|
||||
virtual void Action(void);
|
||||
@ -153,8 +157,11 @@ public:
|
||||
public:
|
||||
virtual void ProcessVideoData(u_char *bufferP, int lengthP);
|
||||
virtual void ProcessApplicationData(u_char *bufferP, int lengthP);
|
||||
virtual void ProcessRtpData(u_char *bufferP, int lengthP);
|
||||
virtual void ProcessRtcpData(u_char *bufferP, int lengthP);
|
||||
virtual void SetStreamId(int streamIdP);
|
||||
virtual void SetSessionTimeout(const char *sessionP, int timeoutP);
|
||||
virtual void SetupTransport(int rtpPortP, int rtcpPortP, const char *streamAddrP, const char *sourceAddrP);
|
||||
virtual int GetId(void);
|
||||
};
|
||||
|
||||
|
@ -14,8 +14,11 @@ public:
|
||||
virtual ~cSatipTunerIf() {}
|
||||
virtual void ProcessVideoData(u_char *bufferP, int lengthP) = 0;
|
||||
virtual void ProcessApplicationData(u_char *bufferP, int lengthP) = 0;
|
||||
virtual void ProcessRtpData(u_char *bufferP, int lengthP) = 0;
|
||||
virtual void ProcessRtcpData(u_char *bufferP, int lengthP) = 0;
|
||||
virtual void SetStreamId(int streamIdP) = 0;
|
||||
virtual void SetSessionTimeout(const char *sessionP, int timeoutP) = 0;
|
||||
virtual void SetupTransport(int rtpPortP, int rtcpPortP, const char *streamAddrP, const char *sourceAddrP) = 0;
|
||||
virtual int GetId(void) = 0;
|
||||
|
||||
private:
|
||||
|
Loading…
x
Reference in New Issue
Block a user