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