mirror of
https://github.com/rofafor/vdr-plugin-satip.git
synced 2023-10-10 13:37:42 +02:00
Changed code to utilize a proper XML library, refactored the session code, fxed EIT scan functionality, and updated for vdr-2.1.6.
This commit is contained in:
parent
497b1893db
commit
dfbb3515ef
7
HISTORY
7
HISTORY
@ -12,3 +12,10 @@ VDR Plugin 'satip' Revision History
|
|||||||
- Switched to the standard S/T/C source identifiers.
|
- Switched to the standard S/T/C source identifiers.
|
||||||
- Added a new operation mode setup parameter.
|
- Added a new operation mode setup parameter.
|
||||||
- Added new SVDRP commands.
|
- Added new SVDRP commands.
|
||||||
|
|
||||||
|
2014-03-22: Version 0.1.1
|
||||||
|
|
||||||
|
- Changed code to utilize a proper XML library.
|
||||||
|
- Refactored the session code.
|
||||||
|
- Fixed EIT scan functionality.
|
||||||
|
- Updated for vdr-2.1.6.
|
||||||
|
11
Makefile
11
Makefile
@ -6,6 +6,10 @@
|
|||||||
|
|
||||||
#SATIP_DEBUG = 1
|
#SATIP_DEBUG = 1
|
||||||
|
|
||||||
|
# Use TinyXML instead of PugiXML
|
||||||
|
|
||||||
|
#SATIP_USE_TINYXML = 1
|
||||||
|
|
||||||
# Strip debug symbols? Set eg. to /bin/true if not
|
# Strip debug symbols? Set eg. to /bin/true if not
|
||||||
|
|
||||||
STRIP = strip
|
STRIP = strip
|
||||||
@ -64,6 +68,13 @@ INCLUDES +=
|
|||||||
|
|
||||||
DEFINES += -DPLUGIN_NAME_I18N='"$(PLUGIN)"'
|
DEFINES += -DPLUGIN_NAME_I18N='"$(PLUGIN)"'
|
||||||
|
|
||||||
|
ifdef SATIP_USE_TINYXML
|
||||||
|
DEFINES += -DUSE_TINYXML
|
||||||
|
LIBS += -ltinyxml
|
||||||
|
else
|
||||||
|
LIBS += -lpugixml
|
||||||
|
endif
|
||||||
|
|
||||||
ifdef SATIP_DEBUG
|
ifdef SATIP_DEBUG
|
||||||
DEFINES += -DDEBUG
|
DEFINES += -DDEBUG
|
||||||
endif
|
endif
|
||||||
|
12
README
12
README
@ -17,6 +17,12 @@ Requirements:
|
|||||||
- Libcurl - the multiprotocol file transfer library with RTSP support
|
- Libcurl - the multiprotocol file transfer library with RTSP support
|
||||||
http://curl.haxx.se/libcurl/
|
http://curl.haxx.se/libcurl/
|
||||||
|
|
||||||
|
- PugiXML - Light-weight, simple and fast XML parser for C++
|
||||||
|
http://pugixml.org/
|
||||||
|
or
|
||||||
|
TinyXML - a simple, small, C++ XML parser
|
||||||
|
http://www.grinninglizard.com/tinyxml/
|
||||||
|
|
||||||
- VDR-2.1.4+ for scrambled channels
|
- VDR-2.1.4+ for scrambled channels
|
||||||
|
|
||||||
Description:
|
Description:
|
||||||
@ -92,13 +98,15 @@ Notes:
|
|||||||
result of invalid channel parameters or lack of free SAT>IP tuners.
|
result of invalid channel parameters or lack of free SAT>IP tuners.
|
||||||
|
|
||||||
- SAT>IP specification 1.2 doesn't support DVB-C/DVB-C2 receivers yet,
|
- SAT>IP specification 1.2 doesn't support DVB-C/DVB-C2 receivers yet,
|
||||||
but DVB-C is supported for Digital Devices Octopus Net devices.
|
but DVB-C (KABEL>IP) is supported for Digital Devices Octopus Net
|
||||||
|
devices.
|
||||||
|
|
||||||
- If the plugin doesn't detect your SAT>IP network device, make sure
|
- If the plugin doesn't detect your SAT>IP network device, make sure
|
||||||
your setup doesn't have firewalled the UDP port 1900.
|
your setup doesn't have firewalled the UDP port 1900.
|
||||||
|
|
||||||
- Stream decryption requires a separate CAM plugin that works without
|
- Stream decryption requires a separate CAM plugin that works without
|
||||||
direct access to any DVB card devices.
|
direct access to any DVB card devices. The integrated CAM slot in
|
||||||
|
Octopus Net devices isn't supported.
|
||||||
|
|
||||||
- The 100% compliance against SAT>IP specification 1.2 requires a
|
- The 100% compliance against SAT>IP specification 1.2 requires a
|
||||||
patched VDR providing channel configuration for pilot, T2 system id,
|
patched VDR providing channel configuration for pilot, T2 system id,
|
||||||
|
9
common.h
9
common.h
@ -78,6 +78,15 @@
|
|||||||
} \
|
} \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
#define FREE_POINTER(ptr) \
|
||||||
|
do { \
|
||||||
|
if (ptr) { \
|
||||||
|
typeof(*ptr) *tmp = ptr; \
|
||||||
|
ptr = NULL; \
|
||||||
|
free(tmp); \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof(arr[0]))
|
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof(arr[0]))
|
||||||
|
|
||||||
uint16_t ts_pid(const uint8_t *bufP);
|
uint16_t ts_pid(const uint8_t *bufP);
|
||||||
|
2
device.c
2
device.c
@ -224,7 +224,7 @@ bool cSatipDevice::ProvidesChannel(const cChannel *channelP, int priorityP, bool
|
|||||||
|
|
||||||
bool cSatipDevice::ProvidesEIT(void) const
|
bool cSatipDevice::ProvidesEIT(void) const
|
||||||
{
|
{
|
||||||
return (SatipConfig.GetEITScan() && pTunerM && pTunerM->IsTuned());
|
return (SatipConfig.GetEITScan());
|
||||||
}
|
}
|
||||||
|
|
||||||
int cSatipDevice::NumProvidedSystems(void) const
|
int cSatipDevice::NumProvidedSystems(void) const
|
||||||
|
48
discover.c
48
discover.c
@ -6,7 +6,11 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#ifdef USE_TINYXML
|
||||||
|
#include <tinyxml.h>
|
||||||
|
#else
|
||||||
|
#include <pugixml.hpp>
|
||||||
|
#endif
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "socket.h"
|
#include "socket.h"
|
||||||
@ -43,28 +47,40 @@ void cSatipDiscover::Destroy(void)
|
|||||||
instanceS->Deactivate();
|
instanceS->Deactivate();
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t cSatipDiscover::WriteCallback(void *ptrP, size_t sizeP, size_t nmembP, void *dataP)
|
size_t cSatipDiscover::WriteCallback(char *ptrP, size_t sizeP, size_t nmembP, void *dataP)
|
||||||
{
|
{
|
||||||
cSatipDiscover *obj = reinterpret_cast<cSatipDiscover *>(dataP);
|
cSatipDiscover *obj = reinterpret_cast<cSatipDiscover *>(dataP);
|
||||||
size_t len = sizeP * nmembP;
|
size_t len = sizeP * nmembP;
|
||||||
//debug("cSatipDiscover::%s(%zu)", __FUNCTION__, len);
|
//debug("cSatipDiscover::%s(%zu)", __FUNCTION__, len);
|
||||||
|
|
||||||
char *s, *p = (char *)ptrP;
|
|
||||||
char *r = strtok_r(p, "\r\n", &s);
|
|
||||||
char *desc = NULL, *model = NULL, *addr = NULL;
|
|
||||||
while (r) {
|
|
||||||
//debug("cSatipDiscover::%s(%zu): %s", __FUNCTION__, len, r);
|
|
||||||
r = skipspace(r);
|
|
||||||
// <friendlyName>OctopusNet</friendlyName>
|
|
||||||
if (startswith(r, "<friendlyName"))
|
|
||||||
desc = StripTags(r);
|
|
||||||
// <satip:X_SATIPCAP xmlns:satip="urn:ses-com:satip">DVBT-2</satip:X_SATIPCAP>
|
|
||||||
if (startswith(r, "<satip:X_SATIPCAP"))
|
|
||||||
model = StripTags(r);
|
|
||||||
r = strtok_r(NULL, "\r\n", &s);
|
|
||||||
}
|
|
||||||
if (obj) {
|
if (obj) {
|
||||||
CURLcode res = CURLE_OK;
|
CURLcode res = CURLE_OK;
|
||||||
|
const char *desc = NULL, *model = NULL, *addr = NULL;
|
||||||
|
#ifdef USE_TINYXML
|
||||||
|
TiXmlDocument doc;
|
||||||
|
char *xml = MALLOC(char, len + 1);
|
||||||
|
memcpy(xml, ptrP, len);
|
||||||
|
*(xml + len + 1) = 0;
|
||||||
|
doc.Parse((const char *)xml);
|
||||||
|
TiXmlHandle docHandle(&doc);
|
||||||
|
TiXmlElement *descElement = docHandle.FirstChild("root").FirstChild("device").FirstChild("friendlyName").ToElement();
|
||||||
|
if (descElement)
|
||||||
|
desc = descElement->GetText() ? descElement->GetText() : "MyBrokenHardware";
|
||||||
|
TiXmlElement *modelElement = docHandle.FirstChild("root").FirstChild("device").FirstChild("satip:X_SATIPCAP").ToElement();
|
||||||
|
if (modelElement)
|
||||||
|
model = modelElement->GetText() ? modelElement->GetText() : "DVBS2-1";
|
||||||
|
#else
|
||||||
|
pugi::xml_document doc;
|
||||||
|
pugi::xml_parse_result result = doc.load_buffer(ptrP, len);
|
||||||
|
if (result) {
|
||||||
|
pugi::xml_node descNode = doc.first_element_by_path("root/device/friendlyName");
|
||||||
|
if (descNode)
|
||||||
|
desc = descNode.text().as_string("MyBrokenHardware");
|
||||||
|
pugi::xml_node modelNode = doc.first_element_by_path("root/device/satip:X_SATIPCAP");
|
||||||
|
if (modelNode)
|
||||||
|
model = modelNode.text().as_string("DVBS2-1");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
SATIP_CURL_EASY_GETINFO(obj->handleM, CURLINFO_PRIMARY_IP, &addr);
|
SATIP_CURL_EASY_GETINFO(obj->handleM, CURLINFO_PRIMARY_IP, &addr);
|
||||||
obj->AddServer(addr, desc, model);
|
obj->AddServer(addr, desc, model);
|
||||||
}
|
}
|
||||||
|
@ -28,7 +28,7 @@ private:
|
|||||||
static cSatipDiscover *instanceS;
|
static cSatipDiscover *instanceS;
|
||||||
static const char *bcastAddressS;
|
static const char *bcastAddressS;
|
||||||
static const char *bcastMessageS;
|
static const char *bcastMessageS;
|
||||||
static size_t WriteCallback(void *ptrP, size_t sizeP, size_t nmembP, void *dataP);
|
static size_t WriteCallback(char *ptrP, size_t sizeP, size_t nmembP, void *dataP);
|
||||||
cMutex mutexM;
|
cMutex mutexM;
|
||||||
CURL *handleM;
|
CURL *handleM;
|
||||||
cSatipSocket *socketM;
|
cSatipSocket *socketM;
|
||||||
|
12
param.c
12
param.c
@ -138,9 +138,15 @@ cString GetTransponderUrlParameters(const cChannel *channelP)
|
|||||||
if (channelP) {
|
if (channelP) {
|
||||||
char buffer[255];
|
char buffer[255];
|
||||||
cDvbTransponderParameters dtp(channelP->Parameters());
|
cDvbTransponderParameters dtp(channelP->Parameters());
|
||||||
int Pilot = PILOT_AUTO; // should be added into cDvbTransponderParameters
|
#if defined(APIVERSNUM) && APIVERSNUM < 20106
|
||||||
int T2SystemId = 0; // should be added into cDvbTransponderParameters
|
int Pilot = PILOT_AUTO;
|
||||||
int SisoMiso = 0; // should be added into cDvbTransponderParameters
|
int T2SystemId = 0;
|
||||||
|
int SisoMiso = 0;
|
||||||
|
#else
|
||||||
|
int Pilot = dtp.Pilot();
|
||||||
|
int T2SystemId = dtp.T2SystemId();
|
||||||
|
int SisoMiso = dtp.SisoMiso();
|
||||||
|
#endif
|
||||||
float freq = channelP->Frequency();
|
float freq = channelP->Frequency();
|
||||||
char type = cSource::ToChar(channelP->Source());
|
char type = cSource::ToChar(channelP->Source());
|
||||||
cSource *source = Sources.Get(channelP->Source());
|
cSource *source = Sources.Get(channelP->Source());
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
#
|
#
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: vdr-satip 0.1.0\n"
|
"Project-Id-Version: vdr-satip 0.1.1\n"
|
||||||
"Report-Msgid-Bugs-To: <see README>\n"
|
"Report-Msgid-Bugs-To: <see README>\n"
|
||||||
"POT-Creation-Date: 2014-03-15 03:15+0200\n"
|
"POT-Creation-Date: 2014-03-15 03:15+0200\n"
|
||||||
"PO-Revision-Date: 2014-03-15 03:15+0200\n"
|
"PO-Revision-Date: 2014-03-15 03:15+0200\n"
|
||||||
@ -53,7 +53,7 @@ msgid "Description"
|
|||||||
msgstr "Beschreibung"
|
msgstr "Beschreibung"
|
||||||
|
|
||||||
msgid "Creation date"
|
msgid "Creation date"
|
||||||
msgstr "Erstellungsdatum"
|
msgstr "Zeitpunkt der Erstellung"
|
||||||
|
|
||||||
msgid "SAT>IP Information"
|
msgid "SAT>IP Information"
|
||||||
msgstr "SAT>IP Informationen"
|
msgstr "SAT>IP Informationen"
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
#
|
#
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: vdr-satip 0.1.0\n"
|
"Project-Id-Version: vdr-satip 0.1.1\n"
|
||||||
"Report-Msgid-Bugs-To: <see README>\n"
|
"Report-Msgid-Bugs-To: <see README>\n"
|
||||||
"POT-Creation-Date: 2014-03-15 03:15+0200\n"
|
"POT-Creation-Date: 2014-03-15 03:15+0200\n"
|
||||||
"PO-Revision-Date: 2014-03-15 03:15+0200\n"
|
"PO-Revision-Date: 2014-03-15 03:15+0200\n"
|
||||||
|
4
satip.c
4
satip.c
@ -21,7 +21,7 @@
|
|||||||
#define GITVERSION ""
|
#define GITVERSION ""
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
const char VERSION[] = "0.1.0" GITVERSION;
|
const char VERSION[] = "0.1.1" GITVERSION;
|
||||||
static const char DESCRIPTION[] = trNOOP("SAT>IP Devices");
|
static const char DESCRIPTION[] = trNOOP("SAT>IP Devices");
|
||||||
|
|
||||||
class cPluginSatip : public cPlugin {
|
class cPluginSatip : public cPlugin {
|
||||||
@ -196,7 +196,7 @@ bool cPluginSatip::SetupParse(const char *nameP, const char *valueP)
|
|||||||
// Parse your own setup parameters and store their values.
|
// Parse your own setup parameters and store their values.
|
||||||
if (!strcasecmp(nameP, "OperatingMode"))
|
if (!strcasecmp(nameP, "OperatingMode"))
|
||||||
SatipConfig.SetOperatingMode(atoi(valueP));
|
SatipConfig.SetOperatingMode(atoi(valueP));
|
||||||
if (!strcasecmp(nameP, "EnableEITScan"))
|
else if (!strcasecmp(nameP, "EnableEITScan"))
|
||||||
SatipConfig.SetEITScan(atoi(valueP));
|
SatipConfig.SetEITScan(atoi(valueP));
|
||||||
else if (!strcasecmp(nameP, "DisabledFilters")) {
|
else if (!strcasecmp(nameP, "DisabledFilters")) {
|
||||||
int DisabledFilters[SECTION_FILTER_TABLE_SIZE];
|
int DisabledFilters[SECTION_FILTER_TABLE_SIZE];
|
||||||
|
37
tuner.c
37
tuner.c
@ -26,6 +26,7 @@ cSatipTuner::cSatipTuner(cSatipDeviceIf &deviceP, unsigned int packetLenP)
|
|||||||
headerListM(NULL),
|
headerListM(NULL),
|
||||||
keepAliveM(),
|
keepAliveM(),
|
||||||
pidUpdateCacheM(),
|
pidUpdateCacheM(),
|
||||||
|
sessionM(),
|
||||||
timeoutM(eKeepAliveIntervalMs),
|
timeoutM(eKeepAliveIntervalMs),
|
||||||
openedM(false),
|
openedM(false),
|
||||||
tunedM(false),
|
tunedM(false),
|
||||||
@ -67,28 +68,29 @@ size_t cSatipTuner::HeaderCallback(void *ptrP, size_t sizeP, size_t nmembP, void
|
|||||||
size_t len = sizeP * nmembP;
|
size_t len = sizeP * nmembP;
|
||||||
//debug("cSatipTuner::%s(%zu)", __FUNCTION__, len);
|
//debug("cSatipTuner::%s(%zu)", __FUNCTION__, len);
|
||||||
|
|
||||||
int id = -1, timeout = -1;
|
|
||||||
char *s, *p = (char *)ptrP;
|
char *s, *p = (char *)ptrP;
|
||||||
char *r = strtok_r(p, "\r\n", &s);
|
char *r = strtok_r(p, "\r\n", &s);
|
||||||
|
|
||||||
while (r) {
|
while (obj && r) {
|
||||||
//debug("cSatipTuner::%s(%zu): %s", __FUNCTION__, len, r);
|
//debug("cSatipTuner::%s(%zu): %s", __FUNCTION__, len, r);
|
||||||
r = skipspace(r);
|
r = skipspace(r);
|
||||||
if (strstr(r, "com.ses.streamID")) {
|
if (strstr(r, "com.ses.streamID")) {
|
||||||
if (sscanf(r, "com.ses.streamID:%11d", &id) != 1)
|
int streamid = -1;
|
||||||
id = -1;
|
if (sscanf(r, "com.ses.streamID:%11d", &streamid) == 1)
|
||||||
|
obj->SetStreamId(streamid);
|
||||||
}
|
}
|
||||||
else if (strstr(r, "Session:")) {
|
else if (strstr(r, "Session:")) {
|
||||||
int session = -1;
|
int timeout = -1;
|
||||||
if (sscanf(r, "Session:%11d;timeout=%11d", &session, &timeout) != 2)
|
char *session = NULL;
|
||||||
timeout = -1;
|
if (sscanf(r, "Session:%m[^;];timeout=%11d", &session, &timeout) == 2)
|
||||||
|
obj->SetSessionTimeout(skipspace(session), timeout);
|
||||||
|
else if (sscanf(r, "Session:%m[^;]", &session) == 1)
|
||||||
|
obj->SetSessionTimeout(skipspace(session), -1);
|
||||||
|
FREE_POINTER(session);
|
||||||
}
|
}
|
||||||
r = strtok_r(NULL, "\r\n", &s);
|
r = strtok_r(NULL, "\r\n", &s);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (id >= 0 && obj)
|
|
||||||
obj->SetStreamInfo(id, timeout);
|
|
||||||
|
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -245,7 +247,7 @@ bool cSatipTuner::Connect(void)
|
|||||||
// Start playing
|
// Start playing
|
||||||
uri = cString::sprintf("rtsp://%s/stream=%d", *streamAddrM, streamIdM);
|
uri = cString::sprintf("rtsp://%s/stream=%d", *streamAddrM, streamIdM);
|
||||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_RTSP_STREAM_URI, *uri);
|
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_RTSP_STREAM_URI, *uri);
|
||||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_RTSP_SESSION_ID, NULL);
|
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_RTSP_SESSION_ID, *sessionM);
|
||||||
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_RTSP_REQUEST, (long)CURL_RTSPREQ_PLAY);
|
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_RTSP_REQUEST, (long)CURL_RTSPREQ_PLAY);
|
||||||
SATIP_CURL_EASY_PERFORM(handleM);
|
SATIP_CURL_EASY_PERFORM(handleM);
|
||||||
if (!ValidateLatestResponse())
|
if (!ValidateLatestResponse())
|
||||||
@ -369,11 +371,18 @@ void cSatipTuner::ParseReceptionParameters(const char *paramP)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void cSatipTuner::SetStreamInfo(int idP, int timeoutP)
|
void cSatipTuner::SetStreamId(int streamIdP)
|
||||||
{
|
{
|
||||||
cMutexLock MutexLock(&mutexM);
|
cMutexLock MutexLock(&mutexM);
|
||||||
debug("cSatipTuner::%s(%d, %d)", __FUNCTION__, idP, timeoutP);
|
debug("cSatipTuner::%s(%d)", __FUNCTION__, streamIdP);
|
||||||
streamIdM = idP;
|
streamIdM = streamIdP;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cSatipTuner::SetSessionTimeout(const char *sessionP, int timeoutP)
|
||||||
|
{
|
||||||
|
cMutexLock MutexLock(&mutexM);
|
||||||
|
debug("cSatipTuner::%s(%s, %d)", __FUNCTION__, sessionP, timeoutP);
|
||||||
|
sessionM = sessionP;
|
||||||
timeoutM = timeoutP > 0 ? timeoutP * 1000L : eKeepAliveIntervalMs;
|
timeoutM = timeoutP > 0 ? timeoutP * 1000L : eKeepAliveIntervalMs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
4
tuner.h
4
tuner.h
@ -50,6 +50,7 @@ private:
|
|||||||
cTimeMs keepAliveM;
|
cTimeMs keepAliveM;
|
||||||
cTimeMs signalInfoCacheM;
|
cTimeMs signalInfoCacheM;
|
||||||
cTimeMs pidUpdateCacheM;
|
cTimeMs pidUpdateCacheM;
|
||||||
|
cString sessionM;
|
||||||
int timeoutM;
|
int timeoutM;
|
||||||
bool openedM;
|
bool openedM;
|
||||||
bool tunedM;
|
bool tunedM;
|
||||||
@ -64,7 +65,8 @@ private:
|
|||||||
bool Disconnect(void);
|
bool Disconnect(void);
|
||||||
bool ValidateLatestResponse(void);
|
bool ValidateLatestResponse(void);
|
||||||
void ParseReceptionParameters(const char *paramP);
|
void ParseReceptionParameters(const char *paramP);
|
||||||
void SetStreamInfo(int idP, int timeoutP);
|
void SetStreamId(int streamIdP);
|
||||||
|
void SetSessionTimeout(const char *sessionP, int timeoutP);
|
||||||
bool KeepAlive(void);
|
bool KeepAlive(void);
|
||||||
bool UpdateSignalInfoCache(void);
|
bool UpdateSignalInfoCache(void);
|
||||||
bool UpdatePids(void);
|
bool UpdatePids(void);
|
||||||
|
Loading…
Reference in New Issue
Block a user