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