diff --git a/HISTORY b/HISTORY index 27753b58..edf2650d 100644 --- a/HISTORY +++ b/HISTORY @@ -2620,3 +2620,7 @@ Video Disk Recorder Revision History - Fixed frequency handling when setting the CA descriptors in cDvbTuner::Action() (thanks to Jan Ekholm for reporting and helping to debug this one). - Now setting CA descriptors even if "Setup/DVB/Update channels" is less than 2. +- There can now be up to 32 audio and Dolby PIDs (however, currently still only + the first two are used throughout the rest of the program). +- The audio and Dolby PIDs in 'channels.conf' now can have an optional language + code (see man vdr(5)). Currently this is only stored and not yet used otherwise. diff --git a/channels.c b/channels.c index 67ee2b53..d49d7a4d 100644 --- a/channels.c +++ b/channels.c @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: channels.c 1.19 2004/01/11 15:52:32 kls Exp $ + * $Id: channels.c 1.20 2004/01/25 15:32:08 kls Exp $ */ #include "channels.h" @@ -177,10 +177,8 @@ cChannel::cChannel(const cChannel *Channel) *name = 0; vpid = 0; ppid = 0; - apid1 = 0; - apid2 = 0; - dpid1 = 0; - dpid2 = 0; + apids[0] = 0; + dpids[0] = 0; tpid = 0; caids[0] = 0; nid = 0; @@ -305,18 +303,62 @@ void cChannel::SetName(const char *Name, bool Log) } } -void cChannel::SetPids(int Vpid, int Ppid, int Apid1, int Apid2, int Dpid1, int Dpid2, int Tpid) +static bool IntArraysDiffer(const int *a, const int *b, const char na[][4] = NULL, const char nb[][4] = NULL) { - //XXX if (vpid != Vpid || ppid != Ppid || apid1 != Apid1 || apid2 != Apid2 || dpid1 != Dpid1 || dpid2 != Dpid2 || tpid != Tpid) { - if (vpid != Vpid || ppid != Ppid || apid1 != Apid1 || (Apid2 && apid2 != Apid2) || dpid1 != Dpid1 || dpid2 != Dpid2 || tpid != Tpid) { - dsyslog("changing pids of channel %d from %d+%d:%d,%d;%d,%d:%d to %d+%d:%d,%d;%d,%d:%d", Number(), vpid, ppid, apid1, apid2, dpid1, dpid2, tpid, Vpid, Ppid, Apid1, Apid2, Dpid1, Dpid2, Tpid); + int i = 0; + while (a[i] && b[i]) { + if (a[i] != b[i] || na && nb && strcmp(na[i], nb[i]) != 0) + return true; + i++; + } + return a[i] != b[i] || a[i] && na && nb && strcmp(na[i], nb[i]) != 0; +} + +static int IntArrayToString(char *s, const int *a, int Base = 10, const char n[][4] = NULL) +{ + char *q = s; + int i = 0; + while (a[i] || i == 0) { + q += sprintf(q, Base == 16 ? "%s%X" : "%s%d", i ? "," : "", a[i]); + if (n && *n[i]) + q += sprintf(q, "=%s", n[i]); + i++; + } + *q = 0; + return q - s; +} + +void cChannel::SetPids(int Vpid, int Ppid, int *Apids, char ALangs[][4], int *Dpids, char DLangs[][4], int Tpid) +{ + bool modified = vpid != Vpid || ppid != Ppid || tpid != Tpid; + if (!modified) + modified = IntArraysDiffer(apids, Apids, alangs, ALangs) || IntArraysDiffer(dpids, Dpids, dlangs, DLangs); + if (modified) { + char OldApidsBuf[MAXAPIDS * 2 * 10 + 10]; // 2: Apids and Dpids, 10: 5 digits plus delimiting ',' or ';' plus optional '=cod', +10: paranoia + char NewApidsBuf[MAXAPIDS * 2 * 10 + 10]; + char *q = OldApidsBuf; + q += IntArrayToString(q, apids, 10, alangs); + if (dpids[0]) { + *q++ = ';'; + q += IntArrayToString(q, dpids, 10, dlangs); + } + *q = 0; + q = NewApidsBuf; + q += IntArrayToString(q, Apids, 10, ALangs); + if (Dpids[0]) { + *q++ = ';'; + q += IntArrayToString(q, Dpids, 10, DLangs); + } + *q = 0; + dsyslog("changing pids of channel %d from %d+%d:%s:%d to %d+%d:%s:%d", Number(), vpid, ppid, OldApidsBuf, tpid, Vpid, Ppid, NewApidsBuf, Tpid); vpid = Vpid; ppid = Ppid; - apid1 = Apid1; - if (Apid2)//XXX should we actually react here? - apid2 = Apid2; - dpid1 = Dpid1; - dpid2 = Dpid2; + for (int i = 0; i <= MAXAPIDS; i++) { // <= to copy the terminating 0 + apids[i] = Apids[i]; + strn0cpy(alangs[i], ALangs[i], 4); + dpids[i] = Dpids[i]; + strn0cpy(dlangs[i], DLangs[i], 4); + } tpid = Tpid; modification |= CHANNELMOD_PIDS; Channels.SetModified(); @@ -327,37 +369,14 @@ void cChannel::SetCaIds(const int *CaIds) { if (caids[0] && caids[0] <= 0x00FF) return; // special values will not be overwritten - bool modified = false; - for (int i = 0; i < MAXCAIDS; i++) { - if (caids[i] != CaIds[i]) { - modified = true; - break; - } - if (!caids[i] || !CaIds[i]) - break; - } - if (modified) { + if (IntArraysDiffer(caids, CaIds)) { char OldCaIdsBuf[MAXCAIDS * 5 + 10]; // 5: 4 digits plus delimiting ',', 10: paranoia char NewCaIdsBuf[MAXCAIDS * 5 + 10]; - char *qo = OldCaIdsBuf; - char *qn = NewCaIdsBuf; - int i; - for (i = 0; i < MAXCAIDS; i++) { - if (i == 0 || caids[i]) - qo += snprintf(qo, sizeof(OldCaIdsBuf), "%s%X", i > 0 ? "," : "", caids[i]); - if (!caids[i]) - break; - } - for (i = 0; i < MAXCAIDS; i++) { - if (i == 0 || CaIds[i]) - qn += snprintf(qn, sizeof(NewCaIdsBuf), "%s%X", i > 0 ? "," : "", CaIds[i]); - caids[i] = CaIds[i]; - if (!CaIds[i]) - break; - } - caids[i] = 0; - *qo = *qn = 0; + IntArrayToString(OldCaIdsBuf, caids, 16); + IntArrayToString(NewCaIdsBuf, CaIds, 16); dsyslog("changing caids of channel %d from %s to %s", Number(), OldCaIdsBuf, NewCaIdsBuf); + for (int i = 0; i <= MAXCAIDS && CaIds[i]; i++) // <= to copy the terminating 0 + caids[i] = CaIds[i]; modification |= CHANNELMOD_CA; Channels.SetModified(); } @@ -460,24 +479,17 @@ const char *cChannel::ToText(cChannel *Channel) if (Channel->ppid && Channel->ppid != Channel->vpid) q += snprintf(q, sizeof(vpidbuf) - (q - vpidbuf), "+%d", Channel->ppid); *q = 0; - char apidbuf[MAXAPIDS * 2 * 6 + 10]; // 2: Apids and Dpids, 6: 5 digits plus delimiting ',' or ';', 10: paranoia + char apidbuf[MAXAPIDS * 2 * 10 + 10]; // 2: Apids and Dpids, 10: 5 digits plus delimiting ',' or ';' plus optional '=cod', +10: paranoia q = apidbuf; - q += snprintf(q, sizeof(apidbuf), "%d", Channel->apid1); - if (Channel->apid2) - q += snprintf(q, sizeof(apidbuf) - (q - apidbuf), ",%d", Channel->apid2); - if (Channel->dpid1 || Channel->dpid2) - q += snprintf(q, sizeof(apidbuf) - (q - apidbuf), ";%d", Channel->dpid1); - if (Channel->dpid2) - q += snprintf(q, sizeof(apidbuf) - (q - apidbuf), ",%d", Channel->dpid2); + q += IntArrayToString(q, Channel->apids, 10, Channel->alangs); + if (Channel->dpids[0]) { + *q++ = ';'; + q += IntArrayToString(q, Channel->dpids, 10, Channel->dlangs); + } *q = 0; char caidbuf[MAXCAIDS * 5 + 10]; // 5: 4 digits plus delimiting ',', 10: paranoia q = caidbuf; - for (int i = 0; i < MAXCAIDS; i++) { - if (i == 0 || Channel->caids[i]) - q += snprintf(q, sizeof(caidbuf), "%s%X", i > 0 ? "," : "", Channel->caids[i]); - if (!Channel->caids[i]) - break; - } + q += IntArrayToString(q, Channel->caids, 16); *q = 0; asprintf(&buffer, "%s:%d:%s:%s:%d:%s:%s:%d:%s:%d:%d:%d:%d\n", s, Channel->frequency, Channel->ParametersToString(), cSource::ToString(Channel->source), Channel->srate, vpidbuf, apidbuf, Channel->tpid, caidbuf, Channel->sid, Channel->nid, Channel->tid, Channel->rid); } @@ -524,9 +536,9 @@ bool cChannel::Parse(const char *s, bool AllowNonUniqueID) caids[1] = 0; tpid = 0; } - vpid = ppid = 0; - apid1 = apid2 = 0; - dpid1 = dpid2 = 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; @@ -540,12 +552,49 @@ bool cChannel::Parse(const char *s, bool AllowNonUniqueID) else ppid = vpid; - p = strchr(apidbuf, ';'); - if (p) - *p++ = 0; - sscanf(apidbuf, "%d ,%d ", &apid1, &apid2); - if (p) - sscanf(p, "%d ,%d ", &dpid1, &dpid2); + char *dpidbuf = strchr(apidbuf, ';'); + if (dpidbuf) + *dpidbuf++ = 0; + p = apidbuf; + char *q; + int NumApids = 0; + while ((q = strtok(p, ",")) != NULL) { + if (NumApids < MAXAPIDS) { + char *l = strchr(q, '='); + if (l) { + *l++ = 0; + strn0cpy(alangs[NumApids], l, 4); + } + 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; + while ((q = strtok(p, ",")) != NULL) { + if (NumDpids < MAXAPIDS) { + char *l = strchr(q, '='); + if (l) { + *l++ = 0; + strn0cpy(dlangs[NumDpids], l, 4); + } + 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; diff --git a/channels.h b/channels.h index 64c05ebe..532a1121 100644 --- a/channels.h +++ b/channels.h @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: channels.h 1.12 2004/01/11 15:20:18 kls Exp $ + * $Id: channels.h 1.13 2004/01/25 15:31:16 kls Exp $ */ #ifndef __CHANNELS_H @@ -26,7 +26,7 @@ #define CHANNELMOD_TRANSP 0x20 #define CHANNELMOD_RETUNE (CHANNELMOD_PIDS | CHANNELMOD_CA | CHANNELMOD_TRANSP) -#define MAXAPIDS 2 +#define MAXAPIDS 32 #define MAXCAIDS 8 struct tChannelParameterMap { @@ -79,8 +79,10 @@ private: int srate; int vpid; int ppid; - int apid1, apid2; - int dpid1, dpid2; + int apids[MAXAPIDS + 1]; // list is zero-terminated + char alangs[MAXAPIDS][4]; + int dpids[MAXAPIDS + 1]; // list is zero-terminated + char dlangs[MAXAPIDS][4]; int tpid; int caids[MAXCAIDS + 1]; // list is zero-terminated int nid; @@ -116,10 +118,10 @@ public: int Srate(void) const { return srate; } int Vpid(void) const { return vpid; } int Ppid(void) const { return ppid; } - int Apid1(void) const { return apid1; } - int Apid2(void) const { return apid2; } - int Dpid1(void) const { return dpid1; } - int Dpid2(void) const { return dpid2; } + int Apid1(void) const { return apids[0]; } + int Apid2(void) const { return apids[1]; } + int Dpid1(void) const { return dpids[0]; } + int Dpid2(void) const { return dpids[1]; } int Tpid(void) const { return tpid; } int Ca(int Index = 0) const { return Index < MAXCAIDS ? caids[Index] : 0; } int Nid(void) const { return nid; } @@ -148,7 +150,7 @@ public: bool SetTerrTransponderData(int Source, int Frequency, int Bandwidth, int Modulation, int Hierarchy, int CodeRateH, int CodeRateL, int Guard, int Transmission, bool Log = true); void SetId(int Nid, int Tid, int Sid, int Rid = 0, bool Log = true); void SetName(const char *Name, bool Log = true); - void SetPids(int Vpid, int Ppid, int Apid1, int Apid2, int Dpid1, int Dpid2, int Tpid); + void SetPids(int Vpid, int Ppid, int *Apids, char ALangs[][4], int *Dpids, char DLangs[][4], int Tpid); void SetCaIds(const int *CaIds); // list must be zero-terminated void SetCaDescriptors(int Level); }; diff --git a/config.c b/config.c index 6caf587a..f6814e84 100644 --- a/config.c +++ b/config.c @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: config.c 1.120 2004/01/11 15:38:11 kls Exp $ + * $Id: config.c 1.121 2004/01/25 14:41:10 kls Exp $ */ #include "config.h" @@ -403,7 +403,7 @@ void cSetup::StoreLanguages(const char *Name, int *Values) for (int i = 0; i < I18nNumLanguages; i++) { if (Values[i] < 0) break; - const char *s = I18nLanguageAbbreviation(Values[i]); + const char *s = I18nLanguageCode(Values[i]); if (s) { if (q > buffer) *q++ = ' '; diff --git a/i18n.c b/i18n.c index 6a5060ff..f87827b6 100644 --- a/i18n.c +++ b/i18n.c @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: i18n.c 1.145 2004/01/24 14:58:08 kls Exp $ + * $Id: i18n.c 1.146 2004/01/25 14:41:02 kls Exp $ * * Translations provided by: * @@ -4233,9 +4233,9 @@ const char * const * I18nCharSets(void) return &Phrases[1][0]; } -const char * I18nLanguageAbbreviation(int Index) +const char * I18nLanguageCode(int Index) { - return Index < I18nNumLanguages ? Phrases[2][Index] : NULL; + return 0 <= Index && Index < I18nNumLanguages ? Phrases[2][Index] : NULL; } int I18nLanguageIndex(const char *Code) @@ -4248,6 +4248,12 @@ int I18nLanguageIndex(const char *Code) return -1; } +const char *I18nNormalizeLanguageCode(const char *Code) +{ + int n = I18nLanguageIndex(Code); + return n >= 0 ? I18nLanguageCode(n) : Code; +} + bool I18nIsPreferredLanguage(int *PreferredLanguages, int LanguageIndex, int &OldPreference) { for (int i = 0; i < I18nNumLanguages; i++) { diff --git a/i18n.h b/i18n.h index dfea90fc..ff990025 100644 --- a/i18n.h +++ b/i18n.h @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: i18n.h 1.10 2004/01/24 14:57:29 kls Exp $ + * $Id: i18n.h 1.11 2004/01/25 14:40:50 kls Exp $ */ #ifndef __I18N_H @@ -22,8 +22,9 @@ const char *I18nTranslate(const char *s, const char *Plugin = NULL); const char * const * I18nLanguages(void); const char * const * I18nCharSets(void); -const char * I18nLanguageAbbreviation(int Index); +const char * I18nLanguageCode(int Index); int I18nLanguageIndex(const char *Code); +const char *I18nNormalizeLanguageCode(const char *Code); bool I18nIsPreferredLanguage(int *PreferredLanguages, int LanguageIndex, int &OldPreference); #ifdef PLUGIN_NAME_I18N diff --git a/menu.c b/menu.c index 8526f36b..e834db46 100644 --- a/menu.c +++ b/menu.c @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: menu.c 1.281 2004/01/17 14:17:00 kls Exp $ + * $Id: menu.c 1.282 2004/01/25 14:40:00 kls Exp $ */ #include "menu.h" @@ -577,10 +577,10 @@ void cMenuEditChannel::Setup(void) Add(new cMenuEditIntItem( tr("Frequency"), &data.frequency)); Add(new cMenuEditIntItem( tr("Vpid"), &data.vpid, 0, 0x1FFF)); Add(new cMenuEditIntItem( tr("Ppid"), &data.ppid, 0, 0x1FFF)); - Add(new cMenuEditIntItem( tr("Apid1"), &data.apid1, 0, 0x1FFF)); - Add(new cMenuEditIntItem( tr("Apid2"), &data.apid2, 0, 0x1FFF)); - Add(new cMenuEditIntItem( tr("Dpid1"), &data.dpid1, 0, 0x1FFF)); - Add(new cMenuEditIntItem( tr("Dpid2"), &data.dpid2, 0, 0x1FFF)); + Add(new cMenuEditIntItem( tr("Apid1"), &data.apids[0], 0, 0x1FFF)); + Add(new cMenuEditIntItem( tr("Apid2"), &data.apids[1], 0, 0x1FFF)); + Add(new cMenuEditIntItem( tr("Dpid1"), &data.dpids[0], 0, 0x1FFF)); + Add(new cMenuEditIntItem( tr("Dpid2"), &data.dpids[1], 0, 0x1FFF)); Add(new cMenuEditIntItem( tr("Tpid"), &data.tpid, 0, 0x1FFF)); Add(new cMenuEditCaItem( tr("CA"), &data.caids[0], true));//XXX Add(new cMenuEditIntItem( tr("Sid"), &data.sid, 0)); diff --git a/pat.c b/pat.c index 393f4b74..9b27bdae 100644 --- a/pat.c +++ b/pat.c @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: pat.c 1.6 2004/01/25 14:07:24 kls Exp $ + * $Id: pat.c 1.7 2004/01/25 15:12:53 kls Exp $ */ #include "pat.h" @@ -109,7 +109,7 @@ bool cCaDescriptors::Is(int Source, int Transponder, int ServiceId) return source == Source && transponder == Transponder && serviceId == ServiceId; } -bool cCaDescriptors::Is(cCaDescriptors * CaDescriptors) +bool cCaDescriptors::Is(cCaDescriptors *CaDescriptors) { return Is(CaDescriptors->source, CaDescriptors->transponder, CaDescriptors->serviceId); } @@ -324,6 +324,8 @@ void cPatFilter::Process(u_short Pid, u_char Tid, const u_char *Data, int Length int Ppid = pmt.getPCRPid(); int Apids[MAXAPIDS] = { 0 }; int Dpids[MAXAPIDS] = { 0 }; + char ALangs[MAXAPIDS][4]; + char DLangs[MAXAPIDS][4]; int Tpid = 0; int NumApids = 0; int NumDpids = 0; @@ -337,28 +339,59 @@ void cPatFilter::Process(u_short Pid, u_char Tid, const u_char *Data, int Length case 3: // STREAMTYPE_11172_AUDIO case 4: // STREAMTYPE_13818_AUDIO { - if (NumApids < MAXAPIDS) - Apids[NumApids++] = stream.getPid(); + if (NumApids < MAXAPIDS) { + Apids[NumApids] = stream.getPid(); + *ALangs[NumApids] = 0; + SI::Descriptor *d; + for (SI::Loop::Iterator it; (d = stream.streamDescriptors.getNext(it)); ) { + switch (d->getDescriptorTag()) { + case SI::ISO639LanguageDescriptorTag: { + SI::ISO639LanguageDescriptor *ld = (SI::ISO639LanguageDescriptor *)d; + if (*ld->languageCode != '-') { // some use "---" to indicate "none" + strn0cpy(ALangs[NumApids], I18nNormalizeLanguageCode(ld->languageCode), 4); + ALangs[NumApids][4] = 0; + } + } + break; + default: ; + } + delete d; + } + NumApids++; + } } break; case 5: // STREAMTYPE_13818_PRIVATE case 6: // STREAMTYPE_13818_PES_PRIVATE //XXX case 8: // STREAMTYPE_13818_DSMCC { + int dpid = 0; + char lang[4] = { 0 }; SI::Descriptor *d; for (SI::Loop::Iterator it; (d = stream.streamDescriptors.getNext(it)); ) { switch (d->getDescriptorTag()) { case SI::AC3DescriptorTag: - if (NumDpids < MAXAPIDS) - Dpids[NumDpids++] = stream.getPid(); + dpid = stream.getPid(); break; case SI::TeletextDescriptorTag: Tpid = stream.getPid(); break; + case SI::ISO639LanguageDescriptorTag: { + SI::ISO639LanguageDescriptor *ld = (SI::ISO639LanguageDescriptor *)d; + strn0cpy(lang, I18nNormalizeLanguageCode(ld->languageCode), 4); + } + break; default: ; } delete d; } + if (dpid) { + if (NumDpids < MAXAPIDS) { + Dpids[NumDpids] = dpid; + strn0cpy(DLangs[NumDpids], lang, 4); + NumDpids++; + } + } } break; //default: printf("PID: %5d %5d %2d %3d %3d\n", pmt.getServiceId(), stream.getPid(), stream.getStreamType(), pmt.getVersionNumber(), Channel->Number());//XXX @@ -369,7 +402,7 @@ void cPatFilter::Process(u_short Pid, u_char Tid, const u_char *Data, int Length } } if (Setup.UpdateChannels >= 2) { - Channel->SetPids(Vpid, Vpid ? Ppid : 0, Apids[0], Apids[1], Dpids[0], Dpids[1], Tpid); + Channel->SetPids(Vpid, Vpid ? Ppid : 0, Apids, ALangs, Dpids, DLangs, Tpid); Channel->SetCaIds(CaDescriptors->CaIds()); } Channel->SetCaDescriptors(CaDescriptorHandler.AddCaDescriptors(CaDescriptors)); diff --git a/vdr.5 b/vdr.5 index 10597f55..7f8626ec 100644 --- a/vdr.5 +++ b/vdr.5 @@ -8,7 +8,7 @@ .\" License as specified in the file COPYING that comes with the .\" vdr distribution. .\" -.\" $Id: vdr.5 1.22 2004/01/05 15:26:33 kls Exp $ +.\" $Id: vdr.5 1.23 2004/01/25 14:44:59 kls Exp $ .\" .TH vdr 5 "1 Jun 2003" "1.2.0" "Video Disk Recorder Files" .SH NAME @@ -117,10 +117,18 @@ plus sign, as in .B ...:164+17:... .TP .B APID -The audio PID (either one number, or two, separated by a comma). +The audio PID (either one number, or several, separated by commas). If this channel also carries Dolby Digital sound, the Dolby PIDs follow the audio PIDs, separated by a semicolon, as in + .B ...:101,102;103,104:... + +If certain audio PIDs broadcast in specific languages, the language +codes for these can be appended to the individual audio or Dolby PID, separated +by an '=' sign, as in + +.B ...:101=deu,102=eng;103=deu,104=eng:... + .TP .B TPID The teletext PID.