28 char *sourcebuf = NULL;
33 int fields = sscanf(s,
"%m[^-]-%d-%d-%d-%d", &sourcebuf, &nid, &tid, &sid, &rid);
34 if (fields == 4 || fields == 5) {
62 shortName = strdup(
"");
63 provider = strdup(
"");
64 portalName = strdup(
"");
65 memset(&__BeginData__, 0, (
char *)&__EndData__ - (
char *)&__BeginData__);
91 if (Channel->linkChannels) {
92 for (
cLinkChannel *lc = Channel->linkChannels->First(); lc; lc = Channel->linkChannels->
Next(lc)) {
93 if (lc->Channel() ==
this) {
94 Channel->linkChannels->Del(lc);
98 if (Channel->linkChannels->Count() == 0) {
99 delete Channel->linkChannels;
100 Channel->linkChannels = NULL;
118 shortNameSource = NULL;
135 if (OrName &&
isempty(shortName))
140 return shortNameSource;
148 switch (toupper(Polarization)) {
149 case 'H': Frequency += 100000;
break;
150 case 'V': Frequency += 200000;
break;
151 case 'L': Frequency += 300000;
break;
152 case 'R': Frequency += 400000;
break;
153 default:
esyslog(
"ERROR: invalid value for Polarization '%c'", Polarization);
164 const char *p = strpbrk(parameters,
"HVLRhvlr");
174 if (Timer->Channel() ==
this)
182 int Result = modification & Mask;
192 srate = Channel->
srate;
199 if (strchr(Parameters,
':')) {
200 esyslog(
"ERROR: parameter string '%s' contains ':'", Parameters);
206 if (abs(frequency - Frequency) <= 1)
207 Frequency = frequency;
212 if (abs(srate - Srate) <= 1)
215 if (
source != Source || frequency != Frequency || srate != Srate || strcmp(parameters, Parameters)) {
216 cString OldTransponderData = TransponderDataToString();
218 frequency = Frequency;
220 parameters = Parameters;
223 shortNameSource = NULL;
224 if (Number() && !Quiet) {
225 dsyslog(
"changing transponder data of channel %d (%s) from %s to %s", Number(), name, *OldTransponderData, *TransponderDataToString());
235 if (
nid != Nid ||
tid != Tid ||
sid != Sid ||
rid != Rid) {
237 dsyslog(
"changing id of channel %d (%s) from %d-%d-%d-%d to %d-%d-%d-%d", Number(), name,
nid,
tid,
sid,
rid, Nid, Tid, Sid, Rid);
256 dsyslog(
"changing lcn of channel %d (%s) from %d to %d\n", Number(), name, lcn, Lcn);
264 bool nn = strcmp(name, Name) != 0;
265 bool ns = strcmp(shortName, ShortName) != 0;
266 bool np = strcmp(provider, Provider) != 0;
267 if (nn || ns || np) {
269 dsyslog(
"changing name of channel %d from '%s,%s;%s' to '%s,%s;%s'", Number(), name, shortName, provider, Name, ShortName, Provider);
279 shortNameSource = NULL;
289 if (!
isempty(PortalName) && strcmp(portalName, PortalName) != 0) {
291 dsyslog(
"changing portal name of channel %d (%s) from '%s' to '%s'", Number(), name, portalName, PortalName);
305 for (
int i = 0; a[i] || b[i]; i++) {
306 if (!a[i] || !b[i]) {
310 if (na && nb && strcmp(na[i], nb[i]) != 0)
322 while (a[i] || i == 0) {
323 q += sprintf(q, Base == 16 ?
"%s%X" :
"%s%d", i ?
"," :
"", a[i]);
324 const char *Delim =
"=";
327 q += sprintf(q,
"%s%s", Delim, n[i]);
331 q += sprintf(q,
"%s@%d", Delim, t[i]);
341 void cChannel::SetPids(
int Vpid,
int Ppid,
int Vtype,
int *Apids,
int *Atypes,
char ALangs[][
MAXLANGCODE2],
int *Dpids,
int *Dtypes,
char DLangs[][MAXLANGCODE2],
int *Spids,
char SLangs[][MAXLANGCODE2],
int Tpid)
344 if (vpid != Vpid || ppid != Ppid || vtype != Vtype)
348 int m =
IntArraysDiffer(apids, Apids, alangs, ALangs) |
IntArraysDiffer(atypes, Atypes) |
IntArraysDiffer(dpids, Dpids, dlangs, DLangs) |
IntArraysDiffer(dtypes, Dtypes) |
IntArraysDiffer(spids, Spids, slangs, SLangs);
354 const int BufferSize = (
MAXAPIDS +
MAXDPIDS) * (5 + 1 + MAXLANGCODE2 + 5) + 10;
355 char OldApidsBuf[BufferSize];
356 char NewApidsBuf[BufferSize];
357 char *q = OldApidsBuf;
372 char OldSpidsBuf[SBufferSize];
373 char NewSpidsBuf[SBufferSize];
381 dsyslog(
"changing pids of channel %d (%s) from %d+%d=%d:%s:%s:%d to %d+%d=%d:%s:%s:%d", Number(), name, vpid, ppid, vtype, OldApidsBuf, OldSpidsBuf, tpid, Vpid, Ppid, Vtype, NewApidsBuf, NewSpidsBuf, Tpid);
385 for (
int i = 0; i <
MAXAPIDS; i++) {
387 atypes[i] = Atypes[i];
388 strn0cpy(alangs[i], ALangs[i], MAXLANGCODE2);
391 for (
int i = 0; i <
MAXDPIDS; i++) {
393 dtypes[i] = Dtypes[i];
394 strn0cpy(dlangs[i], DLangs[i], MAXLANGCODE2);
397 for (
int i = 0; i <
MAXSPIDS; i++) {
399 strn0cpy(slangs[i], SLangs[i], MAXLANGCODE2);
411 if (SubtitlingTypes) {
413 subtitlingTypes[i] = SubtitlingTypes[i];
415 if (CompositionPageIds) {
417 compositionPageIds[i] = CompositionPageIds[i];
419 if (AncillaryPageIds) {
421 ancillaryPageIds[i] = AncillaryPageIds[i];
428 if (totalTtxtSubtitlePages != (fixedTtxtSubtitlePages + numberOfPages))
430 totalTtxtSubtitlePages = fixedTtxtSubtitlePages;
431 for (
int i = 0; (i < numberOfPages) && (totalTtxtSubtitlePages <
MAXTXTPAGES); i++) {
432 if (teletextSubtitlePages[totalTtxtSubtitlePages].ttxtMagazine != pages[i].ttxtMagazine ||
433 teletextSubtitlePages[totalTtxtSubtitlePages].ttxtPage != pages[i].ttxtPage ||
434 teletextSubtitlePages[totalTtxtSubtitlePages].ttxtType != pages[i].ttxtType ||
435 strcmp(teletextSubtitlePages[totalTtxtSubtitlePages].ttxtLanguage, pages[i].ttxtLanguage)) {
437 teletextSubtitlePages[totalTtxtSubtitlePages] = pages[i];
439 totalTtxtSubtitlePages++;
455 char OldCaIdsBuf[
MAXCAIDS * 5 + 10];
456 char NewCaIdsBuf[
MAXCAIDS * 5 + 10];
460 dsyslog(
"changing caids of channel %d (%s) from %s to %s", Number(), name, OldCaIdsBuf, NewCaIdsBuf);
461 for (
int i = 0; i <=
MAXCAIDS; i++) {
476 if (Number() && Level > 1)
477 dsyslog(
"changing ca descriptors of channel %d (%s)", Number(), name);
483 if (!linkChannels && !LinkChannels)
485 if (linkChannels && LinkChannels) {
493 lca = linkChannels->
Next(lca);
494 lcb = LinkChannels->
Next(lcb);
501 char buffer[((linkChannels ? linkChannels->Count() : 0) + (LinkChannels ? LinkChannels->
Count() : 0)) * 6 + 256];
503 q += sprintf(q,
"linking channel %d (%s) from", Number(), name);
505 for (
cLinkChannel *lc = linkChannels->First(); lc; lc = linkChannels->
Next(lc)) {
506 lc->Channel()->SetRefChannel(NULL);
507 q += sprintf(q,
" %d", lc->Channel()->Number());
512 q += sprintf(q,
" none");
513 q += sprintf(q,
" to");
514 linkChannels = LinkChannels;
516 for (
cLinkChannel *lc = linkChannels->First(); lc; lc = linkChannels->
Next(lc)) {
517 lc->Channel()->SetRefChannel(
this);
518 q += sprintf(q,
" %d", lc->Channel()->Number());
523 q += sprintf(q,
" none");
530 refChannel = RefChannel;
542 char FullName[strlen(Channel->
name) + 1 + strlen(Channel->
shortName) + 1 + strlen(Channel->
provider) + 1 + 10];
544 q += sprintf(q,
"%s", Channel->
name);
547 q += sprintf(q,
",%s", Channel->
shortName);
548 else if (strchr(Channel->
name,
','))
549 q += sprintf(q,
",");
551 q += sprintf(q,
";%s", Channel->
provider);
565 q += snprintf(q,
sizeof(vpidbuf),
"%d", Channel->
vpid);
567 q += snprintf(q,
sizeof(vpidbuf) - (q - vpidbuf),
"+%d", Channel->
ppid);
569 q += snprintf(q,
sizeof(vpidbuf) - (q - vpidbuf),
"=%d", Channel->
vtype);
572 char apidbuf[ABufferSize];
575 if (Channel->
dpids[0]) {
581 char tpidbuf[TBufferSize];
583 q += snprintf(q,
sizeof(tpidbuf),
"%d", Channel->
tpid);
591 if (Channel->
spids[0]) {
599 buffer =
cString::sprintf(
"%s:%d:%s:%s:%d:%s:%s:%s:%s:%d:%d:%d:%d\n", FullName, Channel->
frequency, *Channel->
parameters, *
cSource::ToString(Channel->
source), Channel->
srate, vpidbuf, apidbuf, tpidbuf, caidbuf, Channel->
sid, Channel->
nid, Channel->
tid, Channel->
rid);
614 if (*++s ==
'@' && *++s) {
617 int n = strtol(s, &p, 10);
618 if (!errno && p != s && n > 0) {
628 char *namebuf = NULL;
629 char *sourcebuf = NULL;
630 char *parambuf = NULL;
631 char *vpidbuf = NULL;
632 char *apidbuf = NULL;
633 char *tpidbuf = NULL;
634 char *caidbuf = NULL;
635 int fields = sscanf(s,
"%m[^:]:%d :%m[^:]:%m[^:] :%d :%m[^:]:%m[^:]:%m[^:]:%m[^:]:%d :%d :%d :%d ", &namebuf, &frequency, ¶mbuf, &sourcebuf, &srate, &vpidbuf, &apidbuf, &tpidbuf, &caidbuf, &
sid, &
nid, &
tid, &
rid);
642 if (sscanf(tpidbuf,
"%d", &tpid) != 1)
656 if (parambuf && sourcebuf && vpidbuf && apidbuf) {
657 parameters = parambuf;
661 if ((p = strchr(vpidbuf,
'=')) != NULL) {
663 if (sscanf(p,
"%d", &vtype) != 1)
666 if ((p = strchr(vpidbuf,
'+')) != NULL) {
668 if (sscanf(p,
"%d", &ppid) != 1)
671 if (sscanf(vpidbuf,
"%d", &vpid) != 1)
678 char *dpidbuf = strchr(apidbuf,
';');
685 while ((q = strtok_r(p,
",", &strtok_next)) != NULL) {
687 atypes[NumApids] = 4;
688 char *l = strchr(q,
'=');
691 char *t = strchr(l,
'@');
694 atypes[NumApids] = strtol(t, NULL, 10);
699 *alangs[NumApids] = 0;
700 if ((apids[NumApids] = strtol(q, NULL, 10)) != 0)
704 esyslog(
"ERROR: too many APIDs!");
708 atypes[NumApids] = 0;
714 while ((q = strtok_r(p,
",", &strtok_next)) != NULL) {
717 char *l = strchr(q,
'=');
720 char *t = strchr(l,
'@');
723 dtypes[NumDpids] = strtol(t, NULL, 10);
728 *dlangs[NumDpids] = 0;
729 if ((dpids[NumDpids] = strtol(q, NULL, 10)) != 0)
733 esyslog(
"ERROR: too many DPIDs!");
737 dtypes[NumDpids] = 0;
740 if ((p = strchr(tpidbuf,
';')) != NULL) {
744 while ((q = strtok_r(p,
",", &strtok_next)) != NULL) {
746 char *l = strchr(q,
'=');
752 *slangs[NumSpids] = 0;
753 spids[NumSpids++] = strtol(q, NULL, 10);
756 esyslog(
"ERROR: too many SPIDs!");
761 fixedTtxtSubtitlePages = 0;
762 if ((p = strchr(tpidbuf,
'+')) != NULL) {
766 while ((q = strtok_r(p,
",", &strtok_next)) != NULL) {
769 char *l = strchr(q,
'=');
772 if (sscanf(q,
"%d", &page) == 1) {
776 fixedTtxtSubtitlePages++;
779 esyslog(
"ERROR: invalid Teletext page!");
782 esyslog(
"ERROR: too many Teletext pages!");
785 totalTtxtSubtitlePages = fixedTtxtSubtitlePages;
787 if (sscanf(tpidbuf,
"%d", &tpid) != 1)
794 while ((q = strtok_r(p,
",", &strtok_next)) != NULL) {
796 caids[NumCaIds++] = strtol(q, NULL, 16) & 0xFFFF;
801 esyslog(
"ERROR: too many CA ids!");
809 char *p = strchr(namebuf,
';');
814 p = strrchr(namebuf,
',');
829 shortNameSource = NULL;
830 if (!GetChannelID().
Valid()) {
831 esyslog(
"ERROR: channel data results in invalid ID!");
843 return fprintf(f,
"%s", *ToText()) > 0;
858 return memcmp(&channelID, &cs->
channelID,
sizeof(channelID));
869 maxChannelNameLength = 0;
870 maxShortChannelNameLength = 0;
877 for (
cChannel *channel = First(); channel; channel = Next(channel)) {
878 if (!channel->GroupSep())
881 ChannelSorter.
Sort();
896 DeleteDuplicateChannels();
905 channelsHashSid.Add(Channel, Channel->
Sid());
910 channelsHashSid.Del(Channel, Channel->
Sid());
916 while (channel && !(channel->
GroupSep() && *channel->
Name()))
917 channel = Get(++Idx);
918 return channel ? Idx : -1;
924 while (channel && !(channel->
GroupSep() && *channel->
Name()))
925 channel = Get(--Idx);
926 return channel ? Idx : -1;
932 while (channel && channel->
GroupSep())
933 channel = Get(++Idx);
934 return channel ? Idx : -1;
940 while (channel && channel->
GroupSep())
941 channel = Get(--Idx);
942 return channel ? Idx : -1;
947 channelsHashSid.Clear();
953 for (
cChannel *channel = First(); channel; channel = Next(channel)) {
954 if (!channel->GroupSep()) {
956 HashChannel(channel);
960 for (
int i = 0; i < FoundLcn.
Size(); ++i) {
961 if (FoundLcn[i] == Number) {
969 if (Number > maxNumber)
971 channel->SetNumber(Number);
974 maxNumber = Overflow;
975 channel->SetNumber(Overflow++);
981 for (
cChannel *channel = First(); channel; channel = Next(channel)) {
982 if (channel->GroupSep()) {
983 if (channel->Number() > Number)
984 Number = channel->Number();
987 HashChannel(channel);
989 channel->SetNumber(Number++);
998 for (
cChannel *channel = First(); channel; channel = Next(channel)) {
999 if (!channel->GroupSep()) {
1000 if (channel->Number() == Number)
1002 else if (SkipGap && channel->Number() > Number)
1003 return SkipGap > 0 ? channel : previous;
1025 int sid = ChannelID.
Sid();
1033 if (TryWithoutRid) {
1041 if (TryWithoutPolarization) {
1055 int nid = ChannelID.
Nid();
1056 int tid = ChannelID.
Tid();
1057 for (
cChannel *channel = First(); channel; channel = Next(channel)) {
1058 if (channel->Tid() == tid && channel->Nid() == nid && channel->Source() ==
source)
1067 for (
cChannel *channel = First(); channel; channel = Next(channel)) {
1068 if (!channel->GroupSep() && channel != OldChannel && channel->
GetChannelID() == NewChannelID)
1076 cChannel *channel = GetByNumber(Number);
1082 if (!maxChannelNameLength) {
1083 for (
cChannel *channel = First(); channel; channel = Next(channel)) {
1084 if (!channel->GroupSep())
1085 maxChannelNameLength =
max(
Utf8StrLen(channel->Name()), maxChannelNameLength);
1088 return maxChannelNameLength;
1093 if (!maxShortChannelNameLength) {
1094 for (
cChannel *channel = First(); channel; channel = Next(channel)) {
1095 if (!channel->GroupSep())
1096 maxShortChannelNameLength =
max(
Utf8StrLen(channel->ShortName(
true)), maxShortChannelNameLength);
1099 return maxShortChannelNameLength;
1105 maxChannelNameLength = maxShortChannelNameLength = 0;
1110 int Result = modified;
1118 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);
1121 NewChannel->SetId(Nid, Tid, Sid, Rid);
1122 NewChannel->SetName(Name, ShortName, Provider);
1123 NewChannel->SetSeen();
1131 #define CHANNELMARKOBSOLETE "OBSOLETE" 1132 #define CHANNELTIMEOBSOLETE 3600 // seconds to wait before declaring a channel obsolete (in case it has actually been seen before) 1136 for (
cChannel *channel = First(); channel; channel = Next(channel)) {
1137 if (time(NULL) - channel->Seen() >
CHANNELTIMEOBSOLETE && channel->Source() == Source && channel->Nid() == Nid && channel->Tid() == Tid && channel->Rid() == 0) {
1152 snprintf(buffer,
sizeof(buffer),
"%s", Channel->
Name());
1154 snprintf(buffer,
sizeof(buffer),
"%d%s %s", Channel->
Number(), Number ?
"-" :
"", Channel->
Name());
1157 snprintf(buffer,
sizeof(buffer),
"%d-", Number);
1159 snprintf(buffer,
sizeof(buffer),
"%s",
tr(
"*** Invalid Channel ***"));
static cString ToString(int Code)
void SetId(int Nid, int Tid, int Sid, int Rid=0)
int Modified(void)
Returns 0 if no channels have been modified, 1 if an automatic modification has been made...
#define CHANNELTIMEOBSOLETE
static char ToChar(int Code)
static tChannelID FromString(const char *s)
int GetPrevGroup(int Idx)
int MaxShortChannelNameLength(void)
void CopyTransponderData(const cChannel *Channel)
void Add(cListObject *Object, cListObject *After=NULL)
static cString ToText(const cChannel *Channel)
static cString sprintf(const char *fmt,...) __attribute__((format(printf
#define CHANNELMOD_TRANSP
virtual void Append(T Data)
static bool IsTerr(int Code)
void MarkObsoleteChannels(int Source, int Nid, int Tid)
const char * ShortName(bool OrName=false) const
cChannel & operator=(const cChannel &Channel)
bool GroupSep(void) const
tChannelID & ClrPolarization(void)
int MaxChannelNameLength(void)
int nid
actually the "original" network id
cString ChannelString(const cChannel *Channel, int Number)
int Transponder(void) const
Returns the transponder frequency in MHz, plus the polarization in case of sat.
bool Load(const char *FileName, bool AllowComments=false, bool MustExist=false)
bool SetTransponderData(int Source, int Frequency, int Srate, const char *Parameters, bool Quiet=false)
#define LCN_OVERFLOW_OFFSET
const char * Name(void) const
cChannel * NewChannel(const cChannel *Transponder, const char *Name, const char *ShortName, const char *Provider, int Nid, int Tid, int Sid, int Rid=0)
T * Next(const T *object) const
void SetName(const char *Name, const char *ShortName, const char *Provider)
void SetTeletextSubtitlePages(tTeletextSubtitlePage pages[], int numberOfPages)
#define ISTRANSPONDER(f1, f2)
virtual int Compare(const cListObject &ListObject) const
Must return 0 if this object is equal to ListObject, a positive value if it is "greater", and a negative value if it is "smaller".
char alangs[MAXAPIDS][MAXLANGCODE2]
bool Parse(const char *s)
cListObject * Next(void) const
bool SwitchChannel(const cChannel *Channel, bool LiveView)
Switches the device to the given Channel, initiating transfer mode if necessary.
int GetNextNormal(int Idx)
int GetPrevNormal(int Idx)
void SetCaDescriptors(int Level)
char dlangs[MAXDPIDS][MAXLANGCODE2]
tChannelID GetChannelID(void) const
void SetModified(bool ByUser=false)
int GetNextGroup(int Idx)
cString TransponderDataToString(void) const
cChannel * GetByServiceID(int Source, int Transponder, unsigned short ServiceID)
static int IntArrayToString(char *s, const int *a, int Base=10, const char n[][MAXLANGCODE2]=NULL, const int *t=NULL)
void SetSubtitlingDescriptors(uchar *SubtitlingTypes, uint16_t *CompositionPageIds, uint16_t *AncillaryPageIds)
cChannel * GetByChannelID(tChannelID ChannelID, bool TryWithoutRid=false, bool TryWithoutPolarization=false)
bool HasTimer(void) const
char ttxtLanguage[MAXLANGCODE1]
void SetLinkChannels(cLinkChannels *LinkChannels)
bool HasUniqueChannelID(cChannel *NewChannel, cChannel *OldChannel=NULL)
cString ToString(void) const
void SetRefChannel(cChannel *RefChannel)
int ShowChannelNamesWithSource
cChannel * GetByNumber(int Number, int SkipGap=0)
tTeletextSubtitlePage teletextSubtitlePages[MAXTXTPAGES]
int PageNumber(void) const
static cDevice * PrimaryDevice(void)
Returns the primary device.
void DeleteDuplicateChannels(void)
static int FromString(const char *s)
static int IntArraysDiffer(const int *a, const int *b, const char na[][MAXLANGCODE2]=NULL, const char nb[][MAXLANGCODE2]=NULL)
char slangs[MAXSPIDS][MAXLANGCODE2]
cChannel * GetByTransponderID(tChannelID ChannelID)
static const tChannelID InvalidID
int Modification(int Mask=CHANNELMOD_ALL)
bool SwitchTo(int Number)
void UnhashChannel(cChannel *Channel)
cChannelSorter(cChannel *Channel)
void SetPids(int Vpid, int Ppid, int Vtype, int *Apids, int *Atypes, char ALangs[][MAXLANGCODE2], int *Dpids, int *Dtypes, char DLangs[][MAXLANGCODE2], int *Spids, char SLangs[][MAXLANGCODE2], int Tpid)
void SetPortalName(const char *PortalName)
tChannelID & ClrRid(void)
#define CHANNELMARKOBSOLETE
void SetCaIds(const int *CaIds)
cString ToText(void) const
int fixedTtxtSubtitlePages
void HashChannel(cChannel *Channel)