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