mirror of
https://projects.vdr-developer.org/git/vdr-plugin-streamdev.git
synced 2023-10-10 19:16:51 +02:00
- cleaned up common.h / common.c
- dropped cStreamdevMenuSetupPage
This commit is contained in:
parent
6fb88f8d99
commit
1cf41fb16f
2
HISTORY
2
HISTORY
@ -1,6 +1,8 @@
|
||||
VDR Plugin 'streamdev' Revision History
|
||||
---------------------------------------
|
||||
|
||||
- cleaned up common.h / common.c
|
||||
- dropped cStreamdevMenuSetupPage
|
||||
- report charset in HTTP replies (suggested by Rolf Ahrenberg)
|
||||
- use SO_KEEPALIVE option on all sockets do detect dead sockets (thanks to
|
||||
owagner)
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* $Id: setup.c,v 1.8 2009/02/03 10:26:21 schmirl Exp $
|
||||
* $Id: setup.c,v 1.9 2009/09/18 10:43:26 schmirl Exp $
|
||||
*/
|
||||
|
||||
#include <vdr/menuitems.h>
|
||||
@ -41,14 +41,14 @@ bool cStreamdevClientSetup::SetupParse(const char *Name, const char *Value) {
|
||||
cStreamdevClientMenuSetupPage::cStreamdevClientMenuSetupPage(void) {
|
||||
m_NewSetup = StreamdevClientSetup;
|
||||
|
||||
AddBoolEdit (tr("Hide Mainmenu Entry"),m_NewSetup.HideMenuEntry);
|
||||
AddBoolEdit (tr("Start Client"), m_NewSetup.StartClient);
|
||||
AddIpEdit (tr("Remote IP"), m_NewSetup.RemoteIp);
|
||||
AddShortEdit(tr("Remote Port"), m_NewSetup.RemotePort);
|
||||
AddBoolEdit (tr("Filter Streaming"), m_NewSetup.StreamFilters);
|
||||
AddBoolEdit (tr("Synchronize EPG"), m_NewSetup.SyncEPG);
|
||||
AddRangeEdit (tr("Minimum Priority"), m_NewSetup.MinPriority, -1, MAXPRIORITY);
|
||||
AddRangeEdit (tr("Maximum Priority"), m_NewSetup.MaxPriority, -1, MAXPRIORITY);
|
||||
Add(new cMenuEditBoolItem(tr("Hide Mainmenu Entry"), &m_NewSetup.HideMenuEntry));
|
||||
Add(new cMenuEditBoolItem(tr("Start Client"), &m_NewSetup.StartClient));
|
||||
Add(new cMenuEditIpItem (tr("Remote IP"), m_NewSetup.RemoteIp));
|
||||
Add(new cMenuEditIntItem (tr("Remote Port"), &m_NewSetup.RemotePort, 0, 65535));
|
||||
Add(new cMenuEditBoolItem(tr("Filter Streaming"), &m_NewSetup.StreamFilters));
|
||||
Add(new cMenuEditBoolItem(tr("Synchronize EPG"), &m_NewSetup.SyncEPG));
|
||||
Add(new cMenuEditIntItem (tr("Minimum Priority"), &m_NewSetup.MinPriority, -1, MAXPRIORITY));
|
||||
Add(new cMenuEditIntItem (tr("Maximum Priority"), &m_NewSetup.MaxPriority, -1, MAXPRIORITY));
|
||||
SetCurrent(Get(0));
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* $Id: setup.h,v 1.5 2009/01/29 07:48:59 schmirl Exp $
|
||||
* $Id: setup.h,v 1.6 2009/09/18 10:43:26 schmirl Exp $
|
||||
*/
|
||||
|
||||
#ifndef VDR_STREAMDEV_SETUPCLIENT_H
|
||||
@ -24,7 +24,7 @@ struct cStreamdevClientSetup {
|
||||
|
||||
extern cStreamdevClientSetup StreamdevClientSetup;
|
||||
|
||||
class cStreamdevClientMenuSetupPage: public cStreamdevMenuSetupPage {
|
||||
class cStreamdevClientMenuSetupPage: public cMenuSetupPage {
|
||||
private:
|
||||
cStreamdevClientSetup m_NewSetup;
|
||||
|
||||
|
137
common.c
137
common.c
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* $Id: common.c,v 1.10 2009/06/19 06:32:38 schmirl Exp $
|
||||
* $Id: common.c,v 1.11 2009/09/18 10:41:41 schmirl Exp $
|
||||
*/
|
||||
|
||||
#include <vdr/channels.h>
|
||||
@ -12,140 +12,7 @@ using namespace std;
|
||||
|
||||
const char *VERSION = "0.5.0-pre";
|
||||
|
||||
const char *StreamTypes[st_Count] = {
|
||||
"TS",
|
||||
"PES",
|
||||
"PS",
|
||||
"ES",
|
||||
"Extern",
|
||||
"", // used internally only
|
||||
};
|
||||
|
||||
const char *SuspendModes[sm_Count] = {
|
||||
trNOOP("Offer suspend mode"),
|
||||
trNOOP("Always suspended"),
|
||||
trNOOP("Never suspended")
|
||||
};
|
||||
|
||||
const char IpCharacters[] = "0123456789.";
|
||||
|
||||
char *GetNextLine(char *String, uint Length, uint &Offset) {
|
||||
char *last, *first;
|
||||
|
||||
first = String + Offset;
|
||||
for (last = first; last < String + Length; ++last) {
|
||||
if (*last == '\012') {
|
||||
if (*(last - 1) == '\015')
|
||||
*(last - 1) = '\0';
|
||||
|
||||
*last++ = '\0';
|
||||
Dprintf("IN: |%s|\n", first);
|
||||
Offset = last - String;
|
||||
return first;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const cChannel *ChannelFromString(const char *String, int *Apid) {
|
||||
const cChannel *channel = NULL;
|
||||
char *string = strdup(String);
|
||||
char *ptr, *end;
|
||||
int apididx = 0;
|
||||
|
||||
if ((ptr = strrchr(string, '+')) != NULL) {
|
||||
*(ptr++) = '\0';
|
||||
apididx = strtoul(ptr, &end, 10);
|
||||
Dprintf("found apididx: %d\n", apididx);
|
||||
}
|
||||
|
||||
if (isnumber(string)) {
|
||||
int temp = strtol(String, NULL, 10);
|
||||
if (temp >= 1 && temp <= Channels.MaxNumber())
|
||||
channel = Channels.GetByNumber(temp);
|
||||
} else {
|
||||
channel = Channels.GetByChannelID(tChannelID::FromString(string));
|
||||
|
||||
if (channel == NULL) {
|
||||
int i = 1;
|
||||
while ((channel = Channels.GetByNumber(i, 1)) != NULL) {
|
||||
if (String == channel->Name())
|
||||
break;
|
||||
|
||||
i = channel->Number() + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (channel != NULL && apididx > 0) {
|
||||
int apid = 0, index = 1;
|
||||
|
||||
for (int i = 0; channel->Apid(i) != 0; ++i, ++index) {
|
||||
if (index == apididx) {
|
||||
apid = channel->Apid(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (apid == 0) {
|
||||
for (int i = 0; channel->Dpid(i) != 0; ++i, ++index) {
|
||||
if (index == apididx) {
|
||||
apid = channel->Dpid(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (Apid != NULL)
|
||||
*Apid = apid;
|
||||
}
|
||||
|
||||
free(string);
|
||||
return channel;
|
||||
}
|
||||
|
||||
void cStreamdevMenuSetupPage::AddCategory(const char *Title) {
|
||||
char *buffer = NULL;
|
||||
|
||||
asprintf(&buffer, "--- %s -------------------------------------------------"
|
||||
"---------------", Title );
|
||||
|
||||
cOsdItem *item = new cOsdItem(buffer);
|
||||
free(buffer);
|
||||
item->SetSelectable(false);
|
||||
Add(item);
|
||||
}
|
||||
|
||||
void cStreamdevMenuSetupPage::AddBoolEdit(const char *Title, int &Value) {
|
||||
Add(new cMenuEditBoolItem(Title, &Value));
|
||||
}
|
||||
|
||||
void cStreamdevMenuSetupPage::AddIpEdit(const char *Title, char *Value) {
|
||||
Add(new cMenuEditIpItem(Title, Value));
|
||||
}
|
||||
|
||||
void cStreamdevMenuSetupPage::AddShortEdit(const char *Title, int &Value) {
|
||||
AddRangeEdit(Title, Value, 0, 65535);
|
||||
}
|
||||
|
||||
void cStreamdevMenuSetupPage::AddRangeEdit(const char *Title, int &Value,
|
||||
int Min, int Max) {
|
||||
Add(new cMenuEditIntItem(Title, &Value, Min, Max));
|
||||
}
|
||||
|
||||
void cStreamdevMenuSetupPage::AddSuspEdit(const char *Title, int &Value) {
|
||||
static const char *SuspendModesTR[sm_Count] = { NULL };
|
||||
|
||||
if (SuspendModesTR[0] == NULL) {
|
||||
for (int i = 0; i < sm_Count; ++i)
|
||||
SuspendModesTR[i] = tr(SuspendModes[i]);
|
||||
}
|
||||
|
||||
Add(new cMenuEditStraItem(Title, &Value, sm_Count, SuspendModesTR));
|
||||
}
|
||||
void cStreamdevMenuSetupPage::AddTypeEdit(const char *Title, int &Value) {
|
||||
Add(new cMenuEditStraItem(Title, &Value, st_CountSetup, StreamTypes));
|
||||
}
|
||||
const char cMenuEditIpItem::IpCharacters[] = "0123456789.";
|
||||
|
||||
cMenuEditIpItem::cMenuEditIpItem(const char *Name, char *Value):
|
||||
cMenuEditItem(Name) {
|
||||
|
44
common.h
44
common.h
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* $Id: common.h,v 1.14 2009/07/01 10:46:16 schmirl Exp $
|
||||
* $Id: common.h,v 1.15 2009/09/18 10:41:41 schmirl Exp $
|
||||
*/
|
||||
|
||||
#ifndef VDR_STREAMDEV_COMMON_H
|
||||
@ -23,32 +23,15 @@
|
||||
# define Dprintf(x...)
|
||||
#endif
|
||||
|
||||
# define TRANSPONDER(c1, c2) (c1->Transponder() == c2->Transponder())
|
||||
#define TRANSPONDER(c1, c2) (c1->Transponder() == c2->Transponder())
|
||||
|
||||
# define MAXPARSEBUFFER KILOBYTE(16)
|
||||
#define MAXPARSEBUFFER KILOBYTE(16)
|
||||
|
||||
/* Check if a channel is a radio station. */
|
||||
#define ISRADIO(x) ((x)->Vpid()==0||(x)->Vpid()==1||(x)->Vpid()==0x1fff)
|
||||
|
||||
class cChannel;
|
||||
|
||||
char *GetNextLine(char *String, uint Length, uint &Offset);
|
||||
|
||||
const cChannel *ChannelFromString(const char *String, int *Apid = NULL);
|
||||
|
||||
/* Disable logging if BUFCOUNT buffer overflows occur within BUFOVERTIME
|
||||
milliseconds. Enable logging again if there is no error within BUFOVERTIME
|
||||
milliseconds. */
|
||||
#define BUFOVERTIME 5000
|
||||
#define BUFOVERCOUNT 100
|
||||
|
||||
#define POLLFAIL esyslog("Streamdev: Polling failed: %s", strerror(errno))
|
||||
#define WRITEFAIL esyslog("Streamdev: Writing failed: %s", strerror(errno))
|
||||
#define READFAIL esyslog("Streamdev: Reading failed: %s", strerror(errno))
|
||||
#define CHECKPOLL(x) if ((x)<0){POLLFAIL; return false;}
|
||||
#define CHECKWRITE(x) if ((x)<0) { WRITEFAIL; return false; }
|
||||
#define CHECKREAD(x) if ((x)<0) { READFAIL; return false; }
|
||||
|
||||
enum eStreamType {
|
||||
stTS,
|
||||
stPES,
|
||||
@ -56,9 +39,7 @@ enum eStreamType {
|
||||
stES,
|
||||
stExtern,
|
||||
stTSPIDS,
|
||||
|
||||
#define st_CountSetup (stExtern+1)
|
||||
#define st_Count (stTSPIDS+1)
|
||||
st_Count
|
||||
};
|
||||
|
||||
enum eSuspendMode {
|
||||
@ -77,25 +58,10 @@ enum eSocketId {
|
||||
};
|
||||
|
||||
extern const char *VERSION;
|
||||
extern const char *StreamTypes[st_Count];
|
||||
extern const char *SuspendModes[sm_Count];
|
||||
extern const char IpCharacters[];
|
||||
|
||||
class cStreamdevMenuSetupPage: public cMenuSetupPage {
|
||||
protected:
|
||||
void AddCategory(const char *Title);
|
||||
virtual void Store(void) = 0;
|
||||
|
||||
void AddBoolEdit(const char *Title, int &Value);
|
||||
void AddIpEdit(const char *Title, char *Value);
|
||||
void AddShortEdit(const char *Title, int &Value);
|
||||
void AddRangeEdit(const char *Title, int &Value, int Min, int Max);
|
||||
void AddSuspEdit(const char *Title, int &Value);
|
||||
void AddTypeEdit(const char *Title, int &Value);
|
||||
};
|
||||
|
||||
class cMenuEditIpItem: public cMenuEditItem {
|
||||
private:
|
||||
static const char IpCharacters[];
|
||||
char *value;
|
||||
int curNum;
|
||||
int pos;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* $Id: connection.c,v 1.12 2009/02/13 10:39:22 schmirl Exp $
|
||||
* $Id: connection.c,v 1.13 2009/09/18 10:43:26 schmirl Exp $
|
||||
*/
|
||||
|
||||
#include "server/connection.h"
|
||||
@ -27,6 +27,63 @@ cServerConnection::~cServerConnection()
|
||||
{
|
||||
}
|
||||
|
||||
const cChannel* cServerConnection::ChannelFromString(const char *String, int *Apid) {
|
||||
const cChannel *channel = NULL;
|
||||
char *string = strdup(String);
|
||||
char *ptr, *end;
|
||||
int apididx = 0;
|
||||
|
||||
if ((ptr = strrchr(string, '+')) != NULL) {
|
||||
*(ptr++) = '\0';
|
||||
apididx = strtoul(ptr, &end, 10);
|
||||
Dprintf("found apididx: %d\n", apididx);
|
||||
}
|
||||
|
||||
if (isnumber(string)) {
|
||||
int temp = strtol(String, NULL, 10);
|
||||
if (temp >= 1 && temp <= Channels.MaxNumber())
|
||||
channel = Channels.GetByNumber(temp);
|
||||
} else {
|
||||
channel = Channels.GetByChannelID(tChannelID::FromString(string));
|
||||
|
||||
if (channel == NULL) {
|
||||
int i = 1;
|
||||
while ((channel = Channels.GetByNumber(i, 1)) != NULL) {
|
||||
if (String == channel->Name())
|
||||
break;
|
||||
|
||||
i = channel->Number() + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (channel != NULL && apididx > 0) {
|
||||
int apid = 0, index = 1;
|
||||
|
||||
for (int i = 0; channel->Apid(i) != 0; ++i, ++index) {
|
||||
if (index == apididx) {
|
||||
apid = channel->Apid(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (apid == 0) {
|
||||
for (int i = 0; channel->Dpid(i) != 0; ++i, ++index) {
|
||||
if (index == apididx) {
|
||||
apid = channel->Dpid(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (Apid != NULL)
|
||||
*Apid = apid;
|
||||
}
|
||||
|
||||
free(string);
|
||||
return channel;
|
||||
}
|
||||
|
||||
bool cServerConnection::Read(void)
|
||||
{
|
||||
int b;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* $Id: connection.h,v 1.7 2009/02/13 10:39:22 schmirl Exp $
|
||||
* $Id: connection.h,v 1.8 2009/09/18 10:43:26 schmirl Exp $
|
||||
*/
|
||||
|
||||
#ifndef VDR_STREAMDEV_SERVER_CONNECTION_H
|
||||
@ -41,6 +41,8 @@ protected:
|
||||
virtual bool Respond(const char *Message, bool Last = true, ...);
|
||||
//__attribute__ ((format (printf, 2, 4)));
|
||||
|
||||
static const cChannel *ChannelFromString(const char *String, int *Apid = NULL);
|
||||
|
||||
public:
|
||||
/* If you derive, specify a short string such as HTTP for Protocol, which
|
||||
will be displayed in error messages */
|
||||
|
@ -495,8 +495,9 @@ bool cStreamdevLiveStreamer::SetChannel(const cChannel *Channel, eStreamType Str
|
||||
case stTSPIDS:
|
||||
Dprintf("pid streaming mode\n");
|
||||
return true;
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
int cStreamdevLiveStreamer::Put(const uchar *Data, int Count)
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* $Id: setup.c,v 1.6 2009/02/13 10:39:22 schmirl Exp $
|
||||
* $Id: setup.c,v 1.7 2009/09/18 10:43:26 schmirl Exp $
|
||||
*/
|
||||
|
||||
#include <vdr/menuitems.h>
|
||||
@ -45,35 +45,66 @@ bool cStreamdevServerSetup::SetupParse(const char *Name, const char *Value) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const char* cStreamdevServerMenuSetupPage::StreamTypes[st_Count - 1] = {
|
||||
"TS",
|
||||
"PES",
|
||||
"PS",
|
||||
"ES",
|
||||
"Extern"
|
||||
};
|
||||
|
||||
const char* cStreamdevServerMenuSetupPage::SuspendModes[sm_Count] = {
|
||||
"Offer suspend mode",
|
||||
"Always suspended",
|
||||
"Never suspended"
|
||||
};
|
||||
|
||||
cStreamdevServerMenuSetupPage::cStreamdevServerMenuSetupPage(void) {
|
||||
m_NewSetup = StreamdevServerSetup;
|
||||
|
||||
static const char* modes[sm_Count];
|
||||
for (int i = 0; i < sm_Count; i++)
|
||||
modes[i] = tr(SuspendModes[i]);
|
||||
|
||||
AddCategory (tr("Common Settings"));
|
||||
AddRangeEdit(tr("Maximum Number of Clients"), m_NewSetup.MaxClients, 0, 100);
|
||||
AddSuspEdit (tr("Suspend behaviour"), m_NewSetup.SuspendMode);
|
||||
AddBoolEdit (tr("Client may suspend"), m_NewSetup.AllowSuspend);
|
||||
Add(new cMenuEditIntItem (tr("Maximum Number of Clients"), &m_NewSetup.MaxClients, 0, 100));
|
||||
|
||||
Add(new cMenuEditStraItem(tr("Suspend behaviour"), &m_NewSetup.SuspendMode, sm_Count, modes));
|
||||
Add(new cMenuEditBoolItem(tr("Client may suspend"), &m_NewSetup.AllowSuspend));
|
||||
|
||||
AddCategory (tr("VDR-to-VDR Server"));
|
||||
AddBoolEdit (tr("Start VDR-to-VDR Server"), m_NewSetup.StartVTPServer);
|
||||
AddShortEdit(tr("VDR-to-VDR Server Port"), m_NewSetup.VTPServerPort);
|
||||
AddIpEdit (tr("Bind to IP"), m_NewSetup.VTPBindIP);
|
||||
Add(new cMenuEditBoolItem(tr("Start VDR-to-VDR Server"), &m_NewSetup.StartVTPServer));
|
||||
Add(new cMenuEditIntItem (tr("VDR-to-VDR Server Port"), &m_NewSetup.VTPServerPort, 0, 65535));
|
||||
Add(new cMenuEditIpItem (tr("Bind to IP"), m_NewSetup.VTPBindIP));
|
||||
|
||||
AddCategory (tr("HTTP Server"));
|
||||
AddBoolEdit (tr("Start HTTP Server"), m_NewSetup.StartHTTPServer);
|
||||
AddShortEdit(tr("HTTP Server Port"), m_NewSetup.HTTPServerPort);
|
||||
AddTypeEdit (tr("HTTP Streamtype"), m_NewSetup.HTTPStreamType);
|
||||
AddIpEdit (tr("Bind to IP"), m_NewSetup.HTTPBindIP);
|
||||
Add(new cMenuEditBoolItem(tr("Start HTTP Server"), &m_NewSetup.StartHTTPServer));
|
||||
Add(new cMenuEditIntItem (tr("HTTP Server Port"), &m_NewSetup.HTTPServerPort, 0, 65535));
|
||||
Add(new cMenuEditStraItem(tr("HTTP Streamtype"), &m_NewSetup.HTTPStreamType, st_Count - 1, StreamTypes));
|
||||
Add(new cMenuEditIpItem (tr("Bind to IP"), m_NewSetup.HTTPBindIP));
|
||||
AddCategory (tr("Multicast Streaming Server"));
|
||||
AddBoolEdit (tr("Start IGMP Server"), m_NewSetup.StartIGMPServer);
|
||||
AddShortEdit(tr("Multicast Client Port"), m_NewSetup.IGMPClientPort);
|
||||
AddTypeEdit (tr("Multicast Streamtype"), m_NewSetup.IGMPStreamType);
|
||||
AddIpEdit (tr("Bind to IP"), m_NewSetup.IGMPBindIP);
|
||||
Add(new cMenuEditBoolItem(tr("Start IGMP Server"), &m_NewSetup.StartIGMPServer));
|
||||
Add(new cMenuEditIntItem (tr("Multicast Client Port"), &m_NewSetup.IGMPClientPort, 0, 65535));
|
||||
Add(new cMenuEditStraItem(tr("Multicast Streamtype"), &m_NewSetup.IGMPStreamType, st_Count - 1, StreamTypes));
|
||||
Add(new cMenuEditIpItem (tr("Bind to IP"), m_NewSetup.IGMPBindIP));
|
||||
SetCurrent(Get(1));
|
||||
}
|
||||
|
||||
cStreamdevServerMenuSetupPage::~cStreamdevServerMenuSetupPage() {
|
||||
}
|
||||
|
||||
void cStreamdevServerMenuSetupPage::AddCategory(const char *Title) {
|
||||
char *buffer = NULL;
|
||||
|
||||
asprintf(&buffer, "--- %s -------------------------------------------------"
|
||||
"---------------", Title );
|
||||
|
||||
cOsdItem *item = new cOsdItem(buffer);
|
||||
free(buffer);
|
||||
item->SetSelectable(false);
|
||||
Add(item);
|
||||
}
|
||||
|
||||
void cStreamdevServerMenuSetupPage::Store(void) {
|
||||
bool restart = false;
|
||||
if (m_NewSetup.StartVTPServer != StreamdevServerSetup.StartVTPServer
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* $Id: setup.h,v 1.2 2009/02/13 10:39:22 schmirl Exp $
|
||||
* $Id: setup.h,v 1.3 2009/09/18 10:43:26 schmirl Exp $
|
||||
*/
|
||||
|
||||
#ifndef VDR_STREAMDEV_SETUPSERVER_H
|
||||
@ -30,10 +30,13 @@ struct cStreamdevServerSetup {
|
||||
|
||||
extern cStreamdevServerSetup StreamdevServerSetup;
|
||||
|
||||
class cStreamdevServerMenuSetupPage: public cStreamdevMenuSetupPage {
|
||||
class cStreamdevServerMenuSetupPage: public cMenuSetupPage {
|
||||
private:
|
||||
static const char* StreamTypes[];
|
||||
static const char* SuspendModes[];
|
||||
cStreamdevServerSetup m_NewSetup;
|
||||
|
||||
void AddCategory(const char *Title);
|
||||
protected:
|
||||
virtual void Store(void);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user