vdr  2.4.0
channels.c
Go to the documentation of this file.
1 /*
2  * channels.c: Channel handling
3  *
4  * See the main source file 'vdr.c' for copyright information and
5  * how to reach the author.
6  *
7  * $Id: channels.c 4.5 2017/06/10 15:08:56 kls Exp $
8  */
9 
10 #include "channels.h"
11 #include <ctype.h>
12 #include "device.h"
13 #include "libsi/si.h"
14 
15 // IMPORTANT NOTE: in the 'sscanf()' calls there is a blank after the '%d'
16 // format characters in order to allow any number of blanks after a numeric
17 // value!
18 
19 // --- tChannelID ------------------------------------------------------------
20 
22 
24 {
25  char *sourcebuf = NULL;
26  int nid;
27  int tid;
28  int sid;
29  int rid = 0;
30  int fields = sscanf(s, "%m[^-]-%d-%d-%d-%d", &sourcebuf, &nid, &tid, &sid, &rid);
31  if (fields == 4 || fields == 5) {
32  int source = cSource::FromString(sourcebuf);
33  free(sourcebuf);
34  if (source >= 0)
35  return tChannelID(source, nid, tid, sid, rid);
36  }
37  return tChannelID::InvalidID;
38 }
39 
41 {
42  char buffer[256];
43  snprintf(buffer, sizeof(buffer), rid ? "%s-%d-%d-%d-%d" : "%s-%d-%d-%d", *cSource::ToString(source), nid, tid, sid, rid);
44  return buffer;
45 }
46 
48 {
49  while (tid > 100000)
50  tid -= 100000;
51  return *this;
52 }
53 
54 // --- cChannel --------------------------------------------------------------
55 
57 {
58  name = strdup("");
59  shortName = strdup("");
60  provider = strdup("");
61  portalName = strdup("");
62  memset(&__BeginData__, 0, (char *)&__EndData__ - (char *)&__BeginData__);
63  parameters = "";
65  seen = 0;
66  schedule = NULL;
67  linkChannels = NULL;
68  refChannel = NULL;
69 }
70 
72 {
73  name = NULL;
74  shortName = NULL;
75  provider = NULL;
76  portalName = NULL;
77  schedule = NULL;
78  linkChannels = NULL;
79  refChannel = NULL;
80  seen = 0;
81  *this = Channel;
82 }
83 
85 {
86  delete linkChannels; // any links from other channels pointing to this one have been deleted in cChannels::Del()
87  free(name);
88  free(shortName);
89  free(provider);
90  free(portalName);
91 }
92 
94 {
95  name = strcpyrealloc(name, Channel.name);
99  memcpy(&__BeginData__, &Channel.__BeginData__, (char *)&Channel.__EndData__ - (char *)&Channel.__BeginData__);
100  nameSource = NULL; // these will be recalculated automatically
101  nameSourceMode = 0;
102  shortNameSource = NULL;
103  parameters = Channel.parameters;
104  return *this;
105 }
106 
107 const char *cChannel::Name(void) const
108 {
113  else
115  }
116  return nameSource;
117  }
118  return name;
119 }
120 
121 const char *cChannel::ShortName(bool OrName) const
122 {
123  if (OrName && isempty(shortName))
124  return Name();
128  return shortNameSource;
129  }
130  return shortName;
131 }
132 
133 int cChannel::Transponder(int Frequency, char Polarization)
134 {
135  // some satellites have transponders at the same frequency, just with different polarization:
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);
142  }
143  return Frequency;
144 }
145 
146 int cChannel::Transponder(void) const
147 {
148  int tf = frequency;
149  while (tf > 20000)
150  tf /= 1000;
151  if (IsSat()) {
152  const char *p = strpbrk(parameters, "HVLRhvlr"); // lowercase for backwards compatibility
153  if (p)
154  tf = Transponder(tf, *p);
155  }
156  return tf;
157 }
158 
159 int cChannel::Modification(int Mask) const
160 {
161  int Result = modification & Mask;
163  return Result;
164 }
165 
167 {
168  if (Channel) {
169  frequency = Channel->frequency;
170  source = Channel->source;
171  srate = Channel->srate;
172  parameters = Channel->parameters;
173  }
174 }
175 
176 bool cChannel::SetTransponderData(int Source, int Frequency, int Srate, const char *Parameters, bool Quiet)
177 {
178  if (strchr(Parameters, ':')) {
179  esyslog("ERROR: parameter string '%s' contains ':'", Parameters);
180  return false;
181  }
182  // Workarounds for broadcaster stupidity:
183  // Some providers broadcast the transponder frequency of their channels with two different
184  // values (like 12551 and 12552), so we need to allow for a little tolerance here
185  if (abs(frequency - Frequency) <= 1)
187  // Sometimes the transponder frequency is set to 0, which is just wrong
188  if (Frequency == 0)
189  return false;
190  // Sometimes the symbol rate is off by one
191  if (abs(srate - Srate) <= 1)
192  Srate = srate;
193 
194  if (source != Source || frequency != Frequency || srate != Srate || strcmp(parameters, Parameters)) {
195  cString OldTransponderData = TransponderDataToString();
196  source = Source;
198  srate = Srate;
200  schedule = NULL;
201  nameSource = NULL;
202  nameSourceMode = 0;
203  shortNameSource = NULL;
204  if (Number() && !Quiet) {
205  dsyslog("changing transponder data of channel %d (%s) from %s to %s", Number(), name, *OldTransponderData, *TransponderDataToString());
207  }
208  return true;
209  }
210  return false;
211 }
212 
213 bool cChannel::SetSource(int Source)
214 {
215  if (source != Source) {
216  if (Number()) {
217  dsyslog("changing source of channel %d (%s) from %s to %s", Number(), name, *cSource::ToString(source), *cSource::ToString(Source));
219  }
220  source = Source;
221  return true;
222  }
223  return false;
224 }
225 
226 bool cChannel::SetId(cChannels *Channels, int Nid, int Tid, int Sid, int Rid)
227 {
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);
232  Channels->UnhashChannel(this);
233  }
234  nid = Nid;
235  tid = Tid;
236  sid = Sid;
237  rid = Rid;
238  if (Channels)
239  Channels->HashChannel(this);
240  schedule = NULL;
241  return true;
242  }
243  return false;
244 }
245 
246 bool cChannel::SetLcn(int Lcn)
247 {
248  if (lcn != Lcn) {
249  if (Number())
250  dsyslog("changing lcn of channel %d (%s) from %d to %d\n", Number(), name, lcn, Lcn);
251  lcn = Lcn;
252  return true;
253  }
254  return false;
255 }
256 
257 bool cChannel::SetName(const char *Name, const char *ShortName, const char *Provider)
258 {
259  if (!isempty(Name)) {
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) {
264  if (Number()) {
265  dsyslog("changing name of channel %d from '%s,%s;%s' to '%s,%s;%s'", Number(), name, shortName, provider, Name, ShortName, Provider);
267  }
268  if (nn) {
270  nameSource = NULL;
271  nameSourceMode = 0;
272  }
273  if (ns) {
275  shortNameSource = NULL;
276  }
277  if (np)
279  return true;
280  }
281  }
282  return false;
283 }
284 
285 bool cChannel::SetPortalName(const char *PortalName)
286 {
287  if (!isempty(PortalName) && strcmp(portalName, PortalName) != 0) {
288  if (Number()) {
289  dsyslog("changing portal name of channel %d (%s) from '%s' to '%s'", Number(), name, portalName, PortalName);
291  }
293  return true;
294  }
295  return false;
296 }
297 
298 #define STRDIFF 0x01
299 #define VALDIFF 0x02
300 
301 static int IntArraysDiffer(const int *a, const int *b, const char na[][MAXLANGCODE2] = NULL, const char nb[][MAXLANGCODE2] = NULL)
302 {
303  int result = 0;
304  for (int i = 0; a[i] || b[i]; i++) {
305  if (!a[i] || !b[i]) {
306  result |= VALDIFF;
307  break;
308  }
309  if (na && nb && strcmp(na[i], nb[i]) != 0)
310  result |= STRDIFF;
311  if (a[i] != b[i])
312  result |= VALDIFF;
313  }
314  return result;
315 }
316 
317 static int IntArrayToString(char *s, const int *a, int Base = 10, const char n[][MAXLANGCODE2] = NULL, const int *t = NULL)
318 {
319  char *q = s;
320  int 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 = "=";
324  if (a[i]) {
325  if (n && *n[i]) {
326  q += sprintf(q, "%s%s", Delim, n[i]);
327  Delim = "";
328  }
329  if (t && t[i])
330  q += sprintf(q, "%s@%d", Delim, t[i]);
331  }
332  if (!a[i])
333  break;
334  i++;
335  }
336  *q = 0;
337  return q - s;
338 }
339 
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)
341 {
342  int mod = CHANNELMOD_NONE;
343  if (vpid != Vpid || ppid != Ppid || vtype != Vtype)
344  mod |= CHANNELMOD_PIDS;
345  if (tpid != Tpid)
346  mod |= CHANNELMOD_AUX;
347  int m = IntArraysDiffer(apids, Apids, alangs, ALangs) | IntArraysDiffer(atypes, Atypes) | IntArraysDiffer(dpids, Dpids, dlangs, DLangs) | IntArraysDiffer(dtypes, Dtypes) | IntArraysDiffer(spids, Spids, slangs, SLangs);
348  if (m & STRDIFF)
349  mod |= CHANNELMOD_LANGS;
350  if (m & VALDIFF)
351  mod |= CHANNELMOD_PIDS;
352  if (mod) {
353  const int BufferSize = (MAXAPIDS + MAXDPIDS) * (5 + 1 + MAXLANGCODE2 + 5) + 10; // 5 digits plus delimiting ',' or ';' plus optional '=cod+cod@type', +10: paranoia
354  char OldApidsBuf[BufferSize];
355  char NewApidsBuf[BufferSize];
356  char *q = OldApidsBuf;
357  q += IntArrayToString(q, apids, 10, alangs, atypes);
358  if (dpids[0]) {
359  *q++ = ';';
360  q += IntArrayToString(q, dpids, 10, dlangs, dtypes);
361  }
362  *q = 0;
363  q = NewApidsBuf;
364  q += IntArrayToString(q, Apids, 10, ALangs, Atypes);
365  if (Dpids[0]) {
366  *q++ = ';';
367  q += IntArrayToString(q, Dpids, 10, DLangs, Dtypes);
368  }
369  *q = 0;
370  const int SBufferSize = MAXSPIDS * (5 + 1 + MAXLANGCODE2) + 10; // 5 digits plus delimiting ',' or ';' plus optional '=cod', +10: paranoia
371  char OldSpidsBuf[SBufferSize];
372  char NewSpidsBuf[SBufferSize];
373  q = OldSpidsBuf;
374  q += IntArrayToString(q, spids, 10, slangs);
375  *q = 0;
376  q = NewSpidsBuf;
377  q += IntArrayToString(q, Spids, 10, SLangs);
378  *q = 0;
379  if (Number())
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);
381  vpid = Vpid;
382  ppid = Ppid;
383  vtype = Vtype;
384  for (int i = 0; i < MAXAPIDS; i++) {
385  apids[i] = Apids[i];
386  atypes[i] = Atypes[i];
387  strn0cpy(alangs[i], ALangs[i], MAXLANGCODE2);
388  }
389  apids[MAXAPIDS] = 0;
390  for (int i = 0; i < MAXDPIDS; i++) {
391  dpids[i] = Dpids[i];
392  dtypes[i] = Dtypes[i];
393  strn0cpy(dlangs[i], DLangs[i], MAXLANGCODE2);
394  }
395  dpids[MAXDPIDS] = 0;
396  for (int i = 0; i < MAXSPIDS; i++) {
397  spids[i] = Spids[i];
398  strn0cpy(slangs[i], SLangs[i], MAXLANGCODE2);
399  }
400  spids[MAXSPIDS] = 0;
401  tpid = Tpid;
402  modification |= mod;
403  return true;
404  }
405  return false;
406 }
407 
408 bool cChannel::SetSubtitlingDescriptors(uchar *SubtitlingTypes, uint16_t *CompositionPageIds, uint16_t *AncillaryPageIds)
409 {
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];
415  }
416  }
417  if (CompositionPageIds) {
418  for (int i = 0; i < MAXSPIDS; i++) {
419  Modified = compositionPageIds[i] != CompositionPageIds[i];
420  compositionPageIds[i] = CompositionPageIds[i];
421  }
422  }
423  if (AncillaryPageIds) {
424  for (int i = 0; i < MAXSPIDS; i++) {
425  Modified = ancillaryPageIds[i] != AncillaryPageIds[i];
426  ancillaryPageIds[i] = AncillaryPageIds[i];
427  }
428  }
429  return Modified;
430 }
431 
433 {
434  seen = time(NULL);
435 }
436 
438 {
439  if (linkChannels) {
440  for (cLinkChannel *lc = linkChannels->First(); lc; lc = linkChannels->Next(lc)) {
441  if (lc->Channel() == LinkChannel) {
442  linkChannels->Del(lc);
443  break;
444  }
445  }
446  if (linkChannels->Count() == 0) {
447  delete linkChannels;
448  linkChannels = NULL;
449  }
450  }
451 }
452 
453 bool cChannel::SetCaIds(const int *CaIds)
454 {
455  if (caids[0] && caids[0] <= CA_USER_MAX)
456  return false; // special values will not be overwritten
457  if (IntArraysDiffer(caids, CaIds)) {
458  char OldCaIdsBuf[MAXCAIDS * 5 + 10]; // 5: 4 digits plus delimiting ',', 10: paranoia
459  char NewCaIdsBuf[MAXCAIDS * 5 + 10];
460  IntArrayToString(OldCaIdsBuf, caids, 16);
461  IntArrayToString(NewCaIdsBuf, CaIds, 16);
462  if (Number())
463  dsyslog("changing caids of channel %d (%s) from %s to %s", Number(), name, OldCaIdsBuf, NewCaIdsBuf);
464  for (int i = 0; i <= MAXCAIDS; i++) { // <= to copy the terminating 0
465  caids[i] = CaIds[i];
466  if (!CaIds[i])
467  break;
468  }
470  return true;
471  }
472  return false;
473 }
474 
476 {
477  if (Level > 0) {
479  if (Number() && Level > 1)
480  dsyslog("changing ca descriptors of channel %d (%s)", Number(), name);
481  return true;
482  }
483  return false;
484 }
485 
487 {
488  if (!linkChannels && !LinkChannels)
489  return false;
490  if (linkChannels && LinkChannels) {
491  cLinkChannel *lca = linkChannels->First();
492  cLinkChannel *lcb = LinkChannels->First();
493  while (lca && lcb) {
494  if (lca->Channel() != lcb->Channel()) {
495  lca = NULL;
496  break;
497  }
498  lca = linkChannels->Next(lca);
499  lcb = LinkChannels->Next(lcb);
500  }
501  if (!lca && !lcb) {
502  delete LinkChannels;
503  return false; // linkage has not changed
504  }
505  }
506  char buffer[((linkChannels ? linkChannels->Count() : 0) + (LinkChannels ? LinkChannels->Count() : 0)) * 6 + 256]; // 6: 5 digit channel number plus blank, 256: other texts (see below) plus reserve
507  char *q = buffer;
508  q += sprintf(q, "linking channel %d (%s) from", Number(), name);
509  if (linkChannels) {
510  for (cLinkChannel *lc = linkChannels->First(); lc; lc = linkChannels->Next(lc)) {
511  lc->Channel()->SetRefChannel(NULL);
512  q += sprintf(q, " %d", lc->Channel()->Number());
513  }
514  delete linkChannels;
515  }
516  else
517  q += sprintf(q, " none");
518  q += sprintf(q, " to");
520  if (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());
524  //dsyslog("link %4d -> %4d: %s", Number(), lc->Channel()->Number(), lc->Channel()->Name());
525  }
526  }
527  else
528  q += sprintf(q, " none");
529  if (Number())
530  dsyslog("%s", buffer);
531  return true;
532 }
533 
535 {
537 }
538 
540 {
541  if (cSource::IsTerr(source))
543  return cString::sprintf("%d:%s:%s:%d", frequency, *parameters, *cSource::ToString(source), srate);
544 }
545 
547 {
548  char FullName[strlen(Channel->name) + 1 + strlen(Channel->shortName) + 1 + strlen(Channel->provider) + 1 + 10]; // +10: paranoia
549  char *q = FullName;
550  q += sprintf(q, "%s", Channel->name);
551  if (!Channel->groupSep) {
552  if (!isempty(Channel->shortName))
553  q += sprintf(q, ",%s", Channel->shortName);
554  else if (strchr(Channel->name, ','))
555  q += sprintf(q, ",");
556  if (!isempty(Channel->provider))
557  q += sprintf(q, ";%s", Channel->provider);
558  }
559  *q = 0;
560  strreplace(FullName, ':', '|');
561  cString buffer;
562  if (Channel->groupSep) {
563  if (Channel->number)
564  buffer = cString::sprintf(":@%d %s", Channel->number, FullName);
565  else
566  buffer = cString::sprintf(":%s", FullName);
567  }
568  else {
569  char vpidbuf[32];
570  char *q = vpidbuf;
571  q += snprintf(q, sizeof(vpidbuf), "%d", Channel->vpid);
572  if (Channel->ppid && Channel->ppid != Channel->vpid)
573  q += snprintf(q, sizeof(vpidbuf) - (q - vpidbuf), "+%d", Channel->ppid);
574  if (Channel->vpid && Channel->vtype)
575  q += snprintf(q, sizeof(vpidbuf) - (q - vpidbuf), "=%d", Channel->vtype);
576  *q = 0;
577  const int ABufferSize = (MAXAPIDS + MAXDPIDS) * (5 + 1 + MAXLANGCODE2 + 5) + 10; // 5 digits plus delimiting ',' or ';' plus optional '=cod+cod@type', +10: paranoia
578  char apidbuf[ABufferSize];
579  q = apidbuf;
580  q += IntArrayToString(q, Channel->apids, 10, Channel->alangs, Channel->atypes);
581  if (Channel->dpids[0]) {
582  *q++ = ';';
583  q += IntArrayToString(q, Channel->dpids, 10, Channel->dlangs, Channel->dtypes);
584  }
585  *q = 0;
586  const int TBufferSize = MAXSPIDS * (5 + 1 + MAXLANGCODE2) + 10; // 5 digits plus delimiting ',' or ';' plus optional '=cod+cod', +10: paranoia and tpid
587  char tpidbuf[TBufferSize];
588  q = tpidbuf;
589  q += snprintf(q, sizeof(tpidbuf), "%d", Channel->tpid);
590  if (Channel->spids[0]) {
591  *q++ = ';';
592  q += IntArrayToString(q, Channel->spids, 10, Channel->slangs);
593  }
594  char caidbuf[MAXCAIDS * 5 + 10]; // 5: 4 digits plus delimiting ',', 10: paranoia
595  q = caidbuf;
596  q += IntArrayToString(q, Channel->caids, 16);
597  *q = 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);
599  }
600  return buffer;
601 }
602 
604 {
605  return ToText(this);
606 }
607 
608 bool cChannel::Parse(const char *s)
609 {
610  bool ok = true;
611  if (*s == ':') {
612  groupSep = true;
613  if (*++s == '@' && *++s) {
614  char *p = NULL;
615  errno = 0;
616  int n = strtol(s, &p, 10);
617  if (!errno && p != s && n > 0) {
618  number = n;
619  s = p;
620  }
621  }
623  strreplace(name, '|', ':');
624  }
625  else {
626  groupSep = false;
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, &parambuf, &sourcebuf, &srate, &vpidbuf, &apidbuf, &tpidbuf, &caidbuf, &sid, &nid, &tid, &rid);
635  if (fields >= 9) {
636  if (fields == 9) {
637  // allow reading of old format
638  sid = atoi(caidbuf);
639  delete caidbuf;
640  caidbuf = NULL;
641  if (sscanf(tpidbuf, "%d", &tpid) != 1)
642  return false;
643  caids[0] = tpid;
644  caids[1] = 0;
645  tpid = 0;
646  }
647  vpid = ppid = 0;
648  vtype = 0;
649  apids[0] = 0;
650  atypes[0] = 0;
651  dpids[0] = 0;
652  dtypes[0] = 0;
653  spids[0] = 0;
654  ok = false;
655  if (parambuf && sourcebuf && vpidbuf && apidbuf) {
656  parameters = parambuf;
657  ok = (source = cSource::FromString(sourcebuf)) >= 0;
658 
659  char *p;
660  if ((p = strchr(vpidbuf, '=')) != NULL) {
661  *p++ = 0;
662  if (sscanf(p, "%d", &vtype) != 1)
663  return false;
664  }
665  if ((p = strchr(vpidbuf, '+')) != NULL) {
666  *p++ = 0;
667  if (sscanf(p, "%d", &ppid) != 1)
668  return false;
669  }
670  if (sscanf(vpidbuf, "%d", &vpid) != 1)
671  return false;
672  if (!ppid)
673  ppid = vpid;
674  if (vpid && !vtype)
675  vtype = 2; // default is MPEG-2
676 
677  char *dpidbuf = strchr(apidbuf, ';');
678  if (dpidbuf)
679  *dpidbuf++ = 0;
680  p = apidbuf;
681  char *q;
682  int NumApids = 0;
683  char *strtok_next;
684  while ((q = strtok_r(p, ",", &strtok_next)) != NULL) {
685  if (NumApids < MAXAPIDS) {
686  atypes[NumApids] = 4; // backwards compatibility
687  char *l = strchr(q, '=');
688  if (l) {
689  *l++ = 0;
690  char *t = strchr(l, '@');
691  if (t) {
692  *t++ = 0;
693  atypes[NumApids] = strtol(t, NULL, 10);
694  }
695  strn0cpy(alangs[NumApids], l, MAXLANGCODE2);
696  }
697  else
698  *alangs[NumApids] = 0;
699  if ((apids[NumApids] = strtol(q, NULL, 10)) != 0)
700  NumApids++;
701  }
702  else
703  esyslog("ERROR: too many APIDs!"); // no need to set ok to 'false'
704  p = NULL;
705  }
706  apids[NumApids] = 0;
707  atypes[NumApids] = 0;
708  if (dpidbuf) {
709  char *p = dpidbuf;
710  char *q;
711  int NumDpids = 0;
712  char *strtok_next;
713  while ((q = strtok_r(p, ",", &strtok_next)) != NULL) {
714  if (NumDpids < MAXDPIDS) {
715  dtypes[NumDpids] = SI::AC3DescriptorTag; // backwards compatibility
716  char *l = strchr(q, '=');
717  if (l) {
718  *l++ = 0;
719  char *t = strchr(l, '@');
720  if (t) {
721  *t++ = 0;
722  dtypes[NumDpids] = strtol(t, NULL, 10);
723  }
724  strn0cpy(dlangs[NumDpids], l, MAXLANGCODE2);
725  }
726  else
727  *dlangs[NumDpids] = 0;
728  if ((dpids[NumDpids] = strtol(q, NULL, 10)) != 0)
729  NumDpids++;
730  }
731  else
732  esyslog("ERROR: too many DPIDs!"); // no need to set ok to 'false'
733  p = NULL;
734  }
735  dpids[NumDpids] = 0;
736  dtypes[NumDpids] = 0;
737  }
738  int NumSpids = 0;
739  if ((p = strchr(tpidbuf, ';')) != NULL) {
740  *p++ = 0;
741  char *q;
742  char *strtok_next;
743  while ((q = strtok_r(p, ",", &strtok_next)) != NULL) {
744  if (NumSpids < MAXSPIDS) {
745  char *l = strchr(q, '=');
746  if (l) {
747  *l++ = 0;
748  strn0cpy(slangs[NumSpids], l, MAXLANGCODE2);
749  }
750  else
751  *slangs[NumSpids] = 0;
752  spids[NumSpids++] = strtol(q, NULL, 10);
753  }
754  else
755  esyslog("ERROR: too many SPIDs!"); // no need to set ok to 'false'
756  p = NULL;
757  }
758  spids[NumSpids] = 0;
759  }
760  if (sscanf(tpidbuf, "%d", &tpid) != 1)
761  return false;
762  if (caidbuf) {
763  char *p = caidbuf;
764  char *q;
765  int NumCaIds = 0;
766  char *strtok_next;
767  while ((q = strtok_r(p, ",", &strtok_next)) != NULL) {
768  if (NumCaIds < MAXCAIDS) {
769  caids[NumCaIds++] = strtol(q, NULL, 16) & 0xFFFF;
770  if (NumCaIds == 1 && caids[0] <= CA_USER_MAX)
771  break;
772  }
773  else
774  esyslog("ERROR: too many CA ids!"); // no need to set ok to 'false'
775  p = NULL;
776  }
777  caids[NumCaIds] = 0;
778  }
779  }
780  strreplace(namebuf, '|', ':');
781 
782  char *p = strchr(namebuf, ';');
783  if (p) {
784  *p++ = 0;
786  }
787  p = strrchr(namebuf, ','); // long name might contain a ',', so search for the rightmost one
788  if (p) {
789  *p++ = 0;
791  }
792  name = strcpyrealloc(name, namebuf);
793 
794  free(parambuf);
795  free(sourcebuf);
796  free(vpidbuf);
797  free(apidbuf);
798  free(tpidbuf);
799  free(caidbuf);
800  free(namebuf);
801  nameSource = NULL;
802  nameSourceMode = 0;
803  shortNameSource = NULL;
804  if (!GetChannelID().Valid()) {
805  esyslog("ERROR: channel data results in invalid ID!");
806  return false;
807  }
808  }
809  else
810  return false;
811  }
812  return ok;
813 }
814 
815 bool cChannel::Save(FILE *f)
816 {
817  return fprintf(f, "%s\n", *ToText()) > 0;
818 }
819 
820 // --- cChannelSorter --------------------------------------------------------
821 
822 class cChannelSorter : public cListObject {
823 public:
827  channel = Channel;
829  }
830  virtual int Compare(const cListObject &ListObject) const {
831  cChannelSorter *cs = (cChannelSorter *)&ListObject;
832  return memcmp(&channelID, &cs->channelID, sizeof(channelID));
833  }
834  };
835 
836 // --- cChannels -------------------------------------------------------------
837 
839 int cChannels::maxNumber = 0;
842 
844 :cConfig<cChannel>("2 Channels")
845 {
846  modifiedByUser = 0;
847 }
848 
849 const cChannels *cChannels::GetChannelsRead(cStateKey &StateKey, int TimeoutMs)
850 {
851  return channels.Lock(StateKey, false, TimeoutMs) ? &channels : NULL;
852 }
853 
855 {
856  return channels.Lock(StateKey, true, TimeoutMs) ? &channels : NULL;
857 }
858 
860 {
861  cList<cChannelSorter> ChannelSorter;
862  for (cChannel *Channel = First(); Channel; Channel = Next(Channel)) {
863  if (!Channel->GroupSep())
864  ChannelSorter.Add(new cChannelSorter(Channel));
865  }
866  ChannelSorter.Sort();
867  cChannelSorter *cs = ChannelSorter.First();
868  while (cs) {
869  cChannelSorter *Next = ChannelSorter.Next(cs);
870  if (Next && cs->channelID == Next->channelID) {
871  dsyslog("deleting duplicate channel %s", *Next->channel->ToText());
872  Del(Next->channel);
873  }
874  cs = Next;
875  }
876 }
877 
878 bool cChannels::Load(const char *FileName, bool AllowComments, bool MustExist)
879 {
881  if (channels.cConfig<cChannel>::Load(FileName, AllowComments, MustExist)) {
883  channels.ReNumber();
884  return true;
885  }
886  return false;
887 }
888 
890 {
891  channelsHashSid.Add(Channel, Channel->Sid());
892 }
893 
895 {
896  channelsHashSid.Del(Channel, Channel->Sid());
897 }
898 
899 int cChannels::GetNextGroup(int Idx) const
900 {
901  const cChannel *Channel = Get(++Idx);
902  while (Channel && !(Channel->GroupSep() && *Channel->Name()))
903  Channel = Get(++Idx);
904  return Channel ? Idx : -1;
905 }
906 
907 int cChannels::GetPrevGroup(int Idx) const
908 {
909  const cChannel *Channel = Get(--Idx);
910  while (Channel && !(Channel->GroupSep() && *Channel->Name()))
911  Channel = Get(--Idx);
912  return Channel ? Idx : -1;
913 }
914 
915 int cChannels::GetNextNormal(int Idx) const
916 {
917  const cChannel *Channel = Get(++Idx);
918  while (Channel && Channel->GroupSep())
919  Channel = Get(++Idx);
920  return Channel ? Idx : -1;
921 }
922 
923 int cChannels::GetPrevNormal(int Idx) const
924 {
925  const cChannel *Channel = Get(--Idx);
926  while (Channel && Channel->GroupSep())
927  Channel = Get(--Idx);
928  return Channel ? Idx : -1;
929 }
930 
932 {
934  maxNumber = 0;
935  int Number = 1;
936  for (cChannel *Channel = First(); Channel; Channel = Next(Channel)) {
937  if (Channel->GroupSep()) {
938  if (Channel->Number() > Number)
939  Number = Channel->Number();
940  }
941  else {
942  HashChannel(Channel);
943  maxNumber = Number;
944  Channel->SetNumber(Number++);
945  }
946  }
947 }
948 
949 void cChannels::Del(cChannel *Channel)
950 {
951  UnhashChannel(Channel);
952  for (cChannel *ch = First(); ch; ch = Next(ch))
953  ch->DelLinkChannel(Channel);
954  cList<cChannel>::Del(Channel);
955 }
956 
957 const cChannel *cChannels::GetByNumber(int Number, int SkipGap) const
958 {
959  const cChannel *Previous = NULL;
960  for (const cChannel *Channel = First(); Channel; Channel = Next(Channel)) {
961  if (!Channel->GroupSep()) {
962  if (Channel->Number() == Number)
963  return Channel;
964  else if (SkipGap && Channel->Number() > Number)
965  return SkipGap > 0 ? Channel : Previous;
966  Previous = Channel;
967  }
968  }
969  return NULL;
970 }
971 
972 const cChannel *cChannels::GetByServiceID(int Source, int Transponder, unsigned short ServiceID) const
973 {
974  cList<cHashObject> *list = channelsHashSid.GetList(ServiceID);
975  if (list) {
976  for (cHashObject *hobj = list->First(); hobj; hobj = list->Next(hobj)) {
977  cChannel *Channel = (cChannel *)hobj->Object();
978  if (Channel->Sid() == ServiceID && Channel->Source() == Source && ISTRANSPONDER(Channel->Transponder(), Transponder))
979  return Channel;
980  }
981  }
982  return NULL;
983 }
984 
985 const cChannel *cChannels::GetByChannelID(tChannelID ChannelID, bool TryWithoutRid, bool TryWithoutPolarization) const
986 {
987  int sid = ChannelID.Sid();
989  if (list) {
990  for (cHashObject *hobj = list->First(); hobj; hobj = list->Next(hobj)) {
991  cChannel *Channel = (cChannel *)hobj->Object();
992  if (Channel->Sid() == sid && Channel->GetChannelID() == ChannelID)
993  return Channel;
994  }
995  if (TryWithoutRid) {
996  ChannelID.ClrRid();
997  for (cHashObject *hobj = list->First(); hobj; hobj = list->Next(hobj)) {
998  cChannel *Channel = (cChannel *)hobj->Object();
999  if (Channel->Sid() == sid && Channel->GetChannelID().ClrRid() == ChannelID)
1000  return Channel;
1001  }
1002  }
1003  if (TryWithoutPolarization) {
1004  ChannelID.ClrPolarization();
1005  for (cHashObject *hobj = list->First(); hobj; hobj = list->Next(hobj)) {
1006  cChannel *Channel = (cChannel *)hobj->Object();
1007  if (Channel->Sid() == sid && Channel->GetChannelID().ClrPolarization() == ChannelID)
1008  return Channel;
1009  }
1010  }
1011  }
1012  return NULL;
1013 }
1014 
1016 {
1017  int source = ChannelID.Source();
1018  int nid = ChannelID.Nid();
1019  int tid = ChannelID.Tid();
1020  for (const cChannel *Channel = First(); Channel; Channel = Next(Channel)) {
1021  if (Channel->Tid() == tid && Channel->Nid() == nid && Channel->Source() == source)
1022  return Channel;
1023  }
1024  return NULL;
1025 }
1026 
1027 bool cChannels::HasUniqueChannelID(const cChannel *NewChannel, const cChannel *OldChannel) const
1028 {
1029  tChannelID NewChannelID = NewChannel->GetChannelID();
1030  for (const cChannel *Channel = First(); Channel; Channel = Next(Channel)) {
1031  if (!Channel->GroupSep() && Channel != OldChannel && Channel->GetChannelID() == NewChannelID)
1032  return false;
1033  }
1034  return true;
1035 }
1036 
1037 bool cChannels::SwitchTo(int Number) const
1038 {
1039  const cChannel *Channel = GetByNumber(Number);
1040  return Channel && cDevice::PrimaryDevice()->SwitchChannel(Channel, true);
1041 }
1042 
1044 {
1045  if (!maxChannelNameLength) {
1047  for (const cChannel *Channel = Channels->First(); Channel; Channel = Channels->Next(Channel)) {
1048  if (!Channel->GroupSep())
1050  }
1051  }
1052  return maxChannelNameLength;
1053 }
1054 
1056 {
1059  for (const cChannel *Channel = Channels->First(); Channel; Channel = Channels->Next(Channel)) {
1060  if (!Channel->GroupSep())
1061  maxShortChannelNameLength = max(Utf8StrLen(Channel->ShortName(true)), maxShortChannelNameLength);
1062  }
1063  }
1065 }
1066 
1068 {
1069  modifiedByUser++;
1071 }
1072 
1073 bool cChannels::ModifiedByUser(int &State) const
1074 {
1075  int Result = State != modifiedByUser;
1076  State = modifiedByUser;
1077  return Result;
1078 }
1079 
1080 cChannel *cChannels::NewChannel(const cChannel *Transponder, const char *Name, const char *ShortName, const char *Provider, int Nid, int Tid, int Sid, int Rid)
1081 {
1082  if (Transponder) {
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);
1084  cChannel *NewChannel = new cChannel;
1085  NewChannel->CopyTransponderData(Transponder);
1086  NewChannel->SetId(this, Nid, Tid, Sid, Rid);
1087  NewChannel->SetName(Name, ShortName, Provider);
1088  NewChannel->SetSeen();
1089  Add(NewChannel);
1090  ReNumber();
1091  return NewChannel;
1092  }
1093  return NULL;
1094 }
1095 
1096 #define CHANNELMARKOBSOLETE "OBSOLETE"
1097 #define CHANNELTIMEOBSOLETE 3600 // seconds to wait before declaring a channel obsolete (in case it has actually been seen before)
1098 
1099 bool cChannels::MarkObsoleteChannels(int Source, int Nid, int Tid)
1100 {
1101  bool ChannelsModified = false;
1102  for (cChannel *Channel = First(); Channel; Channel = Next(Channel)) {
1103  if (time(NULL) - Channel->Seen() > CHANNELTIMEOBSOLETE && Channel->Source() == Source && Channel->Nid() == Nid && Channel->Tid() == Tid && Channel->Rid() == 0) {
1104  int OldShowChannelNamesWithSource = Setup.ShowChannelNamesWithSource;
1106  if (!endswith(Channel->Name(), CHANNELMARKOBSOLETE))
1107  ChannelsModified |= Channel->SetName(cString::sprintf("%s %s", Channel->Name(), CHANNELMARKOBSOLETE), Channel->ShortName(), cString::sprintf("%s %s", CHANNELMARKOBSOLETE, Channel->Provider()));
1108  Setup.ShowChannelNamesWithSource = OldShowChannelNamesWithSource;
1109  }
1110  }
1111  return ChannelsModified;
1112 }
1113 
1114 cString ChannelString(const cChannel *Channel, int Number)
1115 {
1116  char buffer[256];
1117  if (Channel) {
1118  if (Channel->GroupSep())
1119  snprintf(buffer, sizeof(buffer), "%s", Channel->Name());
1120  else
1121  snprintf(buffer, sizeof(buffer), "%d%s %s", Channel->Number(), Number ? "-" : "", Channel->Name());
1122  }
1123  else if (Number)
1124  snprintf(buffer, sizeof(buffer), "%d-", Number);
1125  else
1126  snprintf(buffer, sizeof(buffer), "%s", tr("*** Invalid Channel ***"));
1127  return buffer;
1128 }
const cChannel * GetByChannelID(tChannelID ChannelID, bool TryWithoutRid=false, bool TryWithoutPolarization=false) const
Definition: channels.c:985
static cString ToString(int Code)
Definition: sources.c:55
int sid
Definition: channels.h:52
unsigned char uchar
Definition: tools.h:31
bool SetName(const char *Name, const char *ShortName, const char *Provider)
Definition: channels.c:257
static const cChannels * GetChannelsRead(cStateKey &StateKey, int TimeoutMs=0)
Gets the list of channels for read access.
Definition: channels.c:849
#define CHANNELTIMEOBSOLETE
Definition: channels.c:1097
int tid
Definition: channels.h:118
const cChannel * Get(int Index) const
Returns the list element at the given Index, or NULL if no such element exists.
Definition: tools.h:603
cString TransponderDataToString(void) const
Definition: channels.c:539
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)
Definition: channels.c:340
static char ToChar(int Code)
Definition: sources.h:51
bool isempty(const char *s)
Definition: tools.c:331
static tChannelID FromString(const char *s)
Definition: channels.c:23
#define dsyslog(a...)
Definition: tools.h:37
int Sid(void) const
Definition: channels.h:64
time_t seen
Definition: channels.h:130
int Utf8StrLen(const char *s)
Returns the number of UTF-8 symbols formed by the given string of character bytes.
Definition: tools.c:869
const char * Provider(void) const
Definition: channels.h:145
bool SetPortalName(const char *PortalName)
Definition: channels.c:285
static int MaxShortChannelNameLength(void)
Definition: channels.c:1055
int Ppid(void) const
Definition: channels.h:153
int Srate(void) const
Definition: channels.h:151
void CopyTransponderData(const cChannel *Channel)
Definition: channels.c:166
void Clear(void)
Definition: tools.c:2372
uint16_t compositionPageIds[MAXSPIDS]
Definition: channels.h:113
int Nid(void) const
Definition: channels.h:62
#define CHANNELMOD_PIDS
Definition: channels.h:23
void Add(cListObject *Object, cListObject *After=NULL)
Definition: tools.c:2152
static cString ToText(const cChannel *Channel)
Definition: channels.c:546
uint16_t ancillaryPageIds[MAXSPIDS]
Definition: channels.h:114
#define CHANNELMOD_AUX
Definition: channels.h:25
bool Lock(cStateKey &StateKey, bool Write=false, int TimeoutMs=0) const
Tries to get a lock on this list and returns true if successful.
Definition: tools.c:2143
int modification
Definition: channels.h:129
tChannelID(void)
Definition: channels.h:55
bool endswith(const char *s, const char *p)
Definition: tools.c:320
static cString sprintf(const char *fmt,...) __attribute__((format(printf
Definition: tools.c:1127
#define CHANNELMOD_TRANSP
Definition: channels.h:27
int tid
Definition: channels.h:51
void Del(cListObject *Object, unsigned int Id)
Definition: tools.c:2359
int Source(void) const
Definition: channels.h:150
static bool IsTerr(int Code)
Definition: sources.h:58
int ppid
Definition: channels.h:102
static int maxChannelNameLength
Definition: channels.h:212
#define CHANNELMOD_NONE
Definition: channels.h:20
tChannelID channelID
Definition: channels.c:825
#define esyslog(a...)
Definition: tools.h:35
uchar subtitlingTypes[MAXSPIDS]
Definition: channels.h:112
const cLinkChannels * LinkChannels(void) const
Definition: channels.h:181
char * strn0cpy(char *dest, const char *src, size_t n)
Definition: tools.c:131
bool SetId(cChannels *Channels, int Nid, int Tid, int Sid, int Rid=0)
Definition: channels.c:226
cChannel & operator=(const cChannel &Channel)
Definition: channels.c:93
T max(T a, T b)
Definition: tools.h:60
Definition: tools.h:594
#define CHANNELMOD_CA
Definition: channels.h:26
tChannelID & ClrPolarization(void)
Definition: channels.c:47
int Rid(void) const
Definition: channels.h:175
int Nid(void) const
Definition: channels.h:172
cList< cHashObject > * GetList(unsigned int Id) const
Definition: tools.c:2399
char * name
Definition: channels.h:93
void ReNumber(void)
Recalculate 'number' based on channel type.
Definition: channels.c:931
int spids[MAXSPIDS+1]
Definition: channels.h:110
const int * Spids(void) const
Definition: channels.h:157
static int MaxChannelNameLength(void)
Definition: channels.c:1043
cString nameSource
Definition: channels.h:125
int nid
actually the "original" network id
Definition: channels.h:50
cString ChannelString(const cChannel *Channel, int Number)
Definition: channels.c:1114
bool groupSep
Definition: channels.h:123
int nid
Definition: channels.h:117
int Vtype(void) const
Definition: channels.h:154
#define LOCK_CHANNELS_WRITE
Definition: channels.h:266
const cSchedule * schedule
Definition: channels.h:131
char * provider
Definition: channels.h:95
const char * FileName(void)
Definition: config.h:119
const char * PortalName(void) const
Definition: channels.h:146
static int maxShortChannelNameLength
Definition: channels.h:213
const int * Apids(void) const
Definition: channels.h:155
bool Save(FILE *f)
Definition: channels.c:815
int tpid
Definition: channels.h:115
static bool Load(const char *FileName, bool AllowComments=false, bool MustExist=false)
Definition: channels.c:878
bool SetTransponderData(int Source, int Frequency, int Srate, const char *Parameters, bool Quiet=false)
Definition: channels.c:176
#define CHANNELMOD_LANGS
Definition: channels.h:28
cChannel * Channel(void)
Definition: channels.h:78
static cChannels * GetChannelsWrite(cStateKey &StateKey, int TimeoutMs=0)
Gets the list of channels for write access.
Definition: channels.c:854
char * shortName
Definition: channels.h:94
int Transponder(void) const
Returns the transponder frequency in MHz, plus the polarization in case of sat.
Definition: channels.c:146
int nameSourceMode
Definition: channels.h:126
static cChannels channels
Definition: channels.h:210
#define STRDIFF
Definition: channels.c:298
void Del(cChannel *Channel)
Delete the given Channel from the list.
Definition: channels.c:949
cChannel * NewChannel(const cChannel *Transponder, const char *Name, const char *ShortName, const char *Provider, int Nid, int Tid, int Sid, int Rid=0)
Definition: channels.c:1080
const int * Dpids(void) const
Definition: channels.h:156
#define ISTRANSPONDER(f1, f2)
Definition: channels.h:18
bool HasUniqueChannelID(const cChannel *NewChannel, const cChannel *OldChannel=NULL) const
Definition: channels.c:1027
char alangs[MAXAPIDS][MAXLANGCODE2]
Definition: channels.h:106
cChannel(void)
Definition: channels.c:56
bool Parse(const char *s)
Definition: channels.c:608
int Tpid(void) const
Definition: channels.h:169
cString ToString(void) const
Definition: channels.c:40
#define CHANNELMOD_NAME
Definition: channels.h:22
int Sid(void) const
Definition: channels.h:174
bool SwitchChannel(const cChannel *Channel, bool LiveView)
Switches the device to the given Channel, initiating transfer mode if necessary.
Definition: device.c:785
#define LOCK_CHANNELS_READ
Definition: channels.h:265
#define VALDIFF
Definition: channels.c:299
int source
Definition: channels.h:49
bool GroupSep(void) const
Definition: channels.h:179
const cChannel * RefChannel(void) const
Definition: channels.h:182
void Sort(void)
Definition: tools.c:2276
#define CA_USER_MAX
Definition: channels.h:43
cChannels(void)
Definition: channels.c:843
int __EndData__
Definition: channels.h:124
char dlangs[MAXDPIDS][MAXLANGCODE2]
Definition: channels.h:109
int atypes[MAXAPIDS+1]
Definition: channels.h:105
virtual int Compare(const cListObject &ListObject) const
Must return 0 if this object is equal to ListObject, a positive value if it is "greater",...
Definition: channels.c:830
int rid
Definition: channels.h:120
cSetup Setup
Definition: config.c:372
int frequency
Definition: channels.h:98
void DelLinkChannel(cChannel *LinkChannel)
Definition: channels.c:437
int __BeginData__
Definition: channels.h:97
int Tid(void) const
Definition: channels.h:173
static int IntArrayToString(char *s, const int *a, int Base=10, const char n[][MAXLANGCODE2]=NULL, const int *t=NULL)
Definition: channels.c:317
bool SetLcn(int Lcn)
Definition: channels.c:246
const cChannel * GetByNumber(int Number, int SkipGap=0) const
Definition: channels.c:957
bool SetSubtitlingDescriptors(uchar *SubtitlingTypes, uint16_t *CompositionPageIds, uint16_t *AncillaryPageIds)
Definition: channels.c:408
int vpid
Definition: channels.h:101
#define MAXLANGCODE2
Definition: channels.h:37
const T * First(void) const
Returns the first element in this list, or NULL if the list is empty.
Definition: tools.h:606
const char * Name(void) const
Definition: channels.c:107
int GetNextNormal(int Idx) const
Get next normal channel (not group)
Definition: channels.c:915
int Tid(void) const
Definition: channels.h:63
int sid
Definition: channels.h:119
int Vpid(void) const
Definition: channels.h:152
cString shortNameSource
Definition: channels.h:127
bool ModifiedByUser(int &State) const
Returns true if the channels have been modified by the user since the last call to this function with...
Definition: channels.c:1073
#define MAXDPIDS
Definition: channels.h:32
void Del(cListObject *Object, bool DeleteObject=true)
Definition: tools.c:2184
void SetRefChannel(cChannel *RefChannel)
Definition: channels.c:534
int Modification(int Mask=CHANNELMOD_ALL) const
Definition: channels.c:159
int ShowChannelNamesWithSource
Definition: config.h:365
int dpids[MAXDPIDS+1]
Definition: channels.h:107
static cDevice * PrimaryDevice(void)
Returns the primary device.
Definition: device.h:146
void DeleteDuplicateChannels(void)
Definition: channels.c:859
tChannelID GetChannelID(void) const
Definition: channels.h:188
int Frequency(void) const
Returns the actual frequency, as given in 'channels.conf'.
Definition: channels.h:147
static int FromString(const char *s)
Definition: sources.c:68
int Source(void) const
Definition: channels.h:61
#define tr(s)
Definition: i18n.h:85
~cChannel()
Definition: channels.c:84
static int maxNumber
Definition: channels.h:211
int source
Definition: channels.h:99
cChannel * channel
Definition: channels.c:824
cListObject * Next(void) const
Definition: tools.h:510
char * skipspace(const char *s)
Definition: tools.h:209
cString parameters
Definition: channels.h:128
bool SetLinkChannels(cLinkChannels *LinkChannels)
Definition: channels.c:486
char * strcpyrealloc(char *dest, const char *src)
Definition: tools.c:114
static int IntArraysDiffer(const int *a, const int *b, const char na[][MAXLANGCODE2]=NULL, const char nb[][MAXLANGCODE2]=NULL)
Definition: channels.c:301
int rid
Definition: channels.h:53
char slangs[MAXSPIDS][MAXLANGCODE2]
Definition: channels.h:111
bool SetSource(int Source)
Definition: channels.c:213
#define MAXSPIDS
Definition: channels.h:33
int vtype
Definition: channels.h:103
int caids[MAXCAIDS+1]
Definition: channels.h:116
void Add(cListObject *Object, unsigned int Id)
Definition: tools.c:2351
cHash< cChannel > channelsHashSid
Definition: channels.h:215
static const tChannelID InvalidID
Definition: channels.h:68
const cChannel * GetByServiceID(int Source, int Transponder, unsigned short ServiceID) const
Definition: channels.c:972
void UnhashChannel(cChannel *Channel)
Definition: channels.c:894
cChannel * refChannel
Definition: channels.h:133
cString ToText(void) const
Definition: channels.c:603
int GetNextGroup(int Idx) const
Get next channel group.
Definition: channels.c:899
cChannelSorter(cChannel *Channel)
Definition: channels.c:826
bool SwitchTo(int Number) const
Definition: channels.c:1037
int number
Definition: channels.h:122
bool SetCaIds(const int *CaIds)
Definition: channels.c:453
const char * ShortName(bool OrName=false) const
Definition: channels.c:121
int Lcn(void) const
Definition: channels.h:176
#define MAXCAIDS
Definition: channels.h:34
const char * Parameters(void) const
Definition: channels.h:180
bool MarkObsoleteChannels(int Source, int Nid, int Tid)
Definition: channels.c:1099
tChannelID & ClrRid(void)
Definition: channels.h:59
cLinkChannels * linkChannels
Definition: channels.h:132
int GetPrevNormal(int Idx) const
Get previous normal channel (not group)
Definition: channels.c:923
#define CHANNELMARKOBSOLETE
Definition: channels.c:1096
char * portalName
Definition: channels.h:96
void SetSeen(void)
Definition: channels.c:432
#define CHANNELMOD_ID
Definition: channels.h:24
const cChannel * GetByTransponderID(tChannelID ChannelID) const
Definition: channels.c:1015
int Count(void) const
Definition: tools.h:590
char * strreplace(char *s, char c1, char c2)
Definition: tools.c:139
void SetModifiedByUser(void)
Definition: channels.c:1067
int lcn
Definition: channels.h:121
int srate
Definition: channels.h:100
void HashChannel(cChannel *Channel)
Definition: channels.c:889
Definition: tools.h:176
int GetPrevGroup(int Idx) const
Get previous channel group.
Definition: channels.c:907
int Number(void) const
Definition: channels.h:177
bool IsSat(void) const
Definition: channels.h:185
int apids[MAXAPIDS+1]
Definition: channels.h:104
int modifiedByUser
Definition: channels.h:214
bool SetCaDescriptors(int Level)
Definition: channels.c:475
#define MAXAPIDS
Definition: channels.h:31
const T * Next(const T *Object) const
< Returns the element immediately before Object in this list, or NULL if Object is the first element ...
Definition: tools.h:613
int dtypes[MAXAPIDS+1]
Definition: channels.h:108