25 char *sourcebuf = NULL;
30 int fields = sscanf(s,
"%m[^-]-%d-%d-%d-%d", &sourcebuf, &nid, &tid, &sid, &rid);
31 if (fields == 4 || fields == 5) {
59 shortName = strdup(
"");
60 provider = strdup(
"");
61 portalName = strdup(
"");
62 memset(&__BeginData__, 0, (
char *)&__EndData__ - (
char *)&__BeginData__);
102 shortNameSource = NULL;
123 if (OrName &&
isempty(shortName))
128 return shortNameSource;
136 switch (toupper(Polarization)) {
137 case 'H': Frequency += 100000;
break;
138 case 'V': Frequency += 200000;
break;
139 case 'L': Frequency += 300000;
break;
140 case 'R': Frequency += 400000;
break;
141 default:
esyslog(
"ERROR: invalid value for Polarization '%c'", Polarization);
152 const char *p = strpbrk(parameters,
"HVLRhvlr");
154 tf = Transponder(tf, *p);
161 int Result = modification & Mask;
171 srate = Channel->
srate;
178 if (strchr(Parameters,
':')) {
179 esyslog(
"ERROR: parameter string '%s' contains ':'", Parameters);
185 if (abs(frequency - Frequency) <= 1)
186 Frequency = frequency;
191 if (abs(srate - Srate) <= 1)
194 if (
source != Source || frequency != Frequency || srate != Srate || strcmp(parameters, Parameters)) {
195 cString OldTransponderData = TransponderDataToString();
197 frequency = Frequency;
199 parameters = Parameters;
203 shortNameSource = NULL;
204 if (Number() && !Quiet) {
205 dsyslog(
"changing transponder data of channel %d (%s) from %s to %s", Number(), name, *OldTransponderData, *TransponderDataToString());
228 if (
nid != Nid ||
tid != Tid ||
sid != Sid ||
rid != Rid) {
229 if (Channels && Number()) {
230 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);
250 dsyslog(
"changing lcn of channel %d (%s) from %d to %d\n", Number(), name, lcn, Lcn);
260 bool nn = strcmp(name, Name) != 0;
261 bool ns = strcmp(shortName, ShortName) != 0;
262 bool np = strcmp(provider, Provider) != 0;
263 if (nn || ns || np) {
265 dsyslog(
"changing name of channel %d from '%s,%s;%s' to '%s,%s;%s'", Number(), name, shortName, provider, Name, ShortName, Provider);
275 shortNameSource = NULL;
287 if (!
isempty(PortalName) && strcmp(portalName, PortalName) != 0) {
289 dsyslog(
"changing portal name of channel %d (%s) from '%s' to '%s'", Number(), name, portalName, PortalName);
304 for (
int i = 0; a[i] || b[i]; i++) {
305 if (!a[i] || !b[i]) {
309 if (na && nb && strcmp(na[i], nb[i]) != 0)
321 while (a[i] || i == 0) {
322 q += sprintf(q, Base == 16 ?
"%s%X" :
"%s%d", i ?
"," :
"", a[i]);
323 const char *Delim =
"=";
326 q += sprintf(q,
"%s%s", Delim, n[i]);
330 q += sprintf(q,
"%s@%d", Delim, t[i]);
340 bool 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)
343 if (vpid != Vpid || ppid != Ppid || vtype != Vtype)
347 int m =
IntArraysDiffer(apids, Apids, alangs, ALangs) |
IntArraysDiffer(atypes, Atypes) |
IntArraysDiffer(dpids, Dpids, dlangs, DLangs) |
IntArraysDiffer(dtypes, Dtypes) |
IntArraysDiffer(spids, Spids, slangs, SLangs);
353 const int BufferSize = (
MAXAPIDS +
MAXDPIDS) * (5 + 1 + MAXLANGCODE2 + 5) + 10;
354 char OldApidsBuf[BufferSize];
355 char NewApidsBuf[BufferSize];
356 char *q = OldApidsBuf;
371 char OldSpidsBuf[SBufferSize];
372 char NewSpidsBuf[SBufferSize];
380 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);
384 for (
int i = 0; i <
MAXAPIDS; i++) {
386 atypes[i] = Atypes[i];
387 strn0cpy(alangs[i], ALangs[i], MAXLANGCODE2);
390 for (
int i = 0; i <
MAXDPIDS; i++) {
392 dtypes[i] = Dtypes[i];
393 strn0cpy(dlangs[i], DLangs[i], MAXLANGCODE2);
396 for (
int i = 0; i <
MAXSPIDS; i++) {
398 strn0cpy(slangs[i], SLangs[i], MAXLANGCODE2);
410 bool Modified =
false;
411 if (SubtitlingTypes) {
412 for (
int i = 0; i <
MAXSPIDS; i++) {
413 Modified = subtitlingTypes[i] != SubtitlingTypes[i];
414 subtitlingTypes[i] = SubtitlingTypes[i];
417 if (CompositionPageIds) {
418 for (
int i = 0; i <
MAXSPIDS; i++) {
419 Modified = compositionPageIds[i] != CompositionPageIds[i];
420 compositionPageIds[i] = CompositionPageIds[i];
423 if (AncillaryPageIds) {
424 for (
int i = 0; i <
MAXSPIDS; i++) {
425 Modified = ancillaryPageIds[i] != AncillaryPageIds[i];
426 ancillaryPageIds[i] = AncillaryPageIds[i];
440 for (
cLinkChannel *lc = linkChannels->First(); lc; lc = linkChannels->
Next(lc)) {
441 if (lc->Channel() == LinkChannel) {
442 linkChannels->Del(lc);
446 if (linkChannels->Count() == 0) {
458 char OldCaIdsBuf[
MAXCAIDS * 5 + 10];
459 char NewCaIdsBuf[
MAXCAIDS * 5 + 10];
463 dsyslog(
"changing caids of channel %d (%s) from %s to %s", Number(), name, OldCaIdsBuf, NewCaIdsBuf);
464 for (
int i = 0; i <=
MAXCAIDS; i++) {
479 if (Number() && Level > 1)
480 dsyslog(
"changing ca descriptors of channel %d (%s)", Number(), name);
488 if (!linkChannels && !LinkChannels)
490 if (linkChannels && LinkChannels) {
498 lca = linkChannels->
Next(lca);
499 lcb = LinkChannels->
Next(lcb);
506 char buffer[((linkChannels ? linkChannels->Count() : 0) + (LinkChannels ? LinkChannels->
Count() : 0)) * 6 + 256];
508 q += sprintf(q,
"linking channel %d (%s) from", Number(), name);
510 for (
cLinkChannel *lc = linkChannels->First(); lc; lc = linkChannels->
Next(lc)) {
511 lc->Channel()->SetRefChannel(NULL);
512 q += sprintf(q,
" %d", lc->Channel()->Number());
517 q += sprintf(q,
" none");
518 q += sprintf(q,
" to");
519 linkChannels = LinkChannels;
521 for (
cLinkChannel *lc = linkChannels->First(); lc; lc = linkChannels->
Next(lc)) {
522 lc->Channel()->SetRefChannel(
this);
523 q += sprintf(q,
" %d", lc->Channel()->Number());
528 q += sprintf(q,
" none");
536 refChannel = RefChannel;
548 char FullName[strlen(Channel->
name) + 1 + strlen(Channel->
shortName) + 1 + strlen(Channel->
provider) + 1 + 10];
550 q += sprintf(q,
"%s", Channel->
name);
553 q += sprintf(q,
",%s", Channel->
shortName);
554 else if (strchr(Channel->
name,
','))
555 q += sprintf(q,
",");
557 q += sprintf(q,
";%s", Channel->
provider);
571 q += snprintf(q,
sizeof(vpidbuf),
"%d", Channel->
vpid);
573 q += snprintf(q,
sizeof(vpidbuf) - (q - vpidbuf),
"+%d", Channel->
ppid);
575 q += snprintf(q,
sizeof(vpidbuf) - (q - vpidbuf),
"=%d", Channel->
vtype);
578 char apidbuf[ABufferSize];
581 if (Channel->
dpids[0]) {
587 char tpidbuf[TBufferSize];
589 q += snprintf(q,
sizeof(tpidbuf),
"%d", Channel->
tpid);
590 if (Channel->
spids[0]) {
598 buffer =
cString::sprintf(
"%s:%d:%s:%s:%d:%s:%s:%s:%s:%d:%d:%d:%d", FullName, Channel->
frequency, *Channel->
parameters, *
cSource::ToString(Channel->
source), Channel->
srate, vpidbuf, apidbuf, tpidbuf, caidbuf, Channel->
sid, Channel->
nid, Channel->
tid, Channel->
rid);
613 if (*++s ==
'@' && *++s) {
616 int n = strtol(s, &p, 10);
617 if (!errno && p != s && n > 0) {
627 char *namebuf = NULL;
628 char *sourcebuf = NULL;
629 char *parambuf = NULL;
630 char *vpidbuf = NULL;
631 char *apidbuf = NULL;
632 char *tpidbuf = NULL;
633 char *caidbuf = NULL;
634 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);
641 if (sscanf(tpidbuf,
"%d", &tpid) != 1)
655 if (parambuf && sourcebuf && vpidbuf && apidbuf) {
656 parameters = parambuf;
660 if ((p = strchr(vpidbuf,
'=')) != NULL) {
662 if (sscanf(p,
"%d", &vtype) != 1)
665 if ((p = strchr(vpidbuf,
'+')) != NULL) {
667 if (sscanf(p,
"%d", &ppid) != 1)
670 if (sscanf(vpidbuf,
"%d", &vpid) != 1)
677 char *dpidbuf = strchr(apidbuf,
';');
684 while ((q = strtok_r(p,
",", &strtok_next)) != NULL) {
686 atypes[NumApids] = 4;
687 char *l = strchr(q,
'=');
690 char *t = strchr(l,
'@');
693 atypes[NumApids] = strtol(t, NULL, 10);
698 *alangs[NumApids] = 0;
699 if ((apids[NumApids] = strtol(q, NULL, 10)) != 0)
703 esyslog(
"ERROR: too many APIDs!");
707 atypes[NumApids] = 0;
713 while ((q = strtok_r(p,
",", &strtok_next)) != NULL) {
716 char *l = strchr(q,
'=');
719 char *t = strchr(l,
'@');
722 dtypes[NumDpids] = strtol(t, NULL, 10);
727 *dlangs[NumDpids] = 0;
728 if ((dpids[NumDpids] = strtol(q, NULL, 10)) != 0)
732 esyslog(
"ERROR: too many DPIDs!");
736 dtypes[NumDpids] = 0;
739 if ((p = strchr(tpidbuf,
';')) != NULL) {
743 while ((q = strtok_r(p,
",", &strtok_next)) != NULL) {
745 char *l = strchr(q,
'=');
751 *slangs[NumSpids] = 0;
752 spids[NumSpids++] = strtol(q, NULL, 10);
755 esyslog(
"ERROR: too many SPIDs!");
760 if (sscanf(tpidbuf,
"%d", &tpid) != 1)
767 while ((q = strtok_r(p,
",", &strtok_next)) != NULL) {
769 caids[NumCaIds++] = strtol(q, NULL, 16) & 0xFFFF;
774 esyslog(
"ERROR: too many CA ids!");
782 char *p = strchr(namebuf,
';');
787 p = strrchr(namebuf,
',');
803 shortNameSource = NULL;
804 if (!GetChannelID().
Valid()) {
805 esyslog(
"ERROR: channel data results in invalid ID!");
817 return fprintf(f,
"%s\n", *ToText()) > 0;
832 return memcmp(&channelID, &cs->
channelID,
sizeof(channelID));
863 if (!Channel->GroupSep())
866 ChannelSorter.
Sort();
881 if (
channels.cConfig<cChannel>::Load(FileName, AllowComments, MustExist)) {
902 while (Channel && !(Channel->
GroupSep() && *Channel->
Name()))
903 Channel =
Get(++Idx);
904 return Channel ? Idx : -1;
910 while (Channel && !(Channel->
GroupSep() && *Channel->
Name()))
911 Channel =
Get(--Idx);
912 return Channel ? Idx : -1;
918 while (Channel && Channel->
GroupSep())
919 Channel =
Get(++Idx);
920 return Channel ? Idx : -1;
926 while (Channel && Channel->
GroupSep())
927 Channel =
Get(--Idx);
928 return Channel ? Idx : -1;
937 if (Channel->GroupSep()) {
938 if (Channel->Number() > Number)
939 Number = Channel->Number();
944 Channel->SetNumber(Number++);
953 ch->DelLinkChannel(Channel);
961 if (!Channel->GroupSep()) {
962 if (Channel->Number() == Number)
964 else if (SkipGap && Channel->Number() > Number)
965 return SkipGap > 0 ? Channel : Previous;
987 int sid = ChannelID.
Sid();
1003 if (TryWithoutPolarization) {
1017 int source = ChannelID.
Source();
1018 int nid = ChannelID.
Nid();
1019 int tid = ChannelID.
Tid();
1021 if (Channel->Tid() == tid && Channel->Nid() == nid && Channel->Source() == source)
1031 if (!Channel->GroupSep() && Channel != OldChannel && Channel->
GetChannelID() == NewChannelID)
1047 for (
const cChannel *Channel = Channels->First(); Channel; Channel = Channels->
Next(Channel)) {
1048 if (!Channel->GroupSep())
1059 for (
const cChannel *Channel = Channels->First(); Channel; Channel = Channels->
Next(Channel)) {
1060 if (!Channel->GroupSep())
1083 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);
1086 NewChannel->SetId(
this, Nid, Tid, Sid, Rid);
1087 NewChannel->SetName(Name, ShortName, Provider);
1088 NewChannel->SetSeen();
1096 #define CHANNELMARKOBSOLETE "OBSOLETE" 1097 #define CHANNELTIMEOBSOLETE 3600 // seconds to wait before declaring a channel obsolete (in case it has actually been seen before) 1101 bool ChannelsModified =
false;
1103 if (time(NULL) - Channel->Seen() >
CHANNELTIMEOBSOLETE && Channel->Source() == Source && Channel->Nid() == Nid && Channel->Tid() == Tid && Channel->Rid() == 0) {
1111 return ChannelsModified;
1119 snprintf(buffer,
sizeof(buffer),
"%s", Channel->
Name());
1121 snprintf(buffer,
sizeof(buffer),
"%d%s %s", Channel->
Number(), Number ?
"-" :
"", Channel->
Name());
1124 snprintf(buffer,
sizeof(buffer),
"%d-", Number);
1126 snprintf(buffer,
sizeof(buffer),
"%s",
tr(
"*** Invalid Channel ***"));
bool Lock(cStateKey &StateKey, bool Write=false, int TimeoutMs=0) const
Tries to get a lock on this list and returns true if successful.
static cString ToString(int Code)
bool SetName(const char *Name, const char *ShortName, const char *Provider)
static const cChannels * GetChannelsRead(cStateKey &StateKey, int TimeoutMs=0)
Gets the list of channels for read access.
#define CHANNELTIMEOBSOLETE
const cChannel * GetByTransponderID(tChannelID ChannelID) const
bool 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)
static char ToChar(int Code)
static tChannelID FromString(const char *s)
bool SetPortalName(const char *PortalName)
static int MaxShortChannelNameLength(void)
void CopyTransponderData(const cChannel *Channel)
cList< cHashObject > * GetList(unsigned int Id) const
int Modification(int Mask=CHANNELMOD_ALL) const
void Add(cListObject *Object, cListObject *After=NULL)
static cString ToText(const cChannel *Channel)
bool HasUniqueChannelID(const cChannel *NewChannel, const cChannel *OldChannel=NULL) const
static cString sprintf(const char *fmt,...) __attribute__((format(printf
#define CHANNELMOD_TRANSP
void Del(cListObject *Object, unsigned int Id)
static bool IsTerr(int Code)
static int maxChannelNameLength
int GetPrevGroup(int Idx) const
Get previous channel group.
const char * ShortName(bool OrName=false) const
bool SetId(cChannels *Channels, int Nid, int Tid, int Sid, int Rid=0)
cChannel & operator=(const cChannel &Channel)
bool GroupSep(void) const
tChannelID & ClrPolarization(void)
const cChannel * GetByServiceID(int Source, int Transponder, unsigned short ServiceID) const
void ReNumber(void)
Recalculate 'number' based on channel type.
static 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.
#define LOCK_CHANNELS_WRITE
const char * FileName(void)
static int maxShortChannelNameLength
static 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)
static cChannels * GetChannelsWrite(cStateKey &StateKey, int TimeoutMs=0)
Gets the list of channels for write access.
static cChannels channels
const char * Name(void) const
void Del(cChannel *Channel)
Delete the given Channel from the list.
cChannel * NewChannel(const cChannel *Transponder, const char *Name, const char *ShortName, const char *Provider, int Nid, int Tid, int Sid, int Rid=0)
#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".
int GetPrevNormal(int Idx) const
Get previous normal channel (not group)
char alangs[MAXAPIDS][MAXLANGCODE2]
const cChannel * GetByChannelID(tChannelID ChannelID, bool TryWithoutRid=false, bool TryWithoutPolarization=false) const
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.
#define LOCK_CHANNELS_READ
int GetNextNormal(int Idx) const
Get next normal channel (not group)
bool ModifiedByUser(int &State) const
Returns true if the channels have been modified by the user since the last call to this function with...
char dlangs[MAXDPIDS][MAXLANGCODE2]
tChannelID GetChannelID(void) const
const T * Next(const T *Object) const
< Returns the element immediately before Object in this list, or NULL if Object is the first element ...
cString TransponderDataToString(void) const
void DelLinkChannel(cChannel *LinkChannel)
static int IntArrayToString(char *s, const int *a, int Base=10, const char n[][MAXLANGCODE2]=NULL, const int *t=NULL)
bool SwitchTo(int Number) const
bool SetSubtitlingDescriptors(uchar *SubtitlingTypes, uint16_t *CompositionPageIds, uint16_t *AncillaryPageIds)
void Del(cListObject *Object, bool DeleteObject=true)
cString ToString(void) const
void SetRefChannel(cChannel *RefChannel)
int ShowChannelNamesWithSource
static cDevice * PrimaryDevice(void)
Returns the primary device.
void DeleteDuplicateChannels(void)
static int FromString(const char *s)
const cChannel * GetByNumber(int Number, int SkipGap=0) const
bool SetLinkChannels(cLinkChannels *LinkChannels)
static int IntArraysDiffer(const int *a, const int *b, const char na[][MAXLANGCODE2]=NULL, const char nb[][MAXLANGCODE2]=NULL)
char slangs[MAXSPIDS][MAXLANGCODE2]
bool SetSource(int Source)
void Add(cListObject *Object, unsigned int Id)
cHash< cChannel > channelsHashSid
static const tChannelID InvalidID
void UnhashChannel(cChannel *Channel)
const cChannel * Get(int Index) const
Returns the list element at the given Index, or NULL if no such element exists.
const T * First(void) const
Returns the first element in this list, or NULL if the list is empty.
cChannelSorter(cChannel *Channel)
int GetNextGroup(int Idx) const
Get next channel group.
bool SetCaIds(const int *CaIds)
bool MarkObsoleteChannels(int Source, int Nid, int Tid)
tChannelID & ClrRid(void)
#define CHANNELMARKOBSOLETE
void SetModifiedByUser(void)
cString ToText(void) const
void HashChannel(cChannel *Channel)
bool SetCaDescriptors(int Level)