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