diff -Nru vdr-1.6.0-vanilla/eit.c vdr-1.6.0-parentalrating-content/eit.c --- vdr-1.6.0-vanilla/eit.c 2008-03-27 21:43:25.000000000 +0200 +++ vdr-1.6.0-parentalrating-content/eit.c 2008-03-27 21:51:24.000000000 +0200 @@ -142,9 +142,41 @@ } } break; - case SI::ContentDescriptorTag: + case SI::ContentDescriptorTag: { + int NumContents = 0; + uchar Contents[MAXEVCONTENTS + 1] = { 0 }; + SI::ContentDescriptor *cd = (SI::ContentDescriptor *)d; + SI::ContentDescriptor::Nibble Nibble; + for (SI::Loop::Iterator it3; cd->nibbleLoop.getNext(Nibble, it3); ) { + if (NumContents < MAXEVCONTENTS) { + Contents[NumContents] = ((Nibble.getContentNibbleLevel1() & 0xF) << 4) | (Nibble.getContentNibbleLevel2() & 0xF); + NumContents++; + } + } + pEvent->SetContents(Contents); + } break; - case SI::ParentalRatingDescriptorTag: + case SI::ParentalRatingDescriptorTag: { + int LanguagePreferenceRating = -1; + SI::ParentalRatingDescriptor *prd = (SI::ParentalRatingDescriptor *)d; + SI::ParentalRatingDescriptor::Rating Rating; + for (SI::Loop::Iterator it3; prd->ratingLoop.getNext(Rating, it3); ) { + if (I18nIsPreferredLanguage(Setup.EPGLanguages, Rating.languageCode, LanguagePreferenceRating)) { + int rate = (Rating.getRating() & 0xFF); + switch (rate) { + case 0x01 ... 0x0F: // minimum age = rating + 3 years + rate += 3; + break; + case 0: // undefined + case 0x10 ... 0xFF: // defined by the broadcaster + default: + rate = 0; + break; + } + pEvent->SetParentalRating(rate); + } + } + } break; case SI::PDCDescriptorTag: { SI::PDCDescriptor *pd = (SI::PDCDescriptor *)d; diff -Nru vdr-1.6.0-vanilla/epg.c vdr-1.6.0-parentalrating-content/epg.c --- vdr-1.6.0-vanilla/epg.c 2008-03-27 21:43:25.000000000 +0200 +++ vdr-1.6.0-parentalrating-content/epg.c 2008-03-27 21:51:24.000000000 +0200 @@ -112,6 +112,9 @@ components = NULL; startTime = 0; duration = 0; + for (int i = 0; i < MAXEVCONTENTS; i++) + contents[i] = 0; + parentalRating = 0; vps = 0; SetSeen(); } @@ -200,6 +203,17 @@ duration = Duration; } +void cEvent::SetContents(uchar *Contents) +{ + for (int i = 0; i < MAXEVCONTENTS; i++) + contents[i] = Contents[i]; +} + +void cEvent::SetParentalRating(uchar ParentalRating) +{ + parentalRating = ParentalRating; +} + void cEvent::SetVps(time_t Vps) { vps = Vps; @@ -255,6 +269,338 @@ return buf; } +cString cEvent::GetContentsString(int i) const +{ + cString str(""); + switch (contents[i] & 0xF0) { + case EVCONTENTMASK_MOVIEDRAMA: + switch (contents[i] & 0x0F) { + default: + case 0x00: + str = cString(tr("Content$Movie/Drama")); + break; + case 0x01: + str = cString(tr("Content$Detective/Thriller")); + break; + case 0x02: + str = cString(tr("Content$Adventure/Western/War")); + break; + case 0x03: + str = cString(tr("Content$Science Fiction/Fantasy/Horror")); + break; + case 0x04: + str = cString(tr("Content$Comedy")); + break; + case 0x05: + str = cString(tr("Content$Soap/Melodrama/Folkloric")); + break; + case 0x06: + str = cString(tr("Content$Romance")); + break; + case 0x07: + str = cString(tr("Content$Serious/Classical/Religious/Historical Movie/Drama")); + break; + case 0x08: + str = cString(tr("Content$Adult Movie/Drama")); + break; + } + break; + + case EVCONTENTMASK_NEWSCURRENTAFFAIRS: + switch (contents[i] & 0x0F) { + default: + case 0x00: + str = cString(tr("Content$News/Current Affairs")); + break; + case 0x01: + str = cString(tr("Content$News/Weather Report")); + break; + case 0x02: + str = cString(tr("Content$News Magazine")); + break; + case 0x03: + str = cString(tr("Content$Documentary")); + break; + case 0x04: + str = cString(tr("Content$Discussion/Inverview/Debate")); + break; + } + break; + + case EVCONTENTMASK_SHOW: + switch (contents[i] & 0x0F) { + default: + case 0x00: + str = cString(tr("Content$Show/Game Show")); + break; + case 0x01: + str = cString(tr("Content$Game Show/Quiz/Contest")); + break; + case 0x02: + str = cString(tr("Content$Variety Show")); + break; + case 0x03: + str = cString(tr("Content$Talk Show")); + break; + } + break; + + case EVCONTENTMASK_SPORTS: + switch (contents[i] & 0x0F) { + default: + case 0x00: + str = cString(tr("Content$Sports")); + break; + case 0x01: + str = cString(tr("Content$Special Event")); + break; + case 0x02: + str = cString(tr("Content$Sport Magazine")); + break; + case 0x03: + str = cString(tr("Content$Football")); + break; + case 0x04: + str = cString(tr("Content$Tennis/Squash")); + break; + case 0x05: + str = cString(tr("Content$Team Sports")); + break; + case 0x06: + str = cString(tr("Content$Athletics")); + break; + case 0x07: + str = cString(tr("Content$Motor Sport")); + break; + case 0x08: + str = cString(tr("Content$Water Sport")); + break; + case 0x09: + str = cString(tr("Content$Winter Sports")); + break; + case 0x0A: + str = cString(tr("Content$Equestrian")); + break; + case 0x0B: + str = cString(tr("Content$Martial Sports")); + break; + } + break; + + case EVCONTENTMASK_CHILDRENYOUTH: + switch (contents[i] & 0x0F) { + default: + case 0x00: + str = cString(tr("Content$Children's/Youth Programmes")); + break; + case 0x01: + str = cString(tr("Content$Pre-school Children's Programmes")); + break; + case 0x02: + str = cString(tr("Content$Entertainment Programmes for 6 to 14")); + break; + case 0x03: + str = cString(tr("Content$Entertainment Programmes for 10 to 16")); + break; + case 0x04: + str = cString(tr("Content$Informational/Educational/School Programme")); + break; + case 0x05: + str = cString(tr("Content$Cartoons/Puppets")); + break; + } + break; + + case EVCONTENTMASK_MUSICBALLETDANCE: + switch (contents[i] & 0x0F) { + default: + case 0x00: + str = cString(tr("Content$Music/Ballet/Dance")); + break; + case 0x01: + str = cString(tr("Content$Rock/Pop")); + break; + case 0x02: + str = cString(tr("Content$Serious/Classical Music")); + break; + case 0x03: + str = cString(tr("Content$Folk/Tradional Music")); + break; + case 0x04: + str = cString(tr("Content$Jazz")); + break; + case 0x05: + str = cString(tr("Content$Musical/Opera")); + break; + case 0x06: + str = cString(tr("Content$Ballet")); + break; + } + break; + + case EVCONTENTMASK_ARTSCULTURE: + switch (contents[i] & 0x0F) { + default: + case 0x00: + str = cString(tr("Content$Arts/Culture")); + break; + case 0x01: + str = cString(tr("Content$Performing Arts")); + break; + case 0x02: + str = cString(tr("Content$Fine Arts")); + break; + case 0x03: + str = cString(tr("Content$Religion")); + break; + case 0x04: + str = cString(tr("Content$Popular Culture/Traditional Arts")); + break; + case 0x05: + str = cString(tr("Content$Literature")); + break; + case 0x06: + str = cString(tr("Content$Film/Cinema")); + break; + case 0x07: + str = cString(tr("Content$Experimental Film/Video")); + break; + case 0x08: + str = cString(tr("Content$Broadcasting/Press")); + break; + case 0x09: + str = cString(tr("Content$New Media")); + break; + case 0x0A: + str = cString(tr("Content$Arts/Culture Magazines")); + break; + case 0x0B: + str = cString(tr("Content$Fashion")); + break; + } + break; + + case EVCONTENTMASK_SOCIALPOLITICALECONOMICS: + switch (contents[i] & 0x0F) { + default: + case 0x00: + str = cString(tr("Content$Social/Political/Economics")); + break; + case 0x01: + str = cString(tr("Content$Magazines/Reports/Documentary")); + break; + case 0x02: + str = cString(tr("Content$Economics/Social Advisory")); + break; + case 0x03: + str = cString(tr("Content$Remarkable People")); + break; + } + break; + + case EVCONTENTMASK_EDUCATIONALSCIENCE: + switch (contents[i] & 0x0F) { + default: + case 0x00: + str = cString(tr("Content$Education/Science/Factual")); + break; + case 0x01: + str = cString(tr("Content$Nature/Animals/Environment")); + break; + case 0x02: + str = cString(tr("Content$Technology/Natural Sciences")); + break; + case 0x03: + str = cString(tr("Content$Medicine/Physiology/Psychology")); + break; + case 0x04: + str = cString(tr("Content$Foreign Countries/Expeditions")); + break; + case 0x05: + str = cString(tr("Content$Social/Spiritual Sciences")); + break; + case 0x06: + str = cString(tr("Content$Further Education")); + break; + case 0x07: + str = cString(tr("Content$Languages")); + break; + } + break; + + case EVCONTENTMASK_LEISUREHOBBIES: + switch (contents[i] & 0x0F) { + default: + case 0x00: + str = cString(tr("Content$Leisure/Hobbies")); + break; + case 0x01: + str = cString(tr("Content$Tourism/Travel")); + break; + case 0x02: + str = cString(tr("Content$Handicraft")); + break; + case 0x03: + str = cString(tr("Content$Motoring")); + break; + case 0x04: + str = cString(tr("Content$Fitness & Health")); + break; + case 0x05: + str = cString(tr("Content$Cooking")); + break; + case 0x06: + str = cString(tr("Content$Advertisement/Shopping")); + break; + case 0x07: + str = cString(tr("Content$Gardening")); + break; + } + break; + + case EVCONTENTMASK_SPECIAL: + switch (contents[i] & 0x0F) { + case 0x00: + str = cString(tr("Content$Original Language")); + break; + case 0x01: + str = cString(tr("Content$Black & White")); + break; + case 0x02: + str = cString(tr("Content$Unpublished")); + break; + case 0x03: + str = cString(tr("Content$Live Broadcast")); + break; + default: + str = cString(tr("Content$Special Characteristics")); + break; + } + break; + + case EVCONTENTMASK_USERDEFINED: + switch (contents[i] & 0x0F) { + case 0x00: + str = cString(tr("Content$Drama")); // UK Freeview + break; + default: + break; + } + break; + + default: + break; + } + return str; +} + +cString cEvent::GetParentalRatingString(void) const +{ + if (parentalRating > 0) + return cString::sprintf(tr("Suitable for those aged %d and over"), parentalRating); + return NULL; +} + void cEvent::Dump(FILE *f, const char *Prefix, bool InfoOnly) const { if (InfoOnly || startTime + duration + Setup.EPGLinger * 60 >= time(NULL)) { diff -Nru vdr-1.6.0-vanilla/epg.h vdr-1.6.0-parentalrating-content/epg.h --- vdr-1.6.0-vanilla/epg.h 2008-03-27 21:43:25.000000000 +0200 +++ vdr-1.6.0-parentalrating-content/epg.h 2008-03-27 21:51:24.000000000 +0200 @@ -50,6 +50,20 @@ typedef u_int32_t tEventID; +#define MAXEVCONTENTS 4 +#define EVCONTENTMASK_MOVIEDRAMA 0x10 +#define EVCONTENTMASK_NEWSCURRENTAFFAIRS 0x20 +#define EVCONTENTMASK_SHOW 0x30 +#define EVCONTENTMASK_SPORTS 0x40 +#define EVCONTENTMASK_CHILDRENYOUTH 0x50 +#define EVCONTENTMASK_MUSICBALLETDANCE 0x60 +#define EVCONTENTMASK_ARTSCULTURE 0x70 +#define EVCONTENTMASK_SOCIALPOLITICALECONOMICS 0x80 +#define EVCONTENTMASK_EDUCATIONALSCIENCE 0x90 +#define EVCONTENTMASK_LEISUREHOBBIES 0xA0 +#define EVCONTENTMASK_SPECIAL 0xB0 +#define EVCONTENTMASK_USERDEFINED 0xF0 + class cEvent : public cListObject { friend class cSchedule; private: @@ -64,6 +78,8 @@ cComponents *components; // The stream components of this event time_t startTime; // Start time of this event int duration; // Duration of this event in seconds + uchar contents[MAXEVCONTENTS + 1]; // Contents of this event; list is zero-terminated + uchar parentalRating; // Parental rating of this event time_t vps; // Video Programming Service timestamp (VPS, aka "Programme Identification Label", PIL) time_t seen; // When this event was last seen in the data stream public: @@ -83,6 +99,8 @@ time_t StartTime(void) const { return startTime; } time_t EndTime(void) const { return startTime + duration; } int Duration(void) const { return duration; } + uchar Contents(int i = 0) const { return (0 <= i && i < MAXEVCONTENTS) ? contents[i] : 0; } + uchar ParentalRating(void) const { return parentalRating; } time_t Vps(void) const { return vps; } time_t Seen(void) const { return seen; } bool SeenWithin(int Seconds) const { return time(NULL) - seen < Seconds; } @@ -92,6 +110,8 @@ cString GetTimeString(void) const; cString GetEndTimeString(void) const; cString GetVpsString(void) const; + cString GetContentsString(int i = 0) const; + cString GetParentalRatingString(void) const; void SetEventID(tEventID EventID); void SetTableID(uchar TableID); void SetVersion(uchar Version); @@ -102,6 +122,8 @@ void SetComponents(cComponents *Components); // Will take ownership of Components! void SetStartTime(time_t StartTime); void SetDuration(int Duration); + void SetContents(uchar *Contents); + void SetParentalRating(uchar ParentalRating); void SetVps(time_t Vps); void SetSeen(void); cString ToDescr(void) const; diff -Nru vdr-1.6.0-vanilla/po/fi_FI.po vdr-1.6.0-parentalrating-content/po/fi_FI.po --- vdr-1.6.0-vanilla/po/fi_FI.po 2008-03-27 21:43:25.000000000 +0200 +++ vdr-1.6.0-parentalrating-content/po/fi_FI.po 2008-03-27 21:51:24.000000000 +0200 @@ -30,6 +30,253 @@ msgid "Starting EPG scan" msgstr "Ohjelmaoppaan päivitys aloitettu" +msgid "Content$Movie/Drama" +msgstr "Elokuva/draama" + +msgid "Content$Detective/Thriller" +msgstr "Etsivä/trilleri" + +msgid "Content$Adventure/Western/War" +msgstr "Seikkailu/western/sota" + +msgid "Content$Science Fiction/Fantasy/Horror" +msgstr "Scifi/fantasia/kauhu" + +msgid "Content$Comedy" +msgstr "Komedia" + +msgid "Content$Soap/Melodrama/Folkloric" +msgstr "Saippua/melodraama/kansanperinne" + +msgid "Content$Romance" +msgstr "Romanssi" + +msgid "Content$Serious/Classical/Religious/Historical Movie/Drama" +msgstr "Vakava/klassinen/uskonnollinen/historiallinen elokuva/draama" + +msgid "Content$Adult Movie/Drama" +msgstr "Aikuiselokuva/draama" + +msgid "Content$News/Current Affairs" +msgstr "Uutiset/ajankohtaisohjelma" + +msgid "Content$News/Weather Report" +msgstr "Uutiset/säätiedot" + +msgid "Content$News Magazine" +msgstr "Uutismakasiini" + +msgid "Content$Documentary" +msgstr "Dokumentti" + +msgid "Content$Discussion/Inverview/Debate" +msgstr "Keskustelu/haastattelu/väittely" + +msgid "Content$Show/Game Show" +msgstr "Show/visailu" + +msgid "Content$Game Show/Quiz/Contest" +msgstr "Visailu/kilpailu" + +msgid "Content$Variety Show" +msgstr "Varietee" + +msgid "Content$Talk Show" +msgstr "Keskusteluohjelma" + +msgid "Content$Sports" +msgstr "Urheilua" + +msgid "Content$Special Event" +msgstr "Erikoistapahtuma" + +msgid "Content$Sport Magazine" +msgstr "Urheilumakasiini" + +msgid "Content$Football" +msgstr "Jalkapallo" + +msgid "Content$Tennis/Squash" +msgstr "Tennis/Squash" + +msgid "Content$Team Sports" +msgstr "Joukkueurheilua" + +msgid "Content$Athletics" +msgstr "Yleisurheilua" + +msgid "Content$Motor Sport" +msgstr "Moottoriurheilua" + +msgid "Content$Water Sport" +msgstr "Vesiurheilua" + +msgid "Content$Winter Sports" +msgstr "Talviurheilua" + +msgid "Content$Equestrian" +msgstr "Ratsastusta" + +msgid "Content$Martial Sports" +msgstr "Kamppailu-urheilua" + +msgid "Content$Children's/Youth Programmes" +msgstr "Lasten ja nuorten ohjelma" + +msgid "Content$Pre-school Children's Programmes" +msgstr "Alle kouluikäisten ohjelma" + +msgid "Content$Entertainment Programmes for 6 to 14" +msgstr "Viihdeohjelma 6-14 vuotiaille" + +msgid "Content$Entertainment Programmes for 10 to 16" +msgstr "Viihdeohjelma 10-16 vuotiaille" + +msgid "Content$Informational/Educational/School Programme" +msgstr "Opetus/kouluohjelma" + +msgid "Content$Cartoons/Puppets" +msgstr "Piirretty/nukke-esitys" + +msgid "Content$Music/Ballet/Dance" +msgstr "Musiikki/baletti/tanssi" + +msgid "Content$Rock/Pop" +msgstr "Rock/pop" + +msgid "Content$Serious/Classical Music" +msgstr "Vakava/klassinen musiikki" + +msgid "Content$Folk/Tradional Music" +msgstr "Folk/kansanmusiikki" + +msgid "Content$Jazz" +msgstr "Jazz" + +msgid "Content$Musical/Opera" +msgstr "Musikaali/ooppera" + +msgid "Content$Ballet" +msgstr "Baletti" + +msgid "Content$Arts/Culture" +msgstr "Taide/kulttuuri" + +msgid "Content$Performing Arts" +msgstr "Performanssitaide" + +msgid "Content$Fine Arts" +msgstr "Kuvataide" + +msgid "Content$Religion" +msgstr "Uskonto" + +msgid "Content$Popular Culture/Traditional Arts" +msgstr "Populaarikulttuuri/perinnetaiteet" + +msgid "Content$Literature" +msgstr "Kirjallisuus" + +msgid "Content$Film/Cinema" +msgstr "Elokuvataide" + +msgid "Content$Experimental Film/Video" +msgstr "Kokeellinen elokuva/video" + +msgid "Content$Broadcasting/Press" +msgstr "Televisio/radio/lehdistö" + +msgid "Content$New Media" +msgstr "Uusmedia" + +msgid "Content$Arts/Culture Magazines" +msgstr "Taide/kulttuurimakasiini" + +msgid "Content$Fashion" +msgstr "Muoti" + +msgid "Content$Social/Political/Economics" +msgstr "Yhteiskunta/politiikka/talous" + +msgid "Content$Magazines/Reports/Documentary" +msgstr "Makasiini/reportaasi/dokumentti" + +msgid "Content$Economics/Social Advisory" +msgstr "Talous/yhteiskunnallinen neuvonta" + +msgid "Content$Remarkable People" +msgstr "Merkittävät henkilöt" + +msgid "Content$Education/Science/Factual" +msgstr "Koulutus/tiede" + +msgid "Content$Nature/Animals/Environment" +msgstr "Luonto/eläimet/ympäristö" + +msgid "Content$Technology/Natural Sciences" +msgstr "Teknologia/luonnontiede" + +msgid "Content$Medicine/Physiology/Psychology" +msgstr "Lääketiede/fysiologia/psykologia" + +msgid "Content$Foreign Countries/Expeditions" +msgstr "Vieraat maat/tutkimusretket" + +msgid "Content$Social/Spiritual Sciences" +msgstr "Yhteiskunta/hengelliset tieteet" + +msgid "Content$Further Education" +msgstr "Jatkokoulutus" + +msgid "Content$Languages" +msgstr "Kielet" + +msgid "Content$Leisure/Hobbies" +msgstr "Vapaa-aika ja harrastukset" + +msgid "Content$Tourism/Travel" +msgstr "Turismi/matkustaminen" + +msgid "Content$Handicraft" +msgstr "Käsityöt" + +msgid "Content$Motoring" +msgstr "Autoilu" + +msgid "Content$Fitness & Health" +msgstr "Kuntoilu & terveys" + +msgid "Content$Cooking" +msgstr "Ruuanlaitto" + +msgid "Content$Advertisement/Shopping" +msgstr "Mainostaminen/ostaminen" + +msgid "Content$Gardening" +msgstr "Puutarhanhoito" + +msgid "Content$Original Language" +msgstr "Alkuperäiskieli" + +msgid "Content$Black & White" +msgstr "Mustavalkoinen" + +msgid "Content$Unpublished" +msgstr "Julkaisematon" + +msgid "Content$Live Broadcast" +msgstr "Suoralähetys" + +msgid "Content$Special Characteristics" +msgstr "Erikoisominaisuus" + +msgid "Content$Drama" +msgstr "Draama" + +#, c-format +msgid "Suitable for those aged %d and over" +msgstr "Kielletty alle %d vuotiailta" + msgid "No title" msgstr "Ei esitystä" diff -Nru vdr-1.6.0-vanilla/skinsttng.c vdr-1.6.0-parentalrating-content/skinsttng.c --- vdr-1.6.0-vanilla/skinsttng.c 2008-03-27 21:43:25.000000000 +0200 +++ vdr-1.6.0-parentalrating-content/skinsttng.c 2008-03-27 21:51:24.000000000 +0200 @@ -602,6 +602,19 @@ y += ts.Height(); } y += font->Height(); + if (!isempty(Event->GetParentalRatingString())) { + const cFont *font = cFont::GetFont(fontSml); + ts.Set(osd, xl, y, x4 - xl, y4 - y, Event->GetParentalRatingString(), font, Theme.Color(clrMenuEventShortText), Theme.Color(clrBackground)); + y += ts.Height(); + } + int i = 0; + while (Event->Contents(i++)) { + if (!isempty(Event->GetContentsString())) { + const cFont *font = cFont::GetFont(fontSml); + ts.Set(osd, xl, y, x4 - xl, y4 - y, Event->GetContentsString(), font, Theme.Color(clrMenuEventShortText), Theme.Color(clrBackground)); + y += ts.Height(); + } + } if (!isempty(Event->Description())) { int yt = y; int yb = y4 - Roundness;