vdr  2.2.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 3.8 2015/02/01 13:47:05 kls Exp $
8  */
9 
10 #include "channels.h"
11 #include <ctype.h>
12 #include "device.h"
13 #include "epg.h"
14 #include "libsi/si.h"
15 #include "timers.h"
16 #include "dvbdevice.h"
17 
18 // IMPORTANT NOTE: in the 'sscanf()' calls there is a blank after the '%d'
19 // format characters in order to allow any number of blanks after a numeric
20 // value!
21 
22 // --- tChannelID ------------------------------------------------------------
23 
25 
27 {
28  char *sourcebuf = NULL;
29  int nid;
30  int tid;
31  int sid;
32  int rid = 0;
33  int fields = sscanf(s, "%m[^-]-%d-%d-%d-%d", &sourcebuf, &nid, &tid, &sid, &rid);
34  if (fields == 4 || fields == 5) {
35  int source = cSource::FromString(sourcebuf);
36  free(sourcebuf);
37  if (source >= 0)
38  return tChannelID(source, nid, tid, sid, rid);
39  }
40  return tChannelID::InvalidID;
41 }
42 
44 {
45  char buffer[256];
46  snprintf(buffer, sizeof(buffer), rid ? "%s-%d-%d-%d-%d" : "%s-%d-%d-%d", *cSource::ToString(source), nid, tid, sid, rid);
47  return buffer;
48 }
49 
51 {
52  while (tid > 100000)
53  tid -= 100000;
54  return *this;
55 }
56 
57 // --- cChannel --------------------------------------------------------------
58 
60 {
61  name = strdup("");
62  shortName = strdup("");
63  provider = strdup("");
64  portalName = strdup("");
65  memset(&__BeginData__, 0, (char *)&__EndData__ - (char *)&__BeginData__);
66  parameters = "";
67  modification = CHANNELMOD_NONE;
68  seen = 0;
69  schedule = NULL;
70  linkChannels = NULL;
71  refChannel = NULL;
72 }
73 
75 {
76  name = NULL;
77  shortName = NULL;
78  provider = NULL;
79  portalName = NULL;
80  schedule = NULL;
81  linkChannels = NULL;
82  refChannel = NULL;
83  *this = Channel;
84 }
85 
87 {
88  delete linkChannels;
89  linkChannels = NULL; // more than one channel can link to this one, so we need the following loop
90  for (cChannel *Channel = Channels.First(); Channel; Channel = Channels.Next(Channel)) {
91  if (Channel->linkChannels) {
92  for (cLinkChannel *lc = Channel->linkChannels->First(); lc; lc = Channel->linkChannels->Next(lc)) {
93  if (lc->Channel() == this) {
94  Channel->linkChannels->Del(lc);
95  break;
96  }
97  }
98  if (Channel->linkChannels->Count() == 0) {
99  delete Channel->linkChannels;
100  Channel->linkChannels = NULL;
101  }
102  }
103  }
104  free(name);
105  free(shortName);
106  free(provider);
107  free(portalName);
108 }
109 
111 {
112  name = strcpyrealloc(name, Channel.name);
113  shortName = strcpyrealloc(shortName, Channel.shortName);
114  provider = strcpyrealloc(provider, Channel.provider);
115  portalName = strcpyrealloc(portalName, Channel.portalName);
116  memcpy(&__BeginData__, &Channel.__BeginData__, (char *)&Channel.__EndData__ - (char *)&Channel.__BeginData__);
117  nameSource = NULL; // these will be recalculated automatically
118  shortNameSource = NULL;
119  parameters = Channel.parameters;
120  return *this;
121 }
122 
123 const char *cChannel::Name(void) const
124 {
125  if (Setup.ShowChannelNamesWithSource && !groupSep) {
126  if (isempty(nameSource))
127  nameSource = cString::sprintf("%s (%c)", name, cSource::ToChar(source));
128  return nameSource;
129  }
130  return name;
131 }
132 
133 const char *cChannel::ShortName(bool OrName) const
134 {
135  if (OrName && isempty(shortName))
136  return Name();
137  if (Setup.ShowChannelNamesWithSource && !groupSep) {
138  if (isempty(shortNameSource))
139  shortNameSource = cString::sprintf("%s (%c)", shortName, cSource::ToChar(source));
140  return shortNameSource;
141  }
142  return shortName;
143 }
144 
145 int cChannel::Transponder(int Frequency, char Polarization)
146 {
147  // some satellites have transponders at the same frequency, just with different polarization:
148  switch (toupper(Polarization)) {
149  case 'H': Frequency += 100000; break;
150  case 'V': Frequency += 200000; break;
151  case 'L': Frequency += 300000; break;
152  case 'R': Frequency += 400000; break;
153  default: esyslog("ERROR: invalid value for Polarization '%c'", Polarization);
154  }
155  return Frequency;
156 }
157 
158 int cChannel::Transponder(void) const
159 {
160  int tf = frequency;
161  while (tf > 20000)
162  tf /= 1000;
163  if (IsSat()) {
164  const char *p = strpbrk(parameters, "HVLRhvlr"); // lowercase for backwards compatibility
165  if (p)
166  tf = Transponder(tf, *p);
167  }
168  return tf;
169 }
170 
171 bool cChannel::HasTimer(void) const
172 {
173  for (cTimer *Timer = Timers.First(); Timer; Timer = Timers.Next(Timer)) {
174  if (Timer->Channel() == this)
175  return true;
176  }
177  return false;
178 }
179 
181 {
182  int Result = modification & Mask;
183  modification = CHANNELMOD_NONE;
184  return Result;
185 }
186 
188 {
189  if (Channel) {
190  frequency = Channel->frequency;
191  source = Channel->source;
192  srate = Channel->srate;
193  parameters = Channel->parameters;
194  }
195 }
196 
197 bool cChannel::SetTransponderData(int Source, int Frequency, int Srate, const char *Parameters, bool Quiet)
198 {
199  if (strchr(Parameters, ':')) {
200  esyslog("ERROR: parameter string '%s' contains ':'", Parameters);
201  return false;
202  }
203  // Workarounds for broadcaster stupidity:
204  // Some providers broadcast the transponder frequency of their channels with two different
205  // values (like 12551 and 12552), so we need to allow for a little tolerance here
206  if (abs(frequency - Frequency) <= 1)
207  Frequency = frequency;
208  // Sometimes the transponder frequency is set to 0, which is just wrong
209  if (Frequency == 0)
210  return false;
211  // Sometimes the symbol rate is off by one
212  if (abs(srate - Srate) <= 1)
213  Srate = srate;
214 
215  if (source != Source || frequency != Frequency || srate != Srate || strcmp(parameters, Parameters)) {
216  cString OldTransponderData = TransponderDataToString();
217  source = Source;
218  frequency = Frequency;
219  srate = Srate;
220  parameters = Parameters;
221  schedule = NULL;
222  nameSource = NULL;
223  shortNameSource = NULL;
224  if (Number() && !Quiet) {
225  dsyslog("changing transponder data of channel %d (%s) from %s to %s", Number(), name, *OldTransponderData, *TransponderDataToString());
226  modification |= CHANNELMOD_TRANSP;
228  }
229  }
230  return true;
231 }
232 
233 void cChannel::SetId(int Nid, int Tid, int Sid, int Rid)
234 {
235  if (nid != Nid || tid != Tid || sid != Sid || rid != Rid) {
236  if (Number()) {
237  dsyslog("changing id of channel %d (%s) from %d-%d-%d-%d to %d-%d-%d-%d", Number(), name, nid, tid, sid, rid, Nid, Tid, Sid, Rid);
238  modification |= CHANNELMOD_ID;
240  Channels.UnhashChannel(this);
241  }
242  nid = Nid;
243  tid = Tid;
244  sid = Sid;
245  rid = Rid;
246  if (Number())
247  Channels.HashChannel(this);
248  schedule = NULL;
249  }
250 }
251 
252 void cChannel::SetLcn(int Lcn)
253 {
254  if (lcn != Lcn) {
255  if (Number())
256  dsyslog("changing lcn of channel %d (%s) from %d to %d\n", Number(), name, lcn, Lcn);
257  lcn = Lcn;
258  }
259 }
260 
261 void cChannel::SetName(const char *Name, const char *ShortName, const char *Provider)
262 {
263  if (!isempty(Name)) {
264  bool nn = strcmp(name, Name) != 0;
265  bool ns = strcmp(shortName, ShortName) != 0;
266  bool np = strcmp(provider, Provider) != 0;
267  if (nn || ns || np) {
268  if (Number()) {
269  dsyslog("changing name of channel %d from '%s,%s;%s' to '%s,%s;%s'", Number(), name, shortName, provider, Name, ShortName, Provider);
270  modification |= CHANNELMOD_NAME;
272  }
273  if (nn) {
274  name = strcpyrealloc(name, Name);
275  nameSource = NULL;
276  }
277  if (ns) {
278  shortName = strcpyrealloc(shortName, ShortName);
279  shortNameSource = NULL;
280  }
281  if (np)
282  provider = strcpyrealloc(provider, Provider);
283  }
284  }
285 }
286 
287 void cChannel::SetPortalName(const char *PortalName)
288 {
289  if (!isempty(PortalName) && strcmp(portalName, PortalName) != 0) {
290  if (Number()) {
291  dsyslog("changing portal name of channel %d (%s) from '%s' to '%s'", Number(), name, portalName, PortalName);
292  modification |= CHANNELMOD_NAME;
294  }
295  portalName = strcpyrealloc(portalName, PortalName);
296  }
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 void cChannel::SetPids(int Vpid, int Ppid, int Vtype, int *Apids, int *Atypes, char ALangs[][MAXLANGCODE2], int *Dpids, int *Dtypes, char DLangs[][MAXLANGCODE2], int *Spids, char SLangs[][MAXLANGCODE2], int Tpid)
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  if (Number())
406  }
407 }
408 
409 void cChannel::SetSubtitlingDescriptors(uchar *SubtitlingTypes, uint16_t *CompositionPageIds, uint16_t *AncillaryPageIds)
410 {
411  if (SubtitlingTypes) {
412  for (int i = 0; i < MAXSPIDS; i++)
413  subtitlingTypes[i] = SubtitlingTypes[i];
414  }
415  if (CompositionPageIds) {
416  for (int i = 0; i < MAXSPIDS; i++)
417  compositionPageIds[i] = CompositionPageIds[i];
418  }
419  if (AncillaryPageIds) {
420  for (int i = 0; i < MAXSPIDS; i++)
421  ancillaryPageIds[i] = AncillaryPageIds[i];
422  }
423 }
424 
426 {
427  int mod = CHANNELMOD_NONE;
428  if (totalTtxtSubtitlePages != (fixedTtxtSubtitlePages + numberOfPages))
429  mod |= CHANNELMOD_PIDS;
430  totalTtxtSubtitlePages = fixedTtxtSubtitlePages;
431  for (int i = 0; (i < numberOfPages) && (totalTtxtSubtitlePages < MAXTXTPAGES); i++) {
432  if (teletextSubtitlePages[totalTtxtSubtitlePages].ttxtMagazine != pages[i].ttxtMagazine ||
433  teletextSubtitlePages[totalTtxtSubtitlePages].ttxtPage != pages[i].ttxtPage ||
434  teletextSubtitlePages[totalTtxtSubtitlePages].ttxtType != pages[i].ttxtType ||
435  strcmp(teletextSubtitlePages[totalTtxtSubtitlePages].ttxtLanguage, pages[i].ttxtLanguage)) {
436  mod |= CHANNELMOD_PIDS;
437  teletextSubtitlePages[totalTtxtSubtitlePages] = pages[i];
438  }
439  totalTtxtSubtitlePages++;
440  }
441  modification |= mod;
443 }
444 
446 {
447  seen = time(NULL);
448 }
449 
450 void cChannel::SetCaIds(const int *CaIds)
451 {
452  if (caids[0] && caids[0] <= CA_USER_MAX)
453  return; // special values will not be overwritten
454  if (IntArraysDiffer(caids, CaIds)) {
455  char OldCaIdsBuf[MAXCAIDS * 5 + 10]; // 5: 4 digits plus delimiting ',', 10: paranoia
456  char NewCaIdsBuf[MAXCAIDS * 5 + 10];
457  IntArrayToString(OldCaIdsBuf, caids, 16);
458  IntArrayToString(NewCaIdsBuf, CaIds, 16);
459  if (Number())
460  dsyslog("changing caids of channel %d (%s) from %s to %s", Number(), name, OldCaIdsBuf, NewCaIdsBuf);
461  for (int i = 0; i <= MAXCAIDS; i++) { // <= to copy the terminating 0
462  caids[i] = CaIds[i];
463  if (!CaIds[i])
464  break;
465  }
466  modification |= CHANNELMOD_CA;
468  }
469 }
470 
472 {
473  if (Level > 0) {
474  modification |= CHANNELMOD_CA;
476  if (Number() && Level > 1)
477  dsyslog("changing ca descriptors of channel %d (%s)", Number(), name);
478  }
479 }
480 
482 {
483  if (!linkChannels && !LinkChannels)
484  return;
485  if (linkChannels && LinkChannels) {
486  cLinkChannel *lca = linkChannels->First();
487  cLinkChannel *lcb = LinkChannels->First();
488  while (lca && lcb) {
489  if (lca->Channel() != lcb->Channel()) {
490  lca = NULL;
491  break;
492  }
493  lca = linkChannels->Next(lca);
494  lcb = LinkChannels->Next(lcb);
495  }
496  if (!lca && !lcb) {
497  delete LinkChannels;
498  return; // linkage has not changed
499  }
500  }
501  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
502  char *q = buffer;
503  q += sprintf(q, "linking channel %d (%s) from", Number(), name);
504  if (linkChannels) {
505  for (cLinkChannel *lc = linkChannels->First(); lc; lc = linkChannels->Next(lc)) {
506  lc->Channel()->SetRefChannel(NULL);
507  q += sprintf(q, " %d", lc->Channel()->Number());
508  }
509  delete linkChannels;
510  }
511  else
512  q += sprintf(q, " none");
513  q += sprintf(q, " to");
514  linkChannels = LinkChannels;
515  if (linkChannels) {
516  for (cLinkChannel *lc = linkChannels->First(); lc; lc = linkChannels->Next(lc)) {
517  lc->Channel()->SetRefChannel(this);
518  q += sprintf(q, " %d", lc->Channel()->Number());
519  //dsyslog("link %4d -> %4d: %s", Number(), lc->Channel()->Number(), lc->Channel()->Name());
520  }
521  }
522  else
523  q += sprintf(q, " none");
524  if (Number())
525  dsyslog("%s", buffer);
526 }
527 
529 {
530  refChannel = RefChannel;
531 }
532 
534 {
535  if (cSource::IsTerr(source))
536  return cString::sprintf("%d:%s:%s", frequency, *parameters, *cSource::ToString(source));
537  return cString::sprintf("%d:%s:%s:%d", frequency, *parameters, *cSource::ToString(source), srate);
538 }
539 
541 {
542  char FullName[strlen(Channel->name) + 1 + strlen(Channel->shortName) + 1 + strlen(Channel->provider) + 1 + 10]; // +10: paranoia
543  char *q = FullName;
544  q += sprintf(q, "%s", Channel->name);
545  if (!Channel->groupSep) {
546  if (!isempty(Channel->shortName))
547  q += sprintf(q, ",%s", Channel->shortName);
548  else if (strchr(Channel->name, ','))
549  q += sprintf(q, ",");
550  if (!isempty(Channel->provider))
551  q += sprintf(q, ";%s", Channel->provider);
552  }
553  *q = 0;
554  strreplace(FullName, ':', '|');
555  cString buffer;
556  if (Channel->groupSep) {
557  if (Channel->number)
558  buffer = cString::sprintf(":@%d %s\n", Channel->number, FullName);
559  else
560  buffer = cString::sprintf(":%s\n", FullName);
561  }
562  else {
563  char vpidbuf[32];
564  char *q = vpidbuf;
565  q += snprintf(q, sizeof(vpidbuf), "%d", Channel->vpid);
566  if (Channel->ppid && Channel->ppid != Channel->vpid)
567  q += snprintf(q, sizeof(vpidbuf) - (q - vpidbuf), "+%d", Channel->ppid);
568  if (Channel->vpid && Channel->vtype)
569  q += snprintf(q, sizeof(vpidbuf) - (q - vpidbuf), "=%d", Channel->vtype);
570  *q = 0;
571  const int ABufferSize = (MAXAPIDS + MAXDPIDS) * (5 + 1 + MAXLANGCODE2 + 5) + 10; // 5 digits plus delimiting ',' or ';' plus optional '=cod+cod@type', +10: paranoia
572  char apidbuf[ABufferSize];
573  q = apidbuf;
574  q += IntArrayToString(q, Channel->apids, 10, Channel->alangs, Channel->atypes);
575  if (Channel->dpids[0]) {
576  *q++ = ';';
577  q += IntArrayToString(q, Channel->dpids, 10, Channel->dlangs, Channel->dtypes);
578  }
579  *q = 0;
580  const int TBufferSize = (MAXTXTPAGES * MAXSPIDS) * (5 + 1 + MAXLANGCODE2) + 10; // 5 digits plus delimiting ',' or ';' plus optional '=cod+cod', +10: paranoia and tpid
581  char tpidbuf[TBufferSize];
582  q = tpidbuf;
583  q += snprintf(q, sizeof(tpidbuf), "%d", Channel->tpid);
584  if (Channel->fixedTtxtSubtitlePages > 0) {
585  *q++ = '+';
586  for (int i = 0; i < Channel->fixedTtxtSubtitlePages; ++i) {
587  tTeletextSubtitlePage page = Channel->teletextSubtitlePages[i];
588  q += snprintf(q, sizeof(tpidbuf) - (q - tpidbuf), "%d=%s", page.PageNumber(), page.ttxtLanguage);
589  }
590  }
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\n", 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  }
623  name = strcpyrealloc(name, skipspace(s));
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  fixedTtxtSubtitlePages = 0;
762  if ((p = strchr(tpidbuf, '+')) != NULL) {
763  *p++ = 0;
764  char *q;
765  char *strtok_next;
766  while ((q = strtok_r(p, ",", &strtok_next)) != NULL) {
767  if (fixedTtxtSubtitlePages < MAXTXTPAGES) {
768  int page;
769  char *l = strchr(q, '=');
770  if (l)
771  *l++ = 0;
772  if (sscanf(q, "%d", &page) == 1) {
773  teletextSubtitlePages[fixedTtxtSubtitlePages] = tTeletextSubtitlePage(page);
774  if (l)
775  strn0cpy(teletextSubtitlePages[fixedTtxtSubtitlePages].ttxtLanguage, l, MAXLANGCODE2);
776  fixedTtxtSubtitlePages++;
777  }
778  else
779  esyslog("ERROR: invalid Teletext page!"); // no need to set ok to 'false'
780  }
781  else
782  esyslog("ERROR: too many Teletext pages!"); // no need to set ok to 'false'
783  p = NULL;
784  }
785  totalTtxtSubtitlePages = fixedTtxtSubtitlePages;
786  }
787  if (sscanf(tpidbuf, "%d", &tpid) != 1)
788  return false;
789  if (caidbuf) {
790  char *p = caidbuf;
791  char *q;
792  int NumCaIds = 0;
793  char *strtok_next;
794  while ((q = strtok_r(p, ",", &strtok_next)) != NULL) {
795  if (NumCaIds < MAXCAIDS) {
796  caids[NumCaIds++] = strtol(q, NULL, 16) & 0xFFFF;
797  if (NumCaIds == 1 && caids[0] <= CA_USER_MAX)
798  break;
799  }
800  else
801  esyslog("ERROR: too many CA ids!"); // no need to set ok to 'false'
802  p = NULL;
803  }
804  caids[NumCaIds] = 0;
805  }
806  }
807  strreplace(namebuf, '|', ':');
808 
809  char *p = strchr(namebuf, ';');
810  if (p) {
811  *p++ = 0;
812  provider = strcpyrealloc(provider, p);
813  }
814  p = strrchr(namebuf, ','); // long name might contain a ',', so search for the rightmost one
815  if (p) {
816  *p++ = 0;
817  shortName = strcpyrealloc(shortName, p);
818  }
819  name = strcpyrealloc(name, namebuf);
820 
821  free(parambuf);
822  free(sourcebuf);
823  free(vpidbuf);
824  free(apidbuf);
825  free(tpidbuf);
826  free(caidbuf);
827  free(namebuf);
828  nameSource = NULL;
829  shortNameSource = NULL;
830  if (!GetChannelID().Valid()) {
831  esyslog("ERROR: channel data results in invalid ID!");
832  return false;
833  }
834  }
835  else
836  return false;
837  }
838  return ok;
839 }
840 
841 bool cChannel::Save(FILE *f)
842 {
843  return fprintf(f, "%s", *ToText()) > 0;
844 }
845 
846 // --- cChannelSorter --------------------------------------------------------
847 
848 class cChannelSorter : public cListObject {
849 public:
853  channel = Channel;
854  channelID = channel->GetChannelID();
855  }
856  virtual int Compare(const cListObject &ListObject) const {
857  cChannelSorter *cs = (cChannelSorter *)&ListObject;
858  return memcmp(&channelID, &cs->channelID, sizeof(channelID));
859  }
860  };
861 
862 // --- cChannels -------------------------------------------------------------
863 
865 
867 {
868  maxNumber = 0;
869  maxChannelNameLength = 0;
870  maxShortChannelNameLength = 0;
871  modified = CHANNELSMOD_NONE;
872 }
873 
875 {
876  cList<cChannelSorter> ChannelSorter;
877  for (cChannel *channel = First(); channel; channel = Next(channel)) {
878  if (!channel->GroupSep())
879  ChannelSorter.Add(new cChannelSorter(channel));
880  }
881  ChannelSorter.Sort();
882  cChannelSorter *cs = ChannelSorter.First();
883  while (cs) {
884  cChannelSorter *next = ChannelSorter.Next(cs);
885  if (next && cs->channelID == next->channelID) {
886  dsyslog("deleting duplicate channel %s", *next->channel->ToText());
887  Del(next->channel);
888  }
889  cs = next;
890  }
891 }
892 
893 bool cChannels::Load(const char *FileName, bool AllowComments, bool MustExist)
894 {
895  if (cConfig<cChannel>::Load(FileName, AllowComments, MustExist)) {
896  DeleteDuplicateChannels();
897  ReNumber();
898  return true;
899  }
900  return false;
901 }
902 
904 {
905  channelsHashSid.Add(Channel, Channel->Sid());
906 }
907 
909 {
910  channelsHashSid.Del(Channel, Channel->Sid());
911 }
912 
914 {
915  cChannel *channel = Get(++Idx);
916  while (channel && !(channel->GroupSep() && *channel->Name()))
917  channel = Get(++Idx);
918  return channel ? Idx : -1;
919 }
920 
922 {
923  cChannel *channel = Get(--Idx);
924  while (channel && !(channel->GroupSep() && *channel->Name()))
925  channel = Get(--Idx);
926  return channel ? Idx : -1;
927 }
928 
930 {
931  cChannel *channel = Get(++Idx);
932  while (channel && channel->GroupSep())
933  channel = Get(++Idx);
934  return channel ? Idx : -1;
935 }
936 
938 {
939  cChannel *channel = Get(--Idx);
940  while (channel && channel->GroupSep())
941  channel = Get(--Idx);
942  return channel ? Idx : -1;
943 }
944 
946 {
947  channelsHashSid.Clear();
948  maxNumber = 0;
949  int Number = 1;
951  cVector<int> FoundLcn(Count());
952  int Overflow = LCN_OVERFLOW_OFFSET;
953  for (cChannel *channel = First(); channel; channel = Next(channel)) {
954  if (!channel->GroupSep()) {
955  cDvbTransponderParameters dtp(channel->Parameters());
956  HashChannel(channel);
957  Number = dtp.Lcn();
958  if (Number > 0) {
959  bool Clash = false;
960  for (int i = 0; i < FoundLcn.Size(); ++i) {
961  if (FoundLcn[i] == Number) {
962  Number = Overflow++;
963  Clash = true;
964  break;
965  }
966  }
967  if (!Clash)
968  FoundLcn.Append(Number);
969  if (Number > maxNumber)
970  maxNumber = Number;
971  channel->SetNumber(Number);
972  }
973  else {
974  maxNumber = Overflow;
975  channel->SetNumber(Overflow++);
976  }
977  }
978  }
979  }
980  else {
981  for (cChannel *channel = First(); channel; channel = Next(channel)) {
982  if (channel->GroupSep()) {
983  if (channel->Number() > Number)
984  Number = channel->Number();
985  }
986  else {
987  HashChannel(channel);
988  maxNumber = Number;
989  channel->SetNumber(Number++);
990  }
991  }
992  }
993 }
994 
995 cChannel *cChannels::GetByNumber(int Number, int SkipGap)
996 {
997  cChannel *previous = NULL;
998  for (cChannel *channel = First(); channel; channel = Next(channel)) {
999  if (!channel->GroupSep()) {
1000  if (channel->Number() == Number)
1001  return channel;
1002  else if (SkipGap && channel->Number() > Number)
1003  return SkipGap > 0 ? channel : previous;
1004  previous = channel;
1005  }
1006  }
1007  return NULL;
1008 }
1009 
1010 cChannel *cChannels::GetByServiceID(int Source, int Transponder, unsigned short ServiceID)
1011 {
1012  cList<cHashObject> *list = channelsHashSid.GetList(ServiceID);
1013  if (list) {
1014  for (cHashObject *hobj = list->First(); hobj; hobj = list->Next(hobj)) {
1015  cChannel *channel = (cChannel *)hobj->Object();
1016  if (channel->Sid() == ServiceID && channel->Source() == Source && ISTRANSPONDER(channel->Transponder(), Transponder))
1017  return channel;
1018  }
1019  }
1020  return NULL;
1021 }
1022 
1023 cChannel *cChannels::GetByChannelID(tChannelID ChannelID, bool TryWithoutRid, bool TryWithoutPolarization)
1024 {
1025  int sid = ChannelID.Sid();
1026  cList<cHashObject> *list = channelsHashSid.GetList(sid);
1027  if (list) {
1028  for (cHashObject *hobj = list->First(); hobj; hobj = list->Next(hobj)) {
1029  cChannel *channel = (cChannel *)hobj->Object();
1030  if (channel->Sid() == sid && channel->GetChannelID() == ChannelID)
1031  return channel;
1032  }
1033  if (TryWithoutRid) {
1034  ChannelID.ClrRid();
1035  for (cHashObject *hobj = list->First(); hobj; hobj = list->Next(hobj)) {
1036  cChannel *channel = (cChannel *)hobj->Object();
1037  if (channel->Sid() == sid && channel->GetChannelID().ClrRid() == ChannelID)
1038  return channel;
1039  }
1040  }
1041  if (TryWithoutPolarization) {
1042  ChannelID.ClrPolarization();
1043  for (cHashObject *hobj = list->First(); hobj; hobj = list->Next(hobj)) {
1044  cChannel *channel = (cChannel *)hobj->Object();
1045  if (channel->Sid() == sid && channel->GetChannelID().ClrPolarization() == ChannelID)
1046  return channel;
1047  }
1048  }
1049  }
1050  return NULL;
1051 }
1053 {
1054  int source = ChannelID.Source();
1055  int nid = ChannelID.Nid();
1056  int tid = ChannelID.Tid();
1057  for (cChannel *channel = First(); channel; channel = Next(channel)) {
1058  if (channel->Tid() == tid && channel->Nid() == nid && channel->Source() == source)
1059  return channel;
1060  }
1061  return NULL;
1062 }
1063 
1064 bool cChannels::HasUniqueChannelID(cChannel *NewChannel, cChannel *OldChannel)
1065 {
1066  tChannelID NewChannelID = NewChannel->GetChannelID();
1067  for (cChannel *channel = First(); channel; channel = Next(channel)) {
1068  if (!channel->GroupSep() && channel != OldChannel && channel->GetChannelID() == NewChannelID)
1069  return false;
1070  }
1071  return true;
1072 }
1073 
1074 bool cChannels::SwitchTo(int Number)
1075 {
1076  cChannel *channel = GetByNumber(Number);
1077  return channel && cDevice::PrimaryDevice()->SwitchChannel(channel, true);
1078 }
1079 
1081 {
1082  if (!maxChannelNameLength) {
1083  for (cChannel *channel = First(); channel; channel = Next(channel)) {
1084  if (!channel->GroupSep())
1085  maxChannelNameLength = max(Utf8StrLen(channel->Name()), maxChannelNameLength);
1086  }
1087  }
1088  return maxChannelNameLength;
1089 }
1090 
1092 {
1093  if (!maxShortChannelNameLength) {
1094  for (cChannel *channel = First(); channel; channel = Next(channel)) {
1095  if (!channel->GroupSep())
1096  maxShortChannelNameLength = max(Utf8StrLen(channel->ShortName(true)), maxShortChannelNameLength);
1097  }
1098  }
1099  return maxShortChannelNameLength;
1100 }
1101 
1102 void cChannels::SetModified(bool ByUser)
1103 {
1104  modified = ByUser ? CHANNELSMOD_USER : !modified ? CHANNELSMOD_AUTO : modified;
1105  maxChannelNameLength = maxShortChannelNameLength = 0;
1106 }
1107 
1109 {
1110  int Result = modified;
1111  modified = CHANNELSMOD_NONE;
1112  return Result;
1113 }
1114 
1115 cChannel *cChannels::NewChannel(const cChannel *Transponder, const char *Name, const char *ShortName, const char *Provider, int Nid, int Tid, int Sid, int Rid)
1116 {
1117  if (Transponder) {
1118  dsyslog("creating new channel '%s,%s;%s' on %s transponder %d with id %d-%d-%d-%d", Name, ShortName, Provider, *cSource::ToString(Transponder->Source()), Transponder->Transponder(), Nid, Tid, Sid, Rid);
1119  cChannel *NewChannel = new cChannel;
1120  NewChannel->CopyTransponderData(Transponder);
1121  NewChannel->SetId(Nid, Tid, Sid, Rid);
1122  NewChannel->SetName(Name, ShortName, Provider);
1123  NewChannel->SetSeen();
1124  Add(NewChannel);
1125  ReNumber();
1126  return NewChannel;
1127  }
1128  return NULL;
1129 }
1130 
1131 #define CHANNELMARKOBSOLETE "OBSOLETE"
1132 #define CHANNELTIMEOBSOLETE 3600 // seconds to wait before declaring a channel obsolete (in case it has actually been seen before)
1133 
1135 {
1136  for (cChannel *channel = First(); channel; channel = Next(channel)) {
1137  if (time(NULL) - channel->Seen() > CHANNELTIMEOBSOLETE && channel->Source() == Source && channel->Nid() == Nid && channel->Tid() == Tid && channel->Rid() == 0) {
1138  bool OldShowChannelNamesWithSource = Setup.ShowChannelNamesWithSource;
1140  if (!endswith(channel->Name(), CHANNELMARKOBSOLETE))
1141  channel->SetName(cString::sprintf("%s %s", channel->Name(), CHANNELMARKOBSOLETE), channel->ShortName(), cString::sprintf("%s %s", CHANNELMARKOBSOLETE, channel->Provider()));
1142  Setup.ShowChannelNamesWithSource = OldShowChannelNamesWithSource;
1143  }
1144  }
1145 }
1146 
1147 cString ChannelString(const cChannel *Channel, int Number)
1148 {
1149  char buffer[256];
1150  if (Channel) {
1151  if (Channel->GroupSep())
1152  snprintf(buffer, sizeof(buffer), "%s", Channel->Name());
1153  else
1154  snprintf(buffer, sizeof(buffer), "%d%s %s", Channel->Number(), Number ? "-" : "", Channel->Name());
1155  }
1156  else if (Number)
1157  snprintf(buffer, sizeof(buffer), "%d-", Number);
1158  else
1159  snprintf(buffer, sizeof(buffer), "%s", tr("*** Invalid Channel ***"));
1160  return buffer;
1161 }
static cString ToString(int Code)
Definition: sources.c:55
int sid
Definition: channels.h:59
unsigned char uchar
Definition: tools.h:30
void SetId(int Nid, int Tid, int Sid, int Rid=0)
Definition: channels.c:233
int Modified(void)
Returns 0 if no channels have been modified, 1 if an automatic modification has been made...
Definition: channels.c:1108
#define CHANNELTIMEOBSOLETE
Definition: channels.c:1132
int Number(void) const
Definition: channels.h:197
int tid
Definition: channels.h:137
cChannels Channels
Definition: channels.c:864
static char ToChar(int Code)
Definition: sources.h:51
bool isempty(const char *s)
Definition: tools.c:297
static tChannelID FromString(const char *s)
Definition: channels.c:26
#define dsyslog(a...)
Definition: tools.h:36
int StandardCompliance
Definition: config.h:284
int Utf8StrLen(const char *s)
Returns the number of UTF-8 symbols formed by the given string of character bytes.
Definition: tools.c:833
int GetPrevGroup(int Idx)
Definition: channels.c:921
int MaxShortChannelNameLength(void)
Definition: channels.c:1091
int Rid(void) const
Definition: channels.h:72
void CopyTransponderData(const cChannel *Channel)
Definition: channels.c:187
#define CHANNELMOD_PIDS
Definition: channels.h:23
void Add(cListObject *Object, cListObject *After=NULL)
Definition: tools.c:2014
static cString ToText(const cChannel *Channel)
Definition: channels.c:540
#define CHANNELMOD_AUX
Definition: channels.h:25
tChannelID(void)
Definition: channels.h:62
cTimers Timers
Definition: timers.c:694
bool endswith(const char *s, const char *p)
Definition: tools.c:286
static cString sprintf(const char *fmt,...) __attribute__((format(printf
Definition: tools.c:1080
#define CHANNELMOD_TRANSP
Definition: channels.h:27
int tid
Definition: channels.h:58
virtual void Append(T Data)
Definition: tools.h:571
static bool IsTerr(int Code)
Definition: sources.h:58
int ppid
Definition: channels.h:118
#define CHANNELMOD_NONE
Definition: channels.h:20
void MarkObsoleteChannels(int Source, int Nid, int Tid)
Definition: channels.c:1134
tChannelID channelID
Definition: channels.c:851
#define esyslog(a...)
Definition: tools.h:34
char * strn0cpy(char *dest, const char *src, size_t n)
Definition: tools.c:131
const char * ShortName(bool OrName=false) const
Definition: channels.c:133
cChannel & operator=(const cChannel &Channel)
Definition: channels.c:110
T max(T a, T b)
Definition: tools.h:55
Definition: tools.h:489
bool GroupSep(void) const
Definition: channels.h:199
#define CHANNELMOD_CA
Definition: channels.h:26
int Sid(void) const
Definition: channels.h:71
tChannelID & ClrPolarization(void)
Definition: channels.c:50
#define MAXTXTPAGES
Definition: channels.h:39
char * name
Definition: channels.h:109
void ReNumber(void)
Definition: channels.c:945
int spids[MAXSPIDS+1]
Definition: channels.h:126
int MaxChannelNameLength(void)
Definition: channels.c:1080
int nid
actually the "original" network id
Definition: channels.h:57
int Count(void) const
Definition: tools.h:485
cString ChannelString(const cChannel *Channel, int Number)
Definition: channels.c:1147
int Transponder(void) const
Returns the transponder frequency in MHz, plus the polarization in case of sat.
Definition: channels.c:158
bool groupSep
Definition: channels.h:142
int nid
Definition: channels.h:136
char * provider
Definition: channels.h:111
bool Save(FILE *f)
Definition: channels.c:841
int tpid
Definition: channels.h:131
bool Load(const char *FileName, bool AllowComments=false, bool MustExist=false)
Definition: channels.c:893
bool SetTransponderData(int Source, int Frequency, int Srate, const char *Parameters, bool Quiet=false)
Definition: channels.c:197
Definition: timers.h:27
#define CHANNELMOD_LANGS
Definition: channels.h:28
cChannel * Channel(void)
Definition: channels.h:95
char * shortName
Definition: channels.h:110
#define LCN_OVERFLOW_OFFSET
Definition: channels.h:52
#define STRDIFF
Definition: channels.c:299
const char * Name(void) const
Definition: channels.c:123
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:1115
T * Next(const T *object) const
Definition: tools.h:495
void SetName(const char *Name, const char *ShortName, const char *Provider)
Definition: channels.c:261
void SetTeletextSubtitlePages(tTeletextSubtitlePage pages[], int numberOfPages)
Definition: channels.c:425
int Source(void) const
Definition: channels.h:168
#define ISTRANSPONDER(f1, f2)
Definition: channels.h:18
virtual int Compare(const cListObject &ListObject) const
Must return 0 if this object is equal to ListObject, a positive value if it is "greater", and a negative value if it is "smaller".
Definition: channels.c:856
#define STANDARD_NORDIG
Definition: config.h:72
char alangs[MAXAPIDS][MAXLANGCODE2]
Definition: channels.h:122
cChannel(void)
Definition: channels.c:59
bool Parse(const char *s)
Definition: channels.c:609
#define CHANNELMOD_NAME
Definition: channels.h:22
cListObject * Next(void) const
Definition: tools.h:468
bool SwitchChannel(const cChannel *Channel, bool LiveView)
Switches the device to the given Channel, initiating transfer mode if necessary.
Definition: device.c:697
int GetNextNormal(int Idx)
Definition: channels.c:929
#define VALDIFF
Definition: channels.c:300
int source
Definition: channels.h:56
#define CHANNELSMOD_NONE
Definition: channels.h:31
int GetPrevNormal(int Idx)
Definition: channels.c:937
void Sort(void)
Definition: tools.c:2115
#define CA_USER_MAX
Definition: channels.h:48
void SetCaDescriptors(int Level)
Definition: channels.c:471
cChannels(void)
Definition: channels.c:866
int __EndData__
Definition: channels.h:143
char dlangs[MAXDPIDS][MAXLANGCODE2]
Definition: channels.h:125
int atypes[MAXAPIDS+1]
Definition: channels.h:121
int rid
Definition: channels.h:139
cSetup Setup
Definition: config.c:373
tChannelID GetChannelID(void) const
Definition: channels.h:208
int frequency
Definition: channels.h:114
void SetModified(bool ByUser=false)
Definition: channels.c:1102
int GetNextGroup(int Idx)
Definition: channels.c:913
cString TransponderDataToString(void) const
Definition: channels.c:533
void SetLcn(int Lcn)
Definition: channels.c:252
cChannel * GetByServiceID(int Source, int Transponder, unsigned short ServiceID)
Definition: channels.c:1010
int __BeginData__
Definition: channels.h:113
static int IntArrayToString(char *s, const int *a, int Base=10, const char n[][MAXLANGCODE2]=NULL, const int *t=NULL)
Definition: channels.c:318
int Size(void) const
Definition: tools.h:551
void SetSubtitlingDescriptors(uchar *SubtitlingTypes, uint16_t *CompositionPageIds, uint16_t *AncillaryPageIds)
Definition: channels.c:409
cChannel * GetByChannelID(tChannelID ChannelID, bool TryWithoutRid=false, bool TryWithoutPolarization=false)
Definition: channels.c:1023
int vpid
Definition: channels.h:117
#define MAXLANGCODE2
Definition: channels.h:42
bool HasTimer(void) const
Definition: channels.c:171
bool Valid(void) const
Definition: channels.h:65
#define CHANNELSMOD_AUTO
Definition: channels.h:32
char ttxtLanguage[MAXLANGCODE1]
Definition: channels.h:81
int sid
Definition: channels.h:138
void SetLinkChannels(cLinkChannels *LinkChannels)
Definition: channels.c:481
bool HasUniqueChannelID(cChannel *NewChannel, cChannel *OldChannel=NULL)
Definition: channels.c:1064
#define MAXDPIDS
Definition: channels.h:36
T * First(void) const
Definition: tools.h:492
cString ToString(void) const
Definition: channels.c:43
void SetRefChannel(cChannel *RefChannel)
Definition: channels.c:528
int ShowChannelNamesWithSource
Definition: config.h:361
int dpids[MAXDPIDS+1]
Definition: channels.h:123
cChannel * GetByNumber(int Number, int SkipGap=0)
Definition: channels.c:995
tTeletextSubtitlePage teletextSubtitlePages[MAXTXTPAGES]
Definition: channels.h:134
int PageNumber(void) const
Definition: channels.h:85
static cDevice * PrimaryDevice(void)
Returns the primary device.
Definition: device.h:137
void DeleteDuplicateChannels(void)
Definition: channels.c:874
static int FromString(const char *s)
Definition: sources.c:68
#define tr(s)
Definition: i18n.h:85
~cChannel()
Definition: channels.c:86
int source
Definition: channels.h:115
cChannel * channel
Definition: channels.c:850
char * skipspace(const char *s)
Definition: tools.h:200
cString parameters
Definition: channels.h:146
#define CHANNELSMOD_USER
Definition: channels.h:33
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:302
int rid
Definition: channels.h:60
char slangs[MAXSPIDS][MAXLANGCODE2]
Definition: channels.h:127
#define MAXSPIDS
Definition: channels.h:37
int vtype
Definition: channels.h:119
int caids[MAXCAIDS+1]
Definition: channels.h:135
int Tid(void) const
Definition: channels.h:70
cChannel * GetByTransponderID(tChannelID ChannelID)
Definition: channels.c:1052
static const tChannelID InvalidID
Definition: channels.h:75
int Modification(int Mask=CHANNELMOD_ALL)
Definition: channels.c:180
bool SwitchTo(int Number)
Definition: channels.c:1074
void UnhashChannel(cChannel *Channel)
Definition: channels.c:908
cChannelSorter(cChannel *Channel)
Definition: channels.c:852
int number
Definition: channels.h:141
#define MAXCAIDS
Definition: channels.h:38
void SetPids(int Vpid, int Ppid, int Vtype, int *Apids, int *Atypes, char ALangs[][MAXLANGCODE2], int *Dpids, int *Dtypes, char DLangs[][MAXLANGCODE2], int *Spids, char SLangs[][MAXLANGCODE2], int Tpid)
Definition: channels.c:341
int Sid(void) const
Definition: channels.h:194
void SetPortalName(const char *PortalName)
Definition: channels.c:287
tChannelID & ClrRid(void)
Definition: channels.h:66
#define CHANNELMARKOBSOLETE
Definition: channels.c:1131
char * portalName
Definition: channels.h:112
void SetSeen(void)
Definition: channels.c:445
#define CHANNELMOD_ID
Definition: channels.h:24
char * strreplace(char *s, char c1, char c2)
Definition: tools.c:139
void SetCaIds(const int *CaIds)
Definition: channels.c:450
cString ToText(void) const
Definition: channels.c:604
int fixedTtxtSubtitlePages
Definition: channels.h:132
int srate
Definition: channels.h:116
void HashChannel(cChannel *Channel)
Definition: channels.c:903
Definition: tools.h:168
int Source(void) const
Definition: channels.h:68
int apids[MAXAPIDS+1]
Definition: channels.h:120
#define MAXAPIDS
Definition: channels.h:35
int Nid(void) const
Definition: channels.h:69
int dtypes[MAXAPIDS+1]
Definition: channels.h:124