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