void cChannel::SetName(const char *Name, const char *ShortName, const char *Provider) { if (!isempty(Name)) { bool nn = strcmp(name, Name) != 0; bool ns = strcmp(shortName, ShortName) != 0; bool np = strcmp(provider, Provider) != 0; if (nn || ns || np) { if (Number()) { dsyslog("changing name of channel %d from '%s,%s;%s' to '%s,%s;%s'", Number(), name, shortName, provider, Name, ShortName, Provider); modification |= CHANNELMOD_NAME; Channels.SetModified(); } if (nn) { name = strcpyrealloc(name, Name); nameSource = NULL; } if (ns) { shortName = strcpyrealloc(shortName, ShortName); shortNameSource = NULL; } if (np) provider = strcpyrealloc(provider, Provider); } } }
cChannel& cChannel::operator= (const cChannel &Channel) { name = strcpyrealloc(name, Channel.name); shortName = strcpyrealloc(shortName, Channel.shortName); provider = strcpyrealloc(provider, Channel.provider); portalName = strcpyrealloc(portalName, Channel.portalName); memcpy(&__BeginData__, &Channel.__BeginData__, (char *)&Channel.__EndData__ - (char *)&Channel.__BeginData__); return *this; }
cChannel& cChannel::operator= (const cChannel &Channel) { name = strcpyrealloc(name, Channel.name); shortName = strcpyrealloc(shortName, Channel.shortName); provider = strcpyrealloc(provider, Channel.provider); portalName = strcpyrealloc(portalName, Channel.portalName); memcpy(&__BeginData__, &Channel.__BeginData__, (char *)&Channel.__EndData__ - (char *)&Channel.__BeginData__); nameSource = NULL; // these will be recalculated automatically shortNameSource = NULL; parameters = Channel.parameters; return *this; }
void cEpg::SetGenre(const char *Genre, int genreType, int genreSubType) { m_genre_type = genreType; m_genre_sub_type = genreSubType; if (Genre) m_genre = strcpyrealloc(m_genre, Genre); }
void cChannel::SetPortalName(const char *PortalName) { if (!isempty(PortalName) && strcmp(portalName, PortalName) != 0) { if (Number()) { dsyslog("changing portal name of channel %d from '%s' to '%s'", Number(), portalName, PortalName); modification |= CHANNELMOD_NAME; Channels.SetModified(); } portalName = strcpyrealloc(portalName, PortalName); } }
void cComponents::SetComponent(int Index, uchar Stream, uchar Type, const char *Language, const char *Description) { Realloc(Index); tComponent *p = &components[Index]; p->stream = Stream; p->type = Type; strn0cpy(p->language, Language, sizeof(p->language)); char *q = strchr(p->language, ','); if (q) *q = 0; // strips rest of "normalized" language codes p->description = strcpyrealloc(p->description, !isempty(Description) ? Description : NULL); }
void cEvent::FixEpgBugs(void) { // VDR can't usefully handle newline characters in the title and shortText of EPG // data, so let's always convert them to blanks (independent of the setting of EPGBugfixLevel): strreplace(title, '\n', ' '); strreplace(shortText, '\n', ' '); // Same for control characters: strreplace(title, '\x86', ' '); strreplace(title, '\x87', ' '); strreplace(shortText, '\x86', ' '); strreplace(shortText, '\x87', ' '); strreplace(description, '\x86', ' '); strreplace(description, '\x87', ' '); if (isempty(title)) { // we don't want any "(null)" titles title = strcpyrealloc(title, tr("No title")); EpgBugFixStat(12, ChannelID()); } if (Setup.EPGBugfixLevel == 0) return; // Some TV stations apparently have their own idea about how to fill in the // EPG data. Let's fix their bugs as good as we can: // Some channels put the ShortText in quotes and use either the ShortText // or the Description field, depending on how long the string is: // // Title // "ShortText". Description // if ((shortText == NULL) != (description == NULL)) { char *p = shortText ? shortText : description; if (*p == '"') { const char *delim = "\"."; char *e = strstr(p + 1, delim); if (e) { *e = 0; char *s = strdup(p + 1); char *d = strdup(e + strlen(delim)); free(shortText); free(description); shortText = s; description = d; EpgBugFixStat(1, ChannelID()); } } } // Some channels put the Description into the ShortText (preceded // by a blank) if there is no actual ShortText and the Description // is short enough: // // Title // Description // if (shortText && !description) { if (*shortText == ' ') { memmove(shortText, shortText + 1, strlen(shortText)); description = shortText; shortText = NULL; EpgBugFixStat(2, ChannelID()); } } // Sometimes they repeat the Title in the ShortText: // // Title // Title // if (shortText && strcmp(title, shortText) == 0) { free(shortText); shortText = NULL; EpgBugFixStat(3, ChannelID()); } // Some channels put the ShortText between double quotes, which is nothing // but annoying (some even put a '.' after the closing '"'): // // Title // "ShortText"[.] // if (shortText && *shortText == '"') { int l = strlen(shortText); if (l > 2 && (shortText[l - 1] == '"' || (shortText[l - 1] == '.' && shortText[l - 2] == '"'))) { memmove(shortText, shortText + 1, l); char *p = strrchr(shortText, '"'); if (p) *p = 0; EpgBugFixStat(4, ChannelID()); } } if (Setup.EPGBugfixLevel <= 1) return; // Some channels apparently try to do some formatting in the texts, // which is a bad idea because they have no way of knowing the width // of the window that will actually display the text. // Remove excess whitespace: title = compactspace(title); shortText = compactspace(shortText); description = compactspace(description); #define MAX_USEFUL_EPISODE_LENGTH 40 // Some channels put a whole lot of information in the ShortText and leave // the Description totally empty. So if the ShortText length exceeds // MAX_USEFUL_EPISODE_LENGTH, let's put this into the Description // instead: if (!isempty(shortText) && isempty(description)) { if (strlen(shortText) > MAX_USEFUL_EPISODE_LENGTH) { free(description); description = shortText; shortText = NULL; EpgBugFixStat(6, ChannelID()); } } // Some channels put the same information into ShortText and Description. // In that case we delete one of them: if (shortText && description && strcmp(shortText, description) == 0) { if (strlen(shortText) > MAX_USEFUL_EPISODE_LENGTH) { free(shortText); shortText = NULL; } else { free(description); description = NULL; } EpgBugFixStat(7, ChannelID()); } // Some channels use the ` ("backtick") character, where a ' (single quote) // would be normally used. Actually, "backticks" in normal text don't make // much sense, so let's replace them: strreplace(title, '`', '\''); strreplace(shortText, '`', '\''); strreplace(description, '`', '\''); if (Setup.EPGBugfixLevel <= 2) return; // The stream components have a "description" field which some channels // apparently have no idea of how to set correctly: if (components) { for (int i = 0; i < components->NumComponents(); i++) { tComponent *p = components->Component(i); switch (p->stream) { case 0x01: { // video if (p->description) { if (strcasecmp(p->description, "Video") == 0 || strcasecmp(p->description, "Bildformat") == 0) { // Yes, we know it's video - that's what the 'stream' code // is for! But _which_ video is it? free(p->description); p->description = NULL; EpgBugFixStat(8, ChannelID()); } } if (!p->description) { switch (p->type) { case 0x01: case 0x05: p->description = strdup("4:3"); break; case 0x02: case 0x03: case 0x06: case 0x07: p->description = strdup("16:9"); break; case 0x04: case 0x08: p->description = strdup(">16:9"); break; case 0x09: case 0x0D: p->description = strdup("HD 4:3"); break; case 0x0A: case 0x0B: case 0x0E: case 0x0F: p->description = strdup("HD 16:9"); break; case 0x0C: case 0x10: p->description = strdup("HD >16:9"); break; } EpgBugFixStat(9, ChannelID()); } } break; case 0x02: { // audio if (p->description) { if (strcasecmp(p->description, "Audio") == 0) { // Yes, we know it's audio - that's what the 'stream' code // is for! But _which_ audio is it? free(p->description); p->description = NULL; EpgBugFixStat(10, ChannelID()); } } if (!p->description) { switch (p->type) { case 0x05: p->description = strdup("Dolby Digital"); break; // all others will just display the language } EpgBugFixStat(11, ChannelID()); } } break; } } } }
void cEvent::SetDescription(const char *Description) { description = strcpyrealloc(description, Description); }
void cEvent::SetShortText(const char *ShortText) { shortText = strcpyrealloc(shortText, ShortText); }
void cEvent::SetTitle(const char *Title) { title = strcpyrealloc(title, Title); }
void cEpg::SetDescription(const char *Description) { m_description = strcpyrealloc(m_description, Description); }
void cEpg::SetShortText(const char *ShortText) { m_shortText = strcpyrealloc(m_shortText, ShortText); }
void cEpg::SetTitle(const char *Title) { m_title = strcpyrealloc(m_title, Title); }
bool cChannel::Parse(const char *s) { bool ok = true; if (*s == ':') { groupSep = true; if (*++s == '@' && *++s) { char *p = NULL; errno = 0; int n = strtol(s, &p, 10); if (!errno && p != s && n > 0) { number = n; s = p; } } name = strcpyrealloc(name, skipspace(s)); strreplace(name, '|', ':'); } else { groupSep = false; char *namebuf = NULL; char *sourcebuf = NULL; char *parambuf = NULL; char *vpidbuf = NULL; char *apidbuf = NULL; char *tpidbuf = NULL; char *caidbuf = NULL; int fields = sscanf(s, "%a[^:]:%d :%a[^:]:%a[^:] :%d :%a[^:]:%a[^:]:%a[^:]:%a[^:]:%d :%d :%d :%d ", &namebuf, &frequency, ¶mbuf, &sourcebuf, &srate, &vpidbuf, &apidbuf, &tpidbuf, &caidbuf, &sid, &nid, &tid, &rid); if (fields >= 9) { if (fields == 9) { // allow reading of old format sid = atoi(caidbuf); delete caidbuf; caidbuf = NULL; if (sscanf(tpidbuf, "%d", &tpid) != 1) return false; caids[0] = tpid; caids[1] = 0; tpid = 0; } vpid = ppid = 0; vtype = 0; apids[0] = 0; atypes[0] = 0; dpids[0] = 0; dtypes[0] = 0; spids[0] = 0; ok = false; if (parambuf && sourcebuf && vpidbuf && apidbuf) { parameters = parambuf; ok = (source = cSource::FromString(sourcebuf)) >= 0; char *p; if ((p = strchr(vpidbuf, '=')) != NULL) { *p++ = 0; if (sscanf(p, "%d", &vtype) != 1) return false; } if ((p = strchr(vpidbuf, '+')) != NULL) { *p++ = 0; if (sscanf(p, "%d", &ppid) != 1) return false; } if (sscanf(vpidbuf, "%d", &vpid) != 1) return false; if (!ppid) ppid = vpid; if (vpid && !vtype) vtype = 2; // default is MPEG-2 char *dpidbuf = strchr(apidbuf, ';'); if (dpidbuf) *dpidbuf++ = 0; p = apidbuf; char *q; int NumApids = 0; char *strtok_next; while ((q = strtok_r(p, ",", &strtok_next)) != NULL) { if (NumApids < MAXAPIDS) { atypes[NumApids] = 4; // backwards compatibility char *l = strchr(q, '='); if (l) { *l++ = 0; char *t = strchr(l, '@'); if (t) { *t++ = 0; atypes[NumApids] = strtol(t, NULL, 10); } strn0cpy(alangs[NumApids], l, MAXLANGCODE2); } else *alangs[NumApids] = 0; if ((apids[NumApids] = strtol(q, NULL, 10)) != 0) NumApids++; } else esyslog("ERROR: too many APIDs!"); // no need to set ok to 'false' p = NULL; } apids[NumApids] = 0; atypes[NumApids] = 0; if (dpidbuf) { char *p = dpidbuf; char *q; int NumDpids = 0; char *strtok_next; while ((q = strtok_r(p, ",", &strtok_next)) != NULL) { if (NumDpids < MAXDPIDS) { dtypes[NumDpids] = SI::AC3DescriptorTag; // backwards compatibility char *l = strchr(q, '='); if (l) { *l++ = 0; char *t = strchr(l, '@'); if (t) { *t++ = 0; dtypes[NumDpids] = strtol(t, NULL, 10); } strn0cpy(dlangs[NumDpids], l, MAXLANGCODE2); } else *dlangs[NumDpids] = 0; if ((dpids[NumDpids] = strtol(q, NULL, 10)) != 0) NumDpids++; } else esyslog("ERROR: too many DPIDs!"); // no need to set ok to 'false' p = NULL; } dpids[NumDpids] = 0; dtypes[NumDpids] = 0; } int NumSpids = 0; if ((p = strchr(tpidbuf, ';')) != NULL) { *p++ = 0; char *q; char *strtok_next; while ((q = strtok_r(p, ",", &strtok_next)) != NULL) { if (NumSpids < MAXSPIDS) { char *l = strchr(q, '='); if (l) { *l++ = 0; strn0cpy(slangs[NumSpids], l, MAXLANGCODE2); } else *slangs[NumSpids] = 0; spids[NumSpids++] = strtol(q, NULL, 10); } else esyslog("ERROR: too many SPIDs!"); // no need to set ok to 'false' p = NULL; } spids[NumSpids] = 0; } if (sscanf(tpidbuf, "%d", &tpid) != 1) return false; if (caidbuf) { char *p = caidbuf; char *q; int NumCaIds = 0; char *strtok_next; while ((q = strtok_r(p, ",", &strtok_next)) != NULL) { if (NumCaIds < MAXCAIDS) { caids[NumCaIds++] = strtol(q, NULL, 16) & 0xFFFF; if (NumCaIds == 1 && caids[0] <= CA_USER_MAX) break; } else esyslog("ERROR: too many CA ids!"); // no need to set ok to 'false' p = NULL; } caids[NumCaIds] = 0; } } strreplace(namebuf, '|', ':'); char *p = strchr(namebuf, ';'); if (p) { *p++ = 0; provider = strcpyrealloc(provider, p); } p = strrchr(namebuf, ','); // long name might contain a ',', so search for the rightmost one if (p) { *p++ = 0; shortName = strcpyrealloc(shortName, p); } name = strcpyrealloc(name, namebuf); free(parambuf); free(sourcebuf); free(vpidbuf); free(apidbuf); free(tpidbuf); free(caidbuf); free(namebuf); if (!GetChannelID().Valid()) { esyslog("ERROR: channel data results in invalid ID!"); return false; } } else return false; } return ok; }
bool cChannel::Parse(const char *s) { bool ok = true; if (*s == ':') { groupSep = true; if (*++s == '@' && *++s) { char *p = NULL; errno = 0; int n = strtol(s, &p, 10); if (!errno && p != s && n > 0) { number = n; s = p; } } name = strcpyrealloc(name, skipspace(s)); strreplace(name, '|', ':'); } else { groupSep = false; char *namebuf = NULL; char *sourcebuf = NULL; char *parambuf = NULL; char *vpidbuf = NULL; char *apidbuf = NULL; char *caidbuf = NULL; int fields = sscanf(s, "%a[^:]:%d :%a[^:]:%a[^:] :%d :%a[^:]:%a[^:]:%d :%a[^:]:%d :%d :%d :%d ", &namebuf, &frequency, ¶mbuf, &sourcebuf, &srate, &vpidbuf, &apidbuf, &tpid, &caidbuf, &sid, &nid, &tid, &rid); if (fields >= 9) { if (fields == 9) { // allow reading of old format sid = atoi(caidbuf); delete caidbuf; caidbuf = NULL; caids[0] = tpid; caids[1] = 0; tpid = 0; } vpid = ppid = 0; apids[0] = 0; dpids[0] = 0; ok = false; if (parambuf && sourcebuf && vpidbuf && apidbuf) { ok = StringToParameters(parambuf) && (source = cSource::FromString(sourcebuf)) >= 0; char *p = strchr(vpidbuf, '+'); if (p) *p++ = 0; if (sscanf(vpidbuf, "%d", &vpid) != 1) return false; if (p) { if (sscanf(p, "%d", &ppid) != 1) return false; } else ppid = vpid; char *dpidbuf = strchr(apidbuf, ';'); if (dpidbuf) *dpidbuf++ = 0; p = apidbuf; char *q; int NumApids = 0; char *strtok_next; while ((q = strtok_r(p, ",", &strtok_next)) != NULL) { if (NumApids < MAXAPIDS) { char *l = strchr(q, '='); if (l) { *l++ = 0; strn0cpy(alangs[NumApids], l, MAXLANGCODE2); } else *alangs[NumApids] = 0; apids[NumApids++] = strtol(q, NULL, 10); } else esyslog("ERROR: too many APIDs!"); // no need to set ok to 'false' p = NULL; } apids[NumApids] = 0; if (dpidbuf) { char *p = dpidbuf; char *q; int NumDpids = 0; char *strtok_next; while ((q = strtok_r(p, ",", &strtok_next)) != NULL) { if (NumDpids < MAXDPIDS) { char *l = strchr(q, '='); if (l) { *l++ = 0; strn0cpy(dlangs[NumDpids], l, MAXLANGCODE2); } else *dlangs[NumDpids] = 0; dpids[NumDpids++] = strtol(q, NULL, 10); } else esyslog("ERROR: too many DPIDs!"); // no need to set ok to 'false' p = NULL; } dpids[NumDpids] = 0; } if (caidbuf) { char *p = caidbuf; char *q; int NumCaIds = 0; char *strtok_next; while ((q = strtok_r(p, ",", &strtok_next)) != NULL) { if (NumCaIds < MAXCAIDS) { caids[NumCaIds++] = strtol(q, NULL, 16) & 0xFFFF; if (NumCaIds == 1 && caids[0] <= 0x00FF) break; } else esyslog("ERROR: too many CA ids!"); // no need to set ok to 'false' p = NULL; } caids[NumCaIds] = 0; } } strreplace(namebuf, '|', ':'); char *p = strchr(namebuf, ';'); if (p) { *p++ = 0; provider = strcpyrealloc(provider, p); } p = strchr(namebuf, ','); if (p) { *p++ = 0; shortName = strcpyrealloc(shortName, p); } name = strcpyrealloc(name, namebuf); free(parambuf); free(sourcebuf); free(vpidbuf); free(apidbuf); free(caidbuf); free(namebuf); if (!GetChannelID().Valid()) { esyslog("ERROR: channel data results in invalid ID!"); return false; } } else return false; } return ok; }