summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CONTRIBUTORS1
-rw-r--r--HISTORY2
-rw-r--r--MANUAL13
-rw-r--r--config.c38
-rw-r--r--config.h6
-rw-r--r--eit.c47
-rw-r--r--epg.c18
-rw-r--r--epg.h4
-rw-r--r--i18n.c92
-rw-r--r--i18n.h5
-rw-r--r--menu.c70
11 files changed, 278 insertions, 18 deletions
diff --git a/CONTRIBUTORS b/CONTRIBUTORS
index e04e477b..5a5bc701 100644
--- a/CONTRIBUTORS
+++ b/CONTRIBUTORS
@@ -639,6 +639,7 @@ Teemu Rantanen <tvr@iki.fi>
for fixing faulty calculation of section length in eit.c
for reporting a problem in calculation of channel ids for tv stations that use
the undefined NID value 0
+ for adding EPG preferred languages
Jan Ekholm <chakie@infa.abo.fi>
for adding/improving some Swedish language OSD texts
diff --git a/HISTORY b/HISTORY
index e2033377..5d4e291c 100644
--- a/HISTORY
+++ b/HISTORY
@@ -2555,3 +2555,5 @@ Video Disk Recorder Revision History
- Changed calculation of channel ids to make it work for tv stations that use
the undefined NID value 0 (thanks to Teemu Rantanen for reporting this one).
- Enhanced the SDT filter to handle multi part sections.
+- Added support for selecting preferred EPG languages (based upon a patch by
+ Teemu Rantanen).
diff --git a/MANUAL b/MANUAL
index 9b08914e..4584f161 100644
--- a/MANUAL
+++ b/MANUAL
@@ -482,6 +482,19 @@ Version 1.2
be taken. Note that in order to set the system time from
the transponder data the option "Set system time" must also
be enabled.
+ Preferred languages = 0
+ Some tv stations broadcast their EPG data in various
+ different languages. This option allows you to define
+ which language(s) you prefer in such cases. By default,
+ or if none of the preferred languages is broadcast, any
+ language will be accepted and the EPG data will be
+ displayed in the first language received from the data
+ stream. If this option is set to a non-zero value, the
+ menu page will contain that many "Preferred language"
+ options which allow you to select the individual preferred
+ languages. If an actual EPG data record is received in
+ different languages, the preferred languages are checked
+ in the given order to decide which one to take.
DVB:
diff --git a/config.c b/config.c
index 12172900..094d632a 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.118 2004/01/05 11:45:40 kls Exp $
+ * $Id: config.c 1.119 2004/01/06 17:09:54 kls Exp $
*/
#include "config.h"
@@ -259,6 +259,7 @@ cSetup::cSetup(void)
TimeTransponder = 0;
MarginStart = 2;
MarginStop = 10;
+ EPGLanguages[0] = -1;
EPGScanTimeout = 5;
EPGBugfixLevel = 2;
SVDRPTimeout = 300;
@@ -395,6 +396,39 @@ bool cSetup::ParseCaCaps(const char *Value)
return false;
}
+void cSetup::StoreLanguages(const char *Name, int *Values)
+{
+ char buffer[I18nNumLanguages * 4];
+ char *q = buffer;
+ for (int i = 0; i < I18nNumLanguages; i++) {
+ if (Values[i] < 0)
+ break;
+ const char *s = I18nLanguageAbbreviation(Values[i]);
+ if (s) {
+ if (q > buffer)
+ *q++ = ' ';
+ strncpy(q, s, 3);
+ q += 3;
+ }
+ }
+ *q = 0;
+ Store(Name, buffer);
+}
+
+bool cSetup::ParseLanguages(const char *Value, int *Values)
+{
+ int n = 0;
+ while (Value && *Value && n < I18nNumLanguages) {
+ int i = I18nLanguageIndex(Value);
+ if (i >= 0)
+ Values[n++] = i;
+ if ((Value = strchr(Value, ' ')) != NULL)
+ Value++;
+ }
+ Values[n] = -1;
+ return true;
+}
+
bool cSetup::Parse(const char *Name, const char *Value)
{
if (!strcasecmp(Name, "OSDLanguage")) OSDLanguage = atoi(Value);
@@ -412,6 +446,7 @@ bool cSetup::Parse(const char *Name, const char *Value)
else if (!strcasecmp(Name, "TimeTransponder")) TimeTransponder = atoi(Value);
else if (!strcasecmp(Name, "MarginStart")) MarginStart = atoi(Value);
else if (!strcasecmp(Name, "MarginStop")) MarginStop = atoi(Value);
+ else if (!strcasecmp(Name, "EPGLanguages")) return ParseLanguages(Value, EPGLanguages);
else if (!strcasecmp(Name, "EPGScanTimeout")) EPGScanTimeout = atoi(Value);
else if (!strcasecmp(Name, "EPGBugfixLevel")) EPGBugfixLevel = atoi(Value);
else if (!strcasecmp(Name, "SVDRPTimeout")) SVDRPTimeout = atoi(Value);
@@ -463,6 +498,7 @@ bool cSetup::Save(void)
Store("TimeTransponder", TimeTransponder);
Store("MarginStart", MarginStart);
Store("MarginStop", MarginStop);
+ StoreLanguages("EPGLanguages", EPGLanguages);
Store("EPGScanTimeout", EPGScanTimeout);
Store("EPGBugfixLevel", EPGBugfixLevel);
Store("SVDRPTimeout", SVDRPTimeout);
diff --git a/config.h b/config.h
index db4769cd..22623e73 100644
--- a/config.h
+++ b/config.h
@@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
- * $Id: config.h 1.181 2004/01/05 11:31:54 kls Exp $
+ * $Id: config.h 1.182 2004/01/06 16:47:41 kls Exp $
*/
#ifndef __CONFIG_H
@@ -17,6 +17,7 @@
#include <time.h>
#include <unistd.h>
#include "device.h"
+#include "i18n.h"
#include "tools.h"
#define VDRVERSION "1.3.1"
@@ -195,6 +196,8 @@ class cSetup : public cConfig<cSetupLine> {
private:
void StoreCaCaps(const char *Name);
bool ParseCaCaps(const char *Value);
+ void StoreLanguages(const char *Name, int *Values);
+ bool ParseLanguages(const char *Value, int *Values);
bool Parse(const char *Name, const char *Value);
cSetupLine *Get(const char *Name, const char *Plugin = NULL);
void Store(const char *Name, const char *Value, const char *Plugin = NULL, bool AllowMultiple = false);
@@ -216,6 +219,7 @@ public:
int SetSystemTime;
int TimeTransponder;
int MarginStart, MarginStop;
+ int EPGLanguages[I18nNumLanguages + 1];
int EPGScanTimeout;
int EPGBugfixLevel;
int SVDRPTimeout;
diff --git a/eit.c b/eit.c
index 45a4d800..d71cad82 100644
--- a/eit.c
+++ b/eit.c
@@ -8,11 +8,12 @@
* Robert Schneider <Robert.Schneider@web.de> and Rolf Hakenes <hakenes@hippomi.de>.
* Adapted to 'libsi' for VDR 1.3.0 by Marcel Wiesweg <marcel.wiesweg@gmx.de>.
*
- * $Id: eit.c 1.84 2004/01/02 22:27:29 kls Exp $
+ * $Id: eit.c 1.85 2004/01/09 15:44:43 kls Exp $
*/
#include "eit.h"
#include "epg.h"
+#include "i18n.h"
#include "libsi/section.h"
#include "libsi/descriptor.h"
@@ -88,19 +89,36 @@ cEIT::cEIT(cSchedules *Schedules, int Source, u_char Tid, const u_char *Data)
pEvent->SetTableID(Tid);
pEvent->SetEventID(SiEitEvent.getEventId()); // unfortunately some stations use different event ids for the same event in different tables :-(
+ int LanguagePreferenceShort = -1;
+ int LanguagePreferenceExt = -1;
+ bool UseExtendedEventDescriptor = false;
SI::Descriptor *d;
- SI::ExtendedEventDescriptors exGroup;
- char text[256];
+ SI::ExtendedEventDescriptors *ExtendedEventDescriptors = NULL;
+ SI::ShortEventDescriptor *ShortEventDescriptor = NULL;
for (SI::Loop::Iterator it2; (d = SiEitEvent.eventDescriptors.getNext(it2)); ) {
switch (d->getDescriptorTag()) {
- case SI::ExtendedEventDescriptorTag:
- exGroup.Add((SI::ExtendedEventDescriptor *)d);
- d = NULL; //so that it is not deleted
+ case SI::ExtendedEventDescriptorTag: {
+ SI::ExtendedEventDescriptor *eed = (SI::ExtendedEventDescriptor *)d;
+ if (I18nIsPreferredLanguage(Setup.EPGLanguages, I18nLanguageIndex(eed->languageCode), LanguagePreferenceExt) || !ExtendedEventDescriptors) {
+ delete ExtendedEventDescriptors;
+ ExtendedEventDescriptors = new SI::ExtendedEventDescriptors;
+ UseExtendedEventDescriptor = true;
+ }
+ if (UseExtendedEventDescriptor) {
+ ExtendedEventDescriptors->Add(eed);
+ d = NULL; // so that it is not deleted
+ }
+ if (eed->getDescriptorNumber() == eed->getLastDescriptorNumber())
+ UseExtendedEventDescriptor = false;
+ }
break;
case SI::ShortEventDescriptorTag: {
SI::ShortEventDescriptor *sed = (SI::ShortEventDescriptor *)d;
- pEvent->SetTitle(sed->name.getText(text));
- pEvent->SetShortText(sed->text.getText(text));
+ if (I18nIsPreferredLanguage(Setup.EPGLanguages, I18nLanguageIndex(sed->languageCode), LanguagePreferenceShort) || !ShortEventDescriptor) {
+ delete ShortEventDescriptor;
+ ShortEventDescriptor = sed;
+ d = NULL; // so that it is not deleted
+ }
}
break;
case SI::ContentDescriptorTag:
@@ -126,9 +144,18 @@ cEIT::cEIT(cSchedules *Schedules, int Source, u_char Tid, const u_char *Data)
}
if (!rEvent) {
- char buffer[exGroup.getMaximumTextLength()];
- pEvent->SetDescription(exGroup.getText(buffer));
+ if (ShortEventDescriptor) {
+ char buffer[256];
+ pEvent->SetTitle(ShortEventDescriptor->name.getText(buffer));
+ pEvent->SetShortText(ShortEventDescriptor->text.getText(buffer));
+ }
+ if (ExtendedEventDescriptors) {
+ char buffer[ExtendedEventDescriptors->getMaximumTextLength()];
+ pEvent->SetDescription(ExtendedEventDescriptors->getText(buffer));
+ }
}
+ delete ExtendedEventDescriptors;
+ delete ShortEventDescriptor;
pEvent->SetStartTime(SiEitEvent.getStartTime());
pEvent->SetDuration(SiEitEvent.getDuration());
diff --git a/epg.c b/epg.c
index 69130145..19f1c7f4 100644
--- a/epg.c
+++ b/epg.c
@@ -7,7 +7,7 @@
* Original version (as used in VDR before 1.3.0) written by
* Robert Schneider <Robert.Schneider@web.de> and Rolf Hakenes <hakenes@hippomi.de>.
*
- * $Id: epg.c 1.3 2004/01/04 15:20:42 kls Exp $
+ * $Id: epg.c 1.4 2004/01/09 15:22:18 kls Exp $
*/
#include "epg.h"
@@ -486,6 +486,12 @@ bool cSchedule::SetFollowingEvent(cEvent *Event)
return true;
}
+void cSchedule::ResetVersions(void)
+{
+ for (cEvent *p = events.First(); p; p = events.Next(p))
+ p->SetVersion(0xFF);
+}
+
void cSchedule::Cleanup(void)
{
Cleanup(time(NULL));
@@ -613,6 +619,16 @@ void cSchedules::Cleanup(bool Force)
}
}
+void cSchedules::ResetVersions(void)
+{
+ cSchedulesLock SchedulesLock(true);
+ cSchedules *s = (cSchedules *)Schedules(SchedulesLock);
+ if (s) {
+ for (cSchedule *Schedule = s->First(); Schedule; Schedule = s->Next(Schedule))
+ Schedule->ResetVersions();
+ }
+}
+
bool cSchedules::ClearAll(void)
{
cSchedulesLock SchedulesLock(true, 1000);
diff --git a/epg.h b/epg.h
index 19332a59..409968ac 100644
--- a/epg.h
+++ b/epg.h
@@ -7,7 +7,7 @@
* Original version (as used in VDR before 1.3.0) written by
* Robert Schneider <Robert.Schneider@web.de> and Rolf Hakenes <hakenes@hippomi.de>.
*
- * $Id: epg.h 1.3 2004/01/03 17:00:25 kls Exp $
+ * $Id: epg.h 1.4 2004/01/09 15:21:05 kls Exp $
*/
#ifndef __EPG_H
@@ -84,6 +84,7 @@ public:
tChannelID ChannelID(void) const { return channelID; }
bool SetPresentEvent(cEvent *Event);
bool SetFollowingEvent(cEvent *Event);
+ void ResetVersions(void);
void Cleanup(time_t Time);
void Cleanup(void);
cEvent *AddEvent(cEvent *Event);
@@ -122,6 +123,7 @@ public:
///< time the returned cSchedules is accessed. Once the cSchedules is no
///< longer used, the cSchedulesLock must be destroyed.
static void Cleanup(bool Force = false);
+ static void ResetVersions(void);
static bool ClearAll(void);
static bool Dump(FILE *f, const char *Prefix = "");
static bool Read(FILE *f = NULL);
diff --git a/i18n.c b/i18n.c
index 3b6c0bcf..a9009446 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.138 2004/01/05 11:56:24 kls Exp $
+ * $Id: i18n.c 1.139 2004/01/09 15:48:03 kls Exp $
*
* Translations provided by:
*
@@ -111,6 +111,24 @@ const tI18nPhrase Phrases[] = {
"iso8859-1",
"iso8859-1",
},
+ // The 3-letter names of the language (this MUST be the third phrase!):
+ { "eng",
+ "deu,ger",
+ "slv",
+ "ita",
+ "dut,nla",
+ "por",
+ "fra,fre",
+ "nor",
+ "fin",
+ "pol",
+ "esl,spa",
+ "ell,gre",
+ "sve,swe",
+ "ron,rum",
+ "hun",
+ "cat,cln",
+ },
// Menu titles:
{ "VDR",
"VDR",
@@ -2227,6 +2245,40 @@ const tI18nPhrase Phrases[] = {
"Idöhöz tartozó Transponder",
"Usar el temps del múltiplex",
},
+ { "Setup.EPG$Preferred languages",
+ "Bevorzugte Sprachen",
+ "",// TODO
+ "",// TODO
+ "",// TODO
+ "",// TODO
+ "",// TODO
+ "",// TODO
+ "Suosikkikielet",
+ "",// TODO
+ "",// TODO
+ "",// TODO
+ "",// TODO
+ "",// TODO
+ "",// TODO
+ "",// TODO
+ },
+ { "Setup.EPG$Preferred language",
+ "Bevorzugte Sprache",
+ "",// TODO
+ "",// TODO
+ "",// TODO
+ "",// TODO
+ "",// TODO
+ "",// TODO
+ "Suosikkikieli",
+ "",// TODO
+ "",// TODO
+ "",// TODO
+ "",// TODO
+ "",// TODO
+ "",// TODO
+ "",// TODO
+ },
{ "Setup.DVB$Primary DVB interface",
"Primäres DVB Interface",
"Primarna naprava",
@@ -3920,3 +3972,41 @@ const char * const * I18nCharSets(void)
{
return &Phrases[1][0];
}
+
+const char * I18nLanguageAbbreviation(int Index)
+{
+ return Index < I18nNumLanguages ? Phrases[2][Index] : NULL;
+}
+
+int I18nLanguageIndex(const char Code[3])
+{
+ char s[4];
+ memcpy(s, Code, 3);
+ s[3] = 0;
+ for (int i = 0; i < I18nNumLanguages; i++) {
+ if (strcasestr(Phrases[2][i], s))
+ return i;
+ }
+ //dsyslog("unknown language code: '%s'", s);
+ return -1;
+}
+
+bool I18nIsPreferredLanguage(int *PreferredLanguages, int LanguageIndex, int &OldPreference)
+{
+ for (int i = 0; i < I18nNumLanguages; i++) {
+ if (PreferredLanguages[i] < 0)
+ break; // the language is not a preferred one
+ if (PreferredLanguages[i] == LanguageIndex) {
+ if (OldPreference < 0 || i < OldPreference) {
+ OldPreference = i;
+ return true;
+ }
+ break;
+ }
+ }
+ if (OldPreference < 0) {
+ OldPreference = I18nNumLanguages; // higher than the maximum possible value
+ return true; // if we don't find a preferred one, we take the first one
+ }
+ return false;
+}
diff --git a/i18n.h b/i18n.h
index 44cf1905..8c882140 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.7 2003/10/19 15:02:05 kls Exp $
+ * $Id: i18n.h 1.8 2004/01/06 15:56:53 kls Exp $
*/
#ifndef __I18N_H
@@ -22,6 +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);
+int I18nLanguageIndex(const char Code[3]);
+bool I18nIsPreferredLanguage(int *PreferredLanguages, int LanguageIndex, int &OldPreference);
#ifdef PLUGIN_NAME_I18N
#define tr(s) I18nTranslate(s, PLUGIN_NAME_I18N)
diff --git a/menu.c b/menu.c
index 6e2c17be..275544f4 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.277 2004/01/05 11:51:33 kls Exp $
+ * $Id: menu.c 1.278 2004/01/09 15:42:59 kls Exp $
*/
#include "menu.h"
@@ -2029,17 +2029,83 @@ eOSState cMenuSetupOSD::ProcessKey(eKeys Key)
// --- cMenuSetupEPG ---------------------------------------------------------
class cMenuSetupEPG : public cMenuSetupBase {
+private:
+ int originalNumLanguages;
+ int numLanguages;
+ void Setup(void);
public:
cMenuSetupEPG(void);
+ virtual eOSState ProcessKey(eKeys Key);
};
cMenuSetupEPG::cMenuSetupEPG(void)
{
+ for (numLanguages = 0; numLanguages < I18nNumLanguages && data.EPGLanguages[numLanguages] >= 0; numLanguages++)
+ ;
+ originalNumLanguages = numLanguages;
SetSection(tr("EPG"));
+ Setup();
+}
+
+void cMenuSetupEPG::Setup(void)
+{
+ int current = Current();
+
+ Clear();
+
Add(new cMenuEditIntItem( tr("Setup.EPG$EPG scan timeout (h)"), &data.EPGScanTimeout));
Add(new cMenuEditIntItem( tr("Setup.EPG$EPG bugfix level"), &data.EPGBugfixLevel, 0, MAXEPGBUGFIXLEVEL));
Add(new cMenuEditBoolItem(tr("Setup.EPG$Set system time"), &data.SetSystemTime));
- Add(new cMenuEditTranItem(tr("Setup.EPG$Use time from transponder"), &data.TimeTransponder));
+ if (data.SetSystemTime)
+ Add(new cMenuEditTranItem(tr("Setup.EPG$Use time from transponder"), &data.TimeTransponder));
+ Add(new cMenuEditIntItem( tr("Setup.EPG$Preferred languages"), &numLanguages, 0, I18nNumLanguages));
+ for (int i = 0; i < numLanguages; i++)
+ Add(new cMenuEditStraItem(tr("Setup.EPG$Preferred language"), &data.EPGLanguages[i], I18nNumLanguages, I18nLanguages()));
+
+ SetCurrent(Get(current));
+ Display();
+}
+
+eOSState cMenuSetupEPG::ProcessKey(eKeys Key)
+{
+ int oldnumLanguages = numLanguages;
+ int oldSetSystemTime = data.SetSystemTime;
+
+ eOSState state = cMenuSetupBase::ProcessKey(Key);
+ if (Key == kOk) {
+ bool Modified = numLanguages != originalNumLanguages;
+ if (!Modified) {
+ for (int i = 0; i < numLanguages; i++) {
+ if (data.EPGLanguages[i] != ::Setup.EPGLanguages[i]) {
+ Modified = true;
+ break;
+ }
+ }
+ }
+ if (Modified)
+ cSchedules::ResetVersions();
+ }
+ else if (Key != kNone) {
+ if (numLanguages != oldnumLanguages || data.SetSystemTime != oldSetSystemTime) {
+ for (int i = oldnumLanguages; i < numLanguages; i++) {
+ data.EPGLanguages[i] = 0;
+ for (int l = 0; l < I18nNumLanguages; l++) {
+ int k;
+ for (k = 0; k < oldnumLanguages; k++) {
+ if (data.EPGLanguages[k] == l)
+ break;
+ }
+ if (k >= oldnumLanguages) {
+ data.EPGLanguages[i] = l;
+ break;
+ }
+ }
+ }
+ data.EPGLanguages[numLanguages] = -1;
+ Setup();
+ }
+ }
+ return state;
}
// --- cMenuSetupDVB ---------------------------------------------------------