mirror of
https://github.com/VDR4Arch/vdr.git
synced 2023-10-10 13:36:52 +02:00
Now handling the channel name, short name and provider separately
This commit is contained in:
parent
5e731865a6
commit
fd9c2d298c
7
HISTORY
7
HISTORY
@ -3096,3 +3096,10 @@ Video Disk Recorder Revision History
|
||||
- Making sure that timers and channels are only saved together, in a consistent
|
||||
manner (thanks to Mirko Dölle for reporting a problem with inconsistent
|
||||
channel and timer lists).
|
||||
- Now handling the channel name, short name and provider separately. cChannel
|
||||
therefore has two new functions, ShortName() and Provider(). ShortName()
|
||||
can be used to display a short version of the name (in case such a version
|
||||
is available). The optional boolean parameter of ShortName() can be set to
|
||||
true to make it return the name, if no short name is available.
|
||||
The sequence of 'name' and 'short name' in the channels.conf file has been
|
||||
swapped (see man vdr(5)).
|
||||
|
67
channels.c
67
channels.c
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: channels.c 1.28 2004/10/22 14:11:07 kls Exp $
|
||||
* $Id: channels.c 1.29 2004/10/31 12:52:50 kls Exp $
|
||||
*/
|
||||
|
||||
#include "channels.h"
|
||||
@ -166,6 +166,9 @@ char *cChannel::buffer = NULL;
|
||||
|
||||
cChannel::cChannel(void)
|
||||
{
|
||||
name = strdup("");
|
||||
shortName = strdup("");
|
||||
provider = strdup("");
|
||||
memset(&__BeginData__, 0, (char *)&__EndData__ - (char *)&__BeginData__);
|
||||
inversion = INVERSION_AUTO;
|
||||
bandwidth = BANDWIDTH_AUTO;
|
||||
@ -182,8 +185,10 @@ cChannel::cChannel(void)
|
||||
|
||||
cChannel::cChannel(const cChannel &Channel)
|
||||
{
|
||||
name = strdup("");
|
||||
shortName = strdup("");
|
||||
provider = strdup("");
|
||||
*this = Channel;
|
||||
*name = 0;
|
||||
vpid = 0;
|
||||
ppid = 0;
|
||||
apids[0] = 0;
|
||||
@ -219,10 +224,16 @@ cChannel::~cChannel()
|
||||
}
|
||||
}
|
||||
}
|
||||
free(name);
|
||||
free(shortName);
|
||||
free(provider);
|
||||
}
|
||||
|
||||
cChannel& cChannel::operator= (const cChannel &Channel)
|
||||
{
|
||||
name = strcpyrealloc(name, Channel.name);
|
||||
shortName = strcpyrealloc(shortName, Channel.shortName);
|
||||
provider = strcpyrealloc(provider, Channel.provider);
|
||||
memcpy(&__BeginData__, &Channel.__BeginData__, (char *)&Channel.__EndData__ - (char *)&Channel.__BeginData__);
|
||||
return *this;
|
||||
}
|
||||
@ -341,15 +352,17 @@ void cChannel::SetId(int Nid, int Tid, int Sid, int Rid)
|
||||
}
|
||||
}
|
||||
|
||||
void cChannel::SetName(const char *Name)
|
||||
void cChannel::SetName(const char *Name, const char *ShortName, const char *Provider)
|
||||
{
|
||||
if (!isempty(Name) && strcmp(name, Name) != 0) {
|
||||
if (Number()) {
|
||||
dsyslog("changing name of channel %d from '%s' to '%s'", Number(), name, Name);
|
||||
dsyslog("changing name of channel %d from '%s,%s;%s' to '%s,%s;%s'", Number(), name, shortName, provider, Name, ShortName, Provider);
|
||||
modification |= CHANNELMOD_NAME;
|
||||
Channels.SetModified();
|
||||
}
|
||||
strn0cpy(name, Name, MaxChannelName);
|
||||
name = strcpyrealloc(name, Name);
|
||||
shortName = strcpyrealloc(shortName, ShortName);
|
||||
provider = strcpyrealloc(provider, Provider);
|
||||
}
|
||||
}
|
||||
|
||||
@ -565,16 +578,21 @@ bool cChannel::StringToParameters(const char *s)
|
||||
|
||||
const char *cChannel::ToText(const cChannel *Channel)
|
||||
{
|
||||
char buf[MaxChannelName * 2];
|
||||
const char *s = Channel->name;
|
||||
if (strchr(s, ':'))
|
||||
s = strreplace(strcpy(buf, s), ':', '|');
|
||||
char FullName[strlen(Channel->name) + 1 + strlen(Channel->shortName) + 1 + strlen(Channel->provider) + 1 + 10]; // +10: paranoia
|
||||
char *q = FullName;
|
||||
q += sprintf(q, "%s", Channel->name);
|
||||
if (!isempty(Channel->shortName))
|
||||
q += sprintf(q, ",%s", Channel->shortName);
|
||||
if (!isempty(Channel->provider))
|
||||
q += sprintf(q, ";%s", Channel->provider);
|
||||
*q = 0;
|
||||
strreplace(FullName, ':', '|');
|
||||
free(buffer);
|
||||
if (Channel->groupSep) {
|
||||
if (Channel->number)
|
||||
asprintf(&buffer, ":@%d %s\n", Channel->number, s);
|
||||
asprintf(&buffer, ":@%d %s\n", Channel->number, FullName);
|
||||
else
|
||||
asprintf(&buffer, ":%s\n", s);
|
||||
asprintf(&buffer, ":%s\n", FullName);
|
||||
}
|
||||
else {
|
||||
char vpidbuf[32];
|
||||
@ -595,7 +613,7 @@ const char *cChannel::ToText(const cChannel *Channel)
|
||||
q = caidbuf;
|
||||
q += IntArrayToString(q, Channel->caids, 16);
|
||||
*q = 0;
|
||||
asprintf(&buffer, "%s:%d:%s:%s:%d:%s:%s:%d:%s:%d:%d:%d:%d\n", s, Channel->frequency, Channel->ParametersToString(), cSource::ToString(Channel->source), Channel->srate, vpidbuf, apidbuf, Channel->tpid, caidbuf, Channel->sid, Channel->nid, Channel->tid, Channel->rid);
|
||||
asprintf(&buffer, "%s:%d:%s:%s:%d:%s:%s:%d:%s:%d:%d:%d:%d\n", FullName, Channel->frequency, Channel->ParametersToString(), cSource::ToString(Channel->source), Channel->srate, vpidbuf, apidbuf, Channel->tpid, caidbuf, Channel->sid, Channel->nid, Channel->tid, Channel->rid);
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
@ -619,7 +637,8 @@ bool cChannel::Parse(const char *s, bool AllowNonUniqueID)
|
||||
s = p;
|
||||
}
|
||||
}
|
||||
strn0cpy(name, skipspace(s), MaxChannelName);
|
||||
name = strcpyrealloc(name, skipspace(s));
|
||||
strreplace(name, '|', ':');
|
||||
}
|
||||
else {
|
||||
groupSep = false;
|
||||
@ -717,7 +736,20 @@ bool cChannel::Parse(const char *s, bool AllowNonUniqueID)
|
||||
caids[NumCaIds] = 0;
|
||||
}
|
||||
}
|
||||
strn0cpy(name, namebuf, MaxChannelName);
|
||||
strreplace(namebuf, '|', ':');
|
||||
|
||||
char *p = strchr(namebuf, ';');
|
||||
if (p) {
|
||||
*p++ = 0;
|
||||
provider = strcpyrealloc(provider, p);
|
||||
}
|
||||
p = strchr(namebuf, ',');
|
||||
if (p) {
|
||||
*p++ = 0;
|
||||
shortName = strcpyrealloc(shortName, p);
|
||||
}
|
||||
name = strcpyrealloc(name, namebuf);
|
||||
|
||||
free(parambuf);
|
||||
free(sourcebuf);
|
||||
free(vpidbuf);
|
||||
@ -736,7 +768,6 @@ bool cChannel::Parse(const char *s, bool AllowNonUniqueID)
|
||||
else
|
||||
return false;
|
||||
}
|
||||
strreplace(name, '|', ':');
|
||||
return ok;
|
||||
}
|
||||
|
||||
@ -878,13 +909,13 @@ int cChannels::Modified(void)
|
||||
return Result;
|
||||
}
|
||||
|
||||
cChannel *cChannels::NewChannel(const cChannel *Transponder, const char *Name, int Nid, int Tid, int Sid, int Rid)
|
||||
cChannel *cChannels::NewChannel(const cChannel *Transponder, const char *Name, const char *ShortName, const char *Provider, int Nid, int Tid, int Sid, int Rid)
|
||||
{
|
||||
if (Transponder) {
|
||||
dsyslog("creating new channel '%s' on %s transponder %d with id %d-%d-%d-%d", Name, cSource::ToString(Transponder->Source()), Transponder->Transponder(), Nid, Tid, Sid, Rid);
|
||||
dsyslog("creating new channel '%s,%s;%s' on %s transponder %d with id %d-%d-%d-%d", Name, ShortName, Provider, cSource::ToString(Transponder->Source()), Transponder->Transponder(), Nid, Tid, Sid, Rid);
|
||||
cChannel *NewChannel = new cChannel(*Transponder);
|
||||
NewChannel->SetId(Nid, Tid, Sid, Rid);
|
||||
NewChannel->SetName(Name);
|
||||
NewChannel->SetName(Name, ShortName, Provider);
|
||||
Add(NewChannel);
|
||||
ReNumber();
|
||||
return NewChannel;
|
||||
|
13
channels.h
13
channels.h
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: channels.h 1.20 2004/10/22 14:09:47 kls Exp $
|
||||
* $Id: channels.h 1.21 2004/10/31 12:41:38 kls Exp $
|
||||
*/
|
||||
|
||||
#ifndef __CHANNELS_H
|
||||
@ -89,9 +89,10 @@ class cChannel : public cListObject {
|
||||
private:
|
||||
static char *buffer;
|
||||
static const char *ToText(const cChannel *Channel);
|
||||
enum { MaxChannelName = 64 }; // 63 chars + terminating 0!
|
||||
char *name;
|
||||
char *shortName;
|
||||
char *provider;
|
||||
int __BeginData__;
|
||||
char name[MaxChannelName];
|
||||
int frequency; // MHz
|
||||
int source;
|
||||
int srate;
|
||||
@ -133,6 +134,8 @@ public:
|
||||
bool Parse(const char *s, bool AllowNonUniqueID = false);
|
||||
bool Save(FILE *f);
|
||||
const char *Name(void) const { return name; }
|
||||
const char *ShortName(bool OrName = false) const { return (OrName && isempty(shortName)) ? name : shortName; }
|
||||
const char *Provider(void) const { return provider; }
|
||||
int Frequency(void) const { return frequency; } ///< Returns the actual frequency, as given in 'channels.conf'
|
||||
int Transponder(void) const; ///< Returns the transponder frequency in MHz, plus the polarization in case of sat
|
||||
static int Transponder(int Frequency, char Polarization); ///< builds the transponder from the given Frequency and Polarization
|
||||
@ -171,7 +174,7 @@ public:
|
||||
bool SetCableTransponderData(int Source, int Frequency, int Modulation, int Srate, int CoderateH);
|
||||
bool SetTerrTransponderData(int Source, int Frequency, int Bandwidth, int Modulation, int Hierarchy, int CodeRateH, int CodeRateL, int Guard, int Transmission);
|
||||
void SetId(int Nid, int Tid, int Sid, int Rid = 0);
|
||||
void SetName(const char *Name);
|
||||
void SetName(const char *Name, const char *ShortName, const char *Provider);
|
||||
void SetPids(int Vpid, int Ppid, int *Apids, char ALangs[][4], int *Dpids, char DLangs[][4], int Tpid);
|
||||
void SetCaIds(const int *CaIds); // list must be zero-terminated
|
||||
void SetCaDescriptors(int Level);
|
||||
@ -205,7 +208,7 @@ public:
|
||||
///< Returns 0 if no channels have been modified, 1 if an automatic
|
||||
///< modification has been made, and 2 if the user has made a modification.
|
||||
///< Calling this function resets the 'modified' flag to 0.
|
||||
cChannel *NewChannel(const cChannel *Transponder, const char *Name, int Nid, int Tid, int Sid, int Rid = 0);
|
||||
cChannel *NewChannel(const cChannel *Transponder, const char *Name, const char *ShortName, const char *Provider, int Nid, int Tid, int Sid, int Rid = 0);
|
||||
};
|
||||
|
||||
extern cChannels Channels;
|
||||
|
6
eit.c
6
eit.c
@ -8,7 +8,7 @@
|
||||
* Robert Schneider <Robert.Schneider@web.de> and Rolf Hakenes <hakenes@hippomi.de>.
|
||||
* Adapted to 'libsi' for VDR 1.3.0 by Marcel Wiesweg <marcel.wiesweg@gmx.de>.
|
||||
*
|
||||
* $Id: eit.c 1.98 2004/10/24 14:56:39 kls Exp $
|
||||
* $Id: eit.c 1.99 2004/10/31 12:41:04 kls Exp $
|
||||
*/
|
||||
|
||||
#include "eit.h"
|
||||
@ -168,10 +168,10 @@ cEIT::cEIT(cSchedules *Schedules, int Source, u_char Tid, const u_char *Data)
|
||||
//fprintf(stderr, "Linkage %s %4d %4d %5d %5d %5d %5d %02X '%s'\n", hit ? "*" : "", channel->Number(), link ? link->Number() : -1, SiEitEvent.getEventId(), ld->getOriginalNetworkId(), ld->getTransportStreamId(), ld->getServiceId(), ld->getLinkageType(), linkName);//XXX
|
||||
if (link) {
|
||||
if (Setup.UpdateChannels >= 1)
|
||||
link->SetName(linkName);
|
||||
link->SetName(linkName, "", "");
|
||||
}
|
||||
else if (Setup.UpdateChannels >= 3) {
|
||||
link = Channels.NewChannel(channel, linkName, ld->getOriginalNetworkId(), ld->getTransportStreamId(), ld->getServiceId());
|
||||
link = Channels.NewChannel(channel, linkName, "", "", ld->getOriginalNetworkId(), ld->getTransportStreamId(), ld->getServiceId());
|
||||
//XXX patFilter->Trigger();
|
||||
}
|
||||
if (link) {
|
||||
|
11
menu.c
11
menu.c
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: menu.c 1.316 2004/10/31 10:09:16 kls Exp $
|
||||
* $Id: menu.c 1.317 2004/10/31 12:53:00 kls Exp $
|
||||
*/
|
||||
|
||||
#include "menu.h"
|
||||
@ -223,6 +223,7 @@ class cMenuEditChannel : public cOsdMenu {
|
||||
private:
|
||||
cChannel *channel;
|
||||
cChannel data;
|
||||
char name[256];
|
||||
void Setup(void);
|
||||
public:
|
||||
cMenuEditChannel(cChannel *Channel, bool New = false);
|
||||
@ -254,7 +255,8 @@ void cMenuEditChannel::Setup(void)
|
||||
Clear();
|
||||
|
||||
// Parameters for all types of sources:
|
||||
Add(new cMenuEditStrItem( tr("Name"), data.name, sizeof(data.name), tr(FileNameChars)));
|
||||
strn0cpy(name, data.name, sizeof(name));
|
||||
Add(new cMenuEditStrItem( tr("Name"), name, sizeof(name), tr(FileNameChars)));
|
||||
Add(new cMenuEditSrcItem( tr("Source"), &data.source));
|
||||
Add(new cMenuEditIntItem( tr("Frequency"), &data.frequency));
|
||||
Add(new cMenuEditIntItem( tr("Vpid"), &data.vpid, 0, 0x1FFF));
|
||||
@ -295,6 +297,7 @@ eOSState cMenuEditChannel::ProcessKey(eKeys Key)
|
||||
if (state == osUnknown) {
|
||||
if (Key == kOk) {
|
||||
if (Channels.HasUniqueChannelID(&data, channel)) {
|
||||
data.name = strcpyrealloc(data.name, name);
|
||||
if (channel) {
|
||||
*channel = data;
|
||||
isyslog("edited channel %d %s", channel->Number(), data.ToText());
|
||||
@ -629,7 +632,7 @@ eOSState cMenuEditTimer::ProcessKey(eKeys Key)
|
||||
break;
|
||||
}
|
||||
if (!*data.file)
|
||||
strcpy(data.file, data.Channel()->Name());
|
||||
strcpy(data.file, data.Channel()->ShortName(true));
|
||||
if (timer) {
|
||||
if (memcmp(timer, &data, sizeof(data)) != 0) {
|
||||
*timer = data;
|
||||
@ -918,7 +921,7 @@ cMenuWhatsOnItem::cMenuWhatsOnItem(const cEvent *Event, cChannel *Channel)
|
||||
char t = Timers.GetMatch(Event, &TimerMatch) ? (TimerMatch == tmFull) ? 'T' : 't' : ' ';
|
||||
char v = event->Vps() && (event->Vps() - event->StartTime()) ? 'V' : ' ';
|
||||
char r = event->IsRunning() ? '*' : ' ';
|
||||
asprintf(&buffer, "%d\t%.*s\t%s\t%c%c%c\t%s", channel->Number(), 6, channel->Name(), event->GetTimeString(), t, v, r, event->Title());
|
||||
asprintf(&buffer, "%d\t%.*s\t%s\t%c%c%c\t%s", channel->Number(), 6, channel->ShortName(true), event->GetTimeString(), t, v, r, event->Title());
|
||||
SetText(buffer, false);
|
||||
}
|
||||
|
||||
|
26
sdt.c
26
sdt.c
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: sdt.c 1.12 2004/10/16 10:02:23 kls Exp $
|
||||
* $Id: sdt.c 1.13 2004/10/31 12:10:20 kls Exp $
|
||||
*/
|
||||
|
||||
#include "sdt.h"
|
||||
@ -58,28 +58,16 @@ void cSdtFilter::Process(u_short Pid, u_char Tid, const u_char *Data, int Length
|
||||
{
|
||||
char NameBuf[1024];
|
||||
char ShortNameBuf[1024];
|
||||
char ProviderNameBuf[1024];
|
||||
sd->serviceName.getText(NameBuf, ShortNameBuf, sizeof(NameBuf), sizeof(ShortNameBuf));
|
||||
char *pn = compactspace(NameBuf);
|
||||
char *ps = compactspace(ShortNameBuf);
|
||||
if (*NameBuf && *ShortNameBuf && strcmp(NameBuf, ShortNameBuf) != 0) {
|
||||
ps = ShortNameBuf + strlen(ShortNameBuf);
|
||||
*ps++ = ',';
|
||||
strcpy(ps, NameBuf);
|
||||
pn = ShortNameBuf;
|
||||
}
|
||||
if (*pn) {
|
||||
char ProviderNameBuf[1024];
|
||||
sd->providerName.getText(ProviderNameBuf, sizeof(ProviderNameBuf));
|
||||
if (*ProviderNameBuf) {
|
||||
char *p = pn + strlen(pn);
|
||||
*p++ = ';';
|
||||
strcpy(p, ProviderNameBuf);
|
||||
}
|
||||
}
|
||||
sd->providerName.getText(ProviderNameBuf, sizeof(ProviderNameBuf));
|
||||
char *pp = compactspace(ProviderNameBuf);
|
||||
if (channel) {
|
||||
channel->SetId(sdt.getOriginalNetworkId(), sdt.getTransportStreamId(), SiSdtService.getServiceId());
|
||||
if (Setup.UpdateChannels >= 1)
|
||||
channel->SetName(pn);
|
||||
channel->SetName(pn, ps, pp);
|
||||
// Using SiSdtService.getFreeCaMode() is no good, because some
|
||||
// tv stations set this flag even for non-encrypted channels :-(
|
||||
// The special value 0xFFFF was supposed to mean "unknown encryption"
|
||||
@ -87,7 +75,7 @@ void cSdtFilter::Process(u_short Pid, u_char Tid, const u_char *Data, int Length
|
||||
// channel->SetCa(SiSdtService.getFreeCaMode() ? 0xFFFF : 0);
|
||||
}
|
||||
else if (*pn && Setup.UpdateChannels >= 3) {
|
||||
channel = Channels.NewChannel(Channel(), pn, sdt.getOriginalNetworkId(), sdt.getTransportStreamId(), SiSdtService.getServiceId());
|
||||
channel = Channels.NewChannel(Channel(), pn, ps, pp, sdt.getOriginalNetworkId(), sdt.getTransportStreamId(), SiSdtService.getServiceId());
|
||||
patFilter->Trigger();
|
||||
}
|
||||
}
|
||||
@ -112,7 +100,7 @@ void cSdtFilter::Process(u_short Pid, u_char Tid, const u_char *Data, int Length
|
||||
for (SI::Loop::Iterator it; nrd->serviceLoop.getNext(Service, it); ) {
|
||||
cChannel *link = Channels.GetByChannelID(tChannelID(Source(), Service.getOriginalNetworkId(), Service.getTransportStream(), Service.getServiceId()));
|
||||
if (!link && Setup.UpdateChannels >= 3) {
|
||||
link = Channels.NewChannel(Channel(), "NVOD", Service.getOriginalNetworkId(), Service.getTransportStream(), Service.getServiceId());
|
||||
link = Channels.NewChannel(Channel(), "NVOD", "", "", Service.getOriginalNetworkId(), Service.getTransportStream(), Service.getServiceId());
|
||||
patFilter->Trigger();
|
||||
}
|
||||
if (link) {
|
||||
|
14
vdr.5
14
vdr.5
@ -2,15 +2,15 @@
|
||||
.\" ** The above line should force tbl to be a preprocessor **
|
||||
.\" Man page for vdr file formats
|
||||
.\"
|
||||
.\" Copyright (C) 2003 Klaus Schmidinger
|
||||
.\" Copyright (C) 2004 Klaus Schmidinger
|
||||
.\"
|
||||
.\" You may distribute under the terms of the GNU General Public
|
||||
.\" License as specified in the file COPYING that comes with the
|
||||
.\" vdr distribution.
|
||||
.\"
|
||||
.\" $Id: vdr.5 1.28 2004/07/18 11:06:54 kls Exp $
|
||||
.\" $Id: vdr.5 1.29 2004/10/31 12:13:43 kls Exp $
|
||||
.\"
|
||||
.TH vdr 5 "1 Jun 2003" "1.2.0" "Video Disk Recorder Files"
|
||||
.TH vdr 5 "31 Oct 2004" "1.3.15" "Video Disk Recorder Files"
|
||||
.SH NAME
|
||||
vdr file formats - the Video Disk Recorder Files
|
||||
.SH DESCRIPTION
|
||||
@ -45,7 +45,7 @@ Such a delimiter will not appear in the Channels menu.
|
||||
A \fBchannel definition\fR is a line with channel data, where the fields
|
||||
are separated by ':' characters. Example:
|
||||
|
||||
\fBRTL,RTL Television:12188:h:S19.2E:27500:163:104:105:0:12003:1:1089:0\fR
|
||||
\fBRTL Television,RTL:12188:h:S19.2E:27500:163:104:105:0:12003:1:1089:0\fR
|
||||
|
||||
The line number of a channel definition (not counting group separators,
|
||||
and based on a possible previous '@...' parameter)
|
||||
@ -60,15 +60,15 @@ it has to be replaced by '|').
|
||||
Some tv stations provide a way of deriving a "short name" from the
|
||||
channel name, which can be used in situations where there is not
|
||||
much space for displaying a long name. If a short name is available
|
||||
for this channel, it preceeds the full name and is delimited by a comma,
|
||||
for this channel, it follows the full name and is delimited by a comma,
|
||||
as in
|
||||
|
||||
\fBRTL,RTL Television:...\fR
|
||||
\fBRTL Television,RTL:...\fR
|
||||
|
||||
If present, the name of the service provider or "bouquet" is appended
|
||||
to the channel name, separated by a semicolon, as in
|
||||
|
||||
\fBRTL,RTL Television;RTL World:...\fR
|
||||
\fBRTL Television,RTL;RTL World:...\fR
|
||||
.TP
|
||||
.B Frequency
|
||||
The transponder frequency (as an integer). For DVB-S this value is in MHz. For DVB-C
|
||||
|
Loading…
Reference in New Issue
Block a user