diff --git a/FORMATS b/FORMATS index 0da29397..91903384 100644 --- a/FORMATS +++ b/FORMATS @@ -29,8 +29,9 @@ Video Disk Recorder File Formats If this channel also carries Dolby Digital sound, the Dolby PIDs follow the audio PIDs, separated by a semicolon, as in "...:101,102;103,104:..." - Teletext PID - - Conditional Access (0 = Free To Air, 1 = can be decrypted by the first - DVB card, 2 = can be decrypted by the second DVB card) + - Conditional Access (0 = Free To Air, 1..4 = explicitly requires the DVB card + with the given number, >=100 = requires a specific decryption method defined + in 'ca.conf'). - Program Number Fields marked with ** are only meaningful for DVB-S receivers. @@ -38,6 +39,20 @@ Video Disk Recorder File Formats Fields marked with *** are only meaningful for DVB-S and DVB-C receivers. DVB-T receivers simply ignore these. +* ca.conf + + This file contains the definitions of the various conditional access code + numbers. Anything after (and including) a '#' character is comment. + Value lines consist of an integer number, followed by a text describing + this decryption method (typically the name of the pay tv service using this + decryption method). + The special value 0 means "Free To Air", i.e. can be used for channels that + don't require additional decryption hardware. + The values 1..4 can be used for channels that for some reason explicitly + need a given DVB card (for backward compatibility). + The values defined in this file are the ones used in the 'Ca' parameter of + 'channels.conf'. + * timers.conf This file contains the timer setup. diff --git a/HISTORY b/HISTORY index 836de4c5..fd7f35c8 100644 --- a/HISTORY +++ b/HISTORY @@ -1048,8 +1048,20 @@ Video Disk Recorder Revision History - Fixed a crash in case there is no 'epg.data' at program start (thanks to Andreas Schultz). -2002-03-01: Version 1.0.0pre3 +2002-03-03: Version 1.0.0pre3 - Fixed parsing 'E' records in epg2html.pl. - Fixed a deadlock when switching channels via Schedule/Now|Next/Switch (reported by Martin Hammerschmid). +- Changed the meaning of the 'Ca' parameter in 'channels.conf'. Each channel can + now define which decryption method it needs in order to be accessed. The new + configuration file 'ca.conf' contains the defined values, and the default + 'channels.conf' has been modifed to contain the new values for 'Premiere World' + and 'ORF'. If you use the default 'channels.conf' and have the conditional + access hardware to receive encrypted channels, please make sure you copy the + file 'ca.conf' into your /video directory (or wherever your configuration files + are located) and go into the "Setup" menu and set the CICAM values according + to your hardware setup. Currently there are two possible CICAM entries per + DVB card, so any card can implement up to two different conditional access + modes (besides the default "Free To Air" mode, which is always assumed to be + available on any DVB card). diff --git a/MANUAL b/MANUAL index 320d24da..c4cda08a 100644 --- a/MANUAL +++ b/MANUAL @@ -526,6 +526,14 @@ Video Disk Recorder User's Manual 0 = off 1 = on + CaCaps (no default) Defines the "Conditional Access Capabilities" of a DVB + card. The value consists of the card number, followed by + a list of decryption method values (defined in 'ca.conf'). + For instance + CaCaps = 3 101 102 + would define that card number 3 is able to decrypt + "Premiere World" and the "ORF". + * Executing system commands The "Main" menu option "Commands" allows you to execute any system commands diff --git a/ca.conf b/ca.conf new file mode 100644 index 00000000..7024ee42 --- /dev/null +++ b/ca.conf @@ -0,0 +1,22 @@ +# Conditional Access configuration for VDR +# +# Format: +# +# number description +# +# Please contact kls@cadsoft.de before assigning a new number +# to a description, in order to keep them unique. + +0 Free To Air + +# BetaCrypt + +101 Premiere World +102 ORF + +# Special values to "hard code" a channel to a specific DVB card: + +1 DVB 1 +2 DVB 2 +3 DVB 3 +4 DVB 4 diff --git a/channels.conf b/channels.conf index 4642edc5..db1cbf41 100644 --- a/channels.conf +++ b/channels.conf @@ -15,8 +15,8 @@ ZDF:11954:h:0:27500:110:120:130:0:28006 3sat:11954:h:0:27500:210:220:230:0:28007 KiKa:11954:h:0:27500:310:320:330:0:28008 arte:11836:h:0:27500:401:402:404:0:28109 -ORF1:12692:h:0:22000:160:161:165:3:13001 -ORF2:12692:h:0:22000:500:501:505:3:13002 +ORF1:12692:h:0:22000:160:161:165:102:13001 +ORF2:12692:h:0:22000:500:501:505:102:13002 ORF Sat:11954:h:0:27500:506:507:0:0:28010 ZDF.info:11954:h:0:27500:610:620:0:0:28011 CNN:12168:v:0:27500:165:100:0:0:28512 @@ -49,82 +49,82 @@ B1:12110:h:0:27500:601:602:604:0:28206 ARD Online-Kanal:12722:h:0:22000:0:701:0:0:0 :Premiere World Premiere World:11797:h:0:27500:255:256:32:0:8 -Premiere 1:11797:h:0:27500:511:512:0:3:10 -Premiere 2:11797:h:0:27500:1791:1792:0:3:11 -Premiere 3:11797:h:0:27500:2303:2304:0:3:43 -Premiere One:12032:h:0:27500:3071:3072:0:3:51 -Premiere Star:11797:h:0:27500:767:768:0:3:9 -Premiere Sci-Fi:11797:h:0:27500:1535:1536:0:3:41 -Premiere Action:11797:h:0:27500:1023:1024:0:3:20 -Premiere X-Action:11798:h:0:27500:2047:2048:0:3:50 -Premiere Comedy:11797:h:0:27500:1279:1280:0:3:29 -13th Street:12031:h:0:27500:2303:2304:0:3:42 -Studio Universal:12090:V:0:27500:255:256:0:3:36 -Filmpalast:12031:h:0:27500:2559:2560:0:3:516 -Heimatkanal:12031:h:0:27500:2815:2816:0:3:517 -Discovery Channel:12031:h:0:27500:1791:1792:0:3:14 -Planet:12090:V:0:27500:1279:1280:0:3:13 -Fox Kids:12031:h:0:27500:1279:1280:0:3:28 -Fox Kids Türkce:11914:H:0:27500:767:768:8191:3:54 -Junior:12031:h:0:27500:255:256:0:3:19 -K-Toon:12031:h:0:27500:511:512:0:3:12 -Disney Channel:12090:V:0:27500:767:768:0:3:34 -Sunset:12031:h:0:27500:1023:1024:0:3:16 -Krimi&Co:12031:h:0:27500:1535:1536:0:3:23 -Goldstar TV:12031:h:0:27500:3839:3840:0:3:518 -Classica:12031:h:0:27500:767:768:0:3:15 -Seasons:12090:V:0:27500:511:512:0:3:33 +Premiere 1:11797:h:0:27500:511:512:0:101:10 +Premiere 2:11797:h:0:27500:1791:1792:0:101:11 +Premiere 3:11797:h:0:27500:2303:2304:0:101:43 +Premiere One:12032:h:0:27500:3071:3072:0:101:51 +Premiere Star:11797:h:0:27500:767:768:0:101:9 +Premiere Sci-Fi:11797:h:0:27500:1535:1536:0:101:41 +Premiere Action:11797:h:0:27500:1023:1024:0:101:20 +Premiere X-Action:11798:h:0:27500:2047:2048:0:101:50 +Premiere Comedy:11797:h:0:27500:1279:1280:0:101:29 +13th Street:12031:h:0:27500:2303:2304:0:101:42 +Studio Universal:12090:V:0:27500:255:256:0:101:36 +Filmpalast:12031:h:0:27500:2559:2560:0:101:516 +Heimatkanal:12031:h:0:27500:2815:2816:0:101:517 +Discovery Channel:12031:h:0:27500:1791:1792:0:101:14 +Planet:12090:V:0:27500:1279:1280:0:101:13 +Fox Kids:12031:h:0:27500:1279:1280:0:101:28 +Fox Kids Türkce:11914:H:0:27500:767:768:8191:101:54 +Junior:12031:h:0:27500:255:256:0:101:19 +K-Toon:12031:h:0:27500:511:512:0:101:12 +Disney Channel:12090:V:0:27500:767:768:0:101:34 +Sunset:12031:h:0:27500:1023:1024:0:101:16 +Krimi&Co:12031:h:0:27500:1535:1536:0:101:23 +Goldstar TV:12031:h:0:27500:3839:3840:0:101:518 +Classica:12031:h:0:27500:767:768:0:101:15 +Seasons:12090:V:0:27500:511:512:0:101:33 :Cinedom -Cinedom Deluxe:11758:h:0:27500:255:256,257;259:0:3:189 -Cinedom 1A:11758:h:0:27500:511:512,513:0:3:190 -Cinedom 1B:12070:h:0:27500:1535:1536,1537:0:3:178 -Cinedom 1C:11720:h:0:27500:511:512,513:0:3:180 -Cinedom 1D:11720:h:0:27500:1535:1536,1537:0:3:176 -Cinedom 2A:11758:h:0:27500:1023:1024,1025:0:3:193 -Cinedom 2B:11720:h:0:27500:1279:1280:0:3:183 -Cinedom 2C:12070:h:0:27500:1791:1792:0:3:179 -Cinedom 2D:12070:h:0:27500:511:512:0:3:184 -Cinedom 2E:12070:h:0:27500:1279:1280:0:3:188 -Cinedom 3A:11758:h:0:27500:2559:2560:0:3:192 -Cinedom 3B:11758:h:0:27500:1535:1536:0:3:195 -Cinedom 3C:12070:h:0:27500:767:768:0:3:185 -Cinedom 3D:11720:h:0:27500:1023:1024:0:3:182 -Cinedom 4A:11758:h:0:27500:767:768:0:3:191 -Cinedom 4B:11720:h:0:27500:767:768:0:3:181 -Cinedom 4C:12070:h:0:27500:2047:2048:0:3:187 -Cinedom 5A:11758:h:0:27500:1279:1280:0:3:194 -Cinedom 5B:11720:h:0:27500:1791:1792:0:3:177 -Cinedom 5C:12070:h:0:27500:1023:1024:0:3:186 +Cinedom Deluxe:11758:h:0:27500:255:256,257;259:0:101:189 +Cinedom 1A:11758:h:0:27500:511:512,513:0:101:190 +Cinedom 1B:12070:h:0:27500:1535:1536,1537:0:101:178 +Cinedom 1C:11720:h:0:27500:511:512,513:0:101:180 +Cinedom 1D:11720:h:0:27500:1535:1536,1537:0:101:176 +Cinedom 2A:11758:h:0:27500:1023:1024,1025:0:101:193 +Cinedom 2B:11720:h:0:27500:1279:1280:0:101:183 +Cinedom 2C:12070:h:0:27500:1791:1792:0:101:179 +Cinedom 2D:12070:h:0:27500:511:512:0:101:184 +Cinedom 2E:12070:h:0:27500:1279:1280:0:101:188 +Cinedom 3A:11758:h:0:27500:2559:2560:0:101:192 +Cinedom 3B:11758:h:0:27500:1535:1536:0:101:195 +Cinedom 3C:12070:h:0:27500:767:768:0:101:185 +Cinedom 3D:11720:h:0:27500:1023:1024:0:101:182 +Cinedom 4A:11758:h:0:27500:767:768:0:101:191 +Cinedom 4B:11720:h:0:27500:767:768:0:101:181 +Cinedom 4C:12070:h:0:27500:2047:2048:0:101:187 +Cinedom 5A:11758:h:0:27500:1279:1280:0:101:194 +Cinedom 5B:11720:h:0:27500:1791:1792:0:101:177 +Cinedom 5C:12070:h:0:27500:1023:1024:0:101:186 :Beta Digital N24:12480:v:0:27500:2047:2048:0:0:47 CNBC:11954:h:0:27500:510:520:0:0:28010 Liberty TV.com:12610:V:0:22000:941:943,942:0:0:12199 :PW Erotic -Beate-Uhse.TV:11758:h:0:27500:3839:3840:0:3:21 -Blue Movie 1:11758:h:0:27500:1791:1792:0:3:513 -Blue Movie 2:11758:h:0:27500:2047:2048:0:3:514 -Blue Movie 3:11758:h:0:27500:2303:2304:0:3:515 +Beate-Uhse.TV:11758:h:0:27500:3839:3840:0:101:21 +Blue Movie 1:11758:h:0:27500:1791:1792:0:101:513 +Blue Movie 2:11758:h:0:27500:2047:2048:0:101:514 +Blue Movie 3:11758:h:0:27500:2303:2304:0:101:515 :Sportsworld -Premiere Sport 1:11720:h:0:27500:255:256,257:0:3:17 -Premiere Sport 2:12070:h:0:27500:3839:3840:0:3:27 -Premiere Sport 3:12070:h:0:27500:255:256:0:3:26 +Premiere Sport 1:11720:h:0:27500:255:256,257:0:101:17 +Premiere Sport 2:12070:h:0:27500:3839:3840:0:101:27 +Premiere Sport 3:12070:h:0:27500:255:256:0:101:26 :Formel 1 -Infokanal:11720:h:0:27500:3071:3072:0:3:244 -Multikanal:11720:h:0:27500:2815:2816:0:3:243 -Supersignal:11720:h:0:27500:255:256:0:3:17 -Verfolgerfeld:11720:h:0:27500:2303:2304:0:3:241 -Cockpitkanal:11720:h:0:27500:2559:2560:0:3:242 -Boxengasse:11720:h:0:27500:2047:2048:0:3:240 +Infokanal:11720:h:0:27500:3071:3072:0:101:244 +Multikanal:11720:h:0:27500:2815:2816:0:101:243 +Supersignal:11720:h:0:27500:255:256:0:101:17 +Verfolgerfeld:11720:h:0:27500:2303:2304:0:101:241 +Cockpitkanal:11720:h:0:27500:2559:2560:0:101:242 +Boxengasse:11720:h:0:27500:2047:2048:0:101:240 :Premiere World Bundesliga -Superdom:11758:h:0:27500:2815:8192:0:3:18 -BuLi-Konferenz:11758:h:0:27500:3327:3328,3329:0:3:215 -BuLi-Spiel 1:11720:h:0:27500:255:256,257:0:3:17 -BuLi-Spiel 2:11720:h:0:27500:2047:2048,2049:0:3:240 -BuLi-Spiel 3:11720:h:0:27500:2303:2304,2305:0:3:241 -BuLi-Spiel 4:11720:h:0:27500:2559:2560,2561:0:3:242 -BuLi-Spiel 5:11720:h:0:27500:2815:2816,2817:0:3:243 -BuLi-Spiel 6:11720:h:0:27500:3071:3072,3073:0:3:244 -BuLi-Spiel 7:11758:h:0:27500:3071:3072,3073:0:3:214 +Superdom:11758:h:0:27500:2815:8192:0:101:18 +BuLi-Konferenz:11758:h:0:27500:3327:3328,3329:0:101:215 +BuLi-Spiel 1:11720:h:0:27500:255:256,257:0:101:17 +BuLi-Spiel 2:11720:h:0:27500:2047:2048,2049:0:101:240 +BuLi-Spiel 3:11720:h:0:27500:2303:2304,2305:0:101:241 +BuLi-Spiel 4:11720:h:0:27500:2559:2560,2561:0:101:242 +BuLi-Spiel 5:11720:h:0:27500:2815:2816,2817:0:101:243 +BuLi-Spiel 6:11720:h:0:27500:3071:3072,3073:0:101:244 +BuLi-Spiel 7:11758:h:0:27500:3071:3072,3073:0:101:214 : TV Niepokalanow:11876:h:0:27500:305:321:0:0:20601 Mosaico:11934:v:0:27500:165:100:0:0:29010 diff --git a/config.c b/config.c index 213fe2cf..a91cb8ac 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.87 2002/02/24 11:59:14 kls Exp $ + * $Id: config.c 1.88 2002/03/03 16:04:21 kls Exp $ */ #include "config.h" @@ -732,6 +732,24 @@ bool cSVDRPhost::Accepts(in_addr_t Address) return (Address & mask) == addr.s_addr; } +// -- cCaDefinition ---------------------------------------------------------- + +cCaDefinition::cCaDefinition(void) +{ + number = 0; + description = NULL; +} + +cCaDefinition::~cCaDefinition() +{ + delete description; +} + +bool cCaDefinition::Parse(const char *s) +{ + return 2 == sscanf(s, "%d %a[^\n]", &number, &description) && description && *description; +} + // -- cKeys ------------------------------------------------------------------ cKeys Keys; @@ -879,6 +897,21 @@ bool cSVDRPhosts::Acceptable(in_addr_t Address) return false; } +// -- cCaDefinitions --------------------------------------------------------- + +cCaDefinitions CaDefinitions; + +const cCaDefinition *cCaDefinitions::Get(int Number) +{ + cCaDefinition *p = First(); + while (p) { + if (p->Number() == Number) + return p; + p = (cCaDefinition *)p->Next(); + } + return NULL; +} + // -- cSetup ----------------------------------------------------------------- cSetup Setup; @@ -921,10 +954,46 @@ cSetup::cSetup(void) MinUserInactivity = 120; MultiSpeedMode = 0; ShowReplayMode = 0; + memset(CaCaps, sizeof(CaCaps), 0); CurrentChannel = -1; CurrentVolume = MAXVOLUME; } +void cSetup::PrintCaCaps(FILE *f, const char *Name) +{ + for (int d = 0; d < MAXDVBAPI; d++) { + if (CaCaps[d][0]) { + fprintf(f, "CaCaps = %d", d + 1); + for (int i = 0; i < MAXCACAPS && CaCaps[d][i]; i++) + fprintf(f, " %d", CaCaps[d][i]); + fprintf(f, "\n"); + } + } +} + +bool cSetup::ParseCaCaps(const char *Value) +{ + char *p; + int d = strtol(Value, &p, 10); + if (d > 0 && d < MAXDVBAPI) { + d--; + int i = 0; + while (p != Value && p && *p) { + if (i < MAXCACAPS) { + int c = strtol(p, &p, 10); + if (c > 0) + CaCaps[d][i++] = c; + else + return false; + } + else + return false; + } + return true; + } + return false; +} + bool cSetup::Parse(char *s) { char *p = strchr(s, '='); @@ -967,6 +1036,7 @@ bool cSetup::Parse(char *s) else if (!strcasecmp(Name, "MinUserInactivity")) MinUserInactivity = atoi(Value); else if (!strcasecmp(Name, "MultiSpeedMode")) MultiSpeedMode = atoi(Value); else if (!strcasecmp(Name, "ShowReplayMode")) ShowReplayMode = atoi(Value); + else if (!strcasecmp(Name, "CaCaps")) return ParseCaCaps(Value); else if (!strcasecmp(Name, "CurrentChannel")) CurrentChannel = atoi(Value); else if (!strcasecmp(Name, "CurrentVolume")) CurrentVolume = atoi(Value); else @@ -1047,6 +1117,7 @@ bool cSetup::Save(const char *FileName) fprintf(f, "MinUserInactivity = %d\n", MinUserInactivity); fprintf(f, "MultiSpeedMode = %d\n", MultiSpeedMode); fprintf(f, "ShowReplayMode = %d\n", ShowReplayMode); + PrintCaCaps(f, "CaCaps"); fprintf(f, "CurrentChannel = %d\n", CurrentChannel); fprintf(f, "CurrentVolume = %d\n", CurrentVolume); if (f.Close()) { diff --git a/config.h b/config.h index 52a203ff..f5e83435 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.101 2002/02/26 17:25:30 kls Exp $ + * $Id: config.h 1.102 2002/03/03 16:04:43 kls Exp $ */ #ifndef __CONFIG_H @@ -195,6 +195,18 @@ public: bool Accepts(in_addr_t Address); }; +class cCaDefinition : public cListObject { +private: + int number; + char *description; +public: + cCaDefinition(void); + ~cCaDefinition(); + bool Parse(const char *s); + int Number(void) const { return number; } + const char *Description(void) const { return description; } + }; + template class cConfig : public cList { private: char *fileName; @@ -297,15 +309,23 @@ public: bool Acceptable(in_addr_t Address); }; +class cCaDefinitions : public cConfig { +public: + const cCaDefinition *Get(int Number); + }; + extern cChannels Channels; extern cTimers Timers; extern cKeys Keys; extern cCommands Commands; extern cSVDRPhosts SVDRPhosts; +extern cCaDefinitions CaDefinitions; class cSetup { private: static char *fileName; + void PrintCaCaps(FILE *f, const char *Name); + bool ParseCaCaps(const char *Value); bool Parse(char *s); public: // Also adjust cMenuSetup (menu.c) when adding parameters here! @@ -339,6 +359,7 @@ public: int MinEventTimeout, MinUserInactivity; int MultiSpeedMode; int ShowReplayMode; + int CaCaps[MAXDVBAPI][MAXCACAPS]; int CurrentChannel; int CurrentVolume; cSetup(void); diff --git a/dvbapi.c b/dvbapi.c index c55142e1..2f1ca145 100644 --- a/dvbapi.c +++ b/dvbapi.c @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: dvbapi.c 1.153 2002/03/02 09:37:56 kls Exp $ + * $Id: dvbapi.c 1.154 2002/03/03 15:43:24 kls Exp $ */ #include "dvbapi.h" @@ -1684,9 +1684,10 @@ cDvbApi::cDvbApi(int n) replayBuffer = NULL; transferBuffer = NULL; transferringFromDvbApi = NULL; - ca = 0; + ca = -1; priority = -1; cardIndex = n; + SetCaCaps(); // Devices that are only present on DVB-C or DVB-S cards: @@ -1783,37 +1784,93 @@ bool cDvbApi::SetPrimaryDvbApi(int n) return false; } +int cDvbApi::CanShift(int Ca, int Priority) +{ + // Test whether a recording on this DVB device can be shifted to another one + // in order to perform a new recording with the given Ca and Priority on this device: + int ShiftLevel = -1; // default means this device can't be shifted + if (Recording()) { + if (ProvidesCa(Ca) // this device provides the requested Ca + && (Ca != this->Ca() // the requested Ca is different from the one currently used... + || Priority > this->Priority())) { // ...or the request comes from a higher priority + cDvbApi *d = NULL; + int Provides[MAXDVBAPI]; + for (int i = 0; i < NumDvbApis; i++) { + if ((Provides[i] = dvbApi[i]->ProvidesCa(this->Ca())) != 0) { // this device is basicly able to do the job + if (dvbApi[i] != this) { // it is not _this_ device + int sl = dvbApi[i]->CanShift(this->Ca(), Priority); // this is the original Priority! + if (sl >= 0 && (ShiftLevel < 0 || sl < ShiftLevel)) { + d = dvbApi[i]; + ShiftLevel = sl; + } + } + } + } + if (ShiftLevel >= 0) + ShiftLevel++; // adds the device's own shift + } + } + else if (Priority > this->Priority()) + ShiftLevel = 0; // no shifting necessary, this device can do the job + return ShiftLevel; +} + cDvbApi *cDvbApi::GetDvbApi(int Ca, int Priority) { - cDvbApi *d = NULL, *dMinPriority = NULL; - int index = Ca - 1; - for (int i = 0; i < MAXDVBAPI; i++) { - if (dvbApi[i]) { - if (dvbApi[i]->CardIndex() == index) { // means we need exactly _this_ device + cDvbApi *d = NULL; + int Provides[MAXDVBAPI]; + // Check which devices provide Ca: + for (int i = 0; i < NumDvbApis; i++) { + if ((Provides[i] = dvbApi[i]->ProvidesCa(Ca)) != 0) { // this device is basicly able to do the job + if (Priority > dvbApi[i]->Priority() // Priority is high enough to use this device + && (!d // we don't have a device yet, or... + || dvbApi[i]->Priority() < d->Priority() // ...this one has an even lower Priority + || (dvbApi[i]->Priority() == d->Priority() // ...same Priority... + && Provides[i] < Provides[d->CardIndex()]))) // ...but this one provides fewer Ca values d = dvbApi[i]; - break; - } - else if (Ca == 0) { // means any device would be acceptable - if (!d || !dvbApi[i]->Recording() || (d->Recording() && d->Priority() > dvbApi[i]->Priority())) - d = dvbApi[i]; // this is one that is either not currently recording or has the lowest priority - if (d && d != PrimaryDvbApi && !d->Recording()) // avoids the PrimaryDvbApi if possible - break; - if (d && d->Recording() && d->Priority() < Setup.PrimaryLimit && (!dMinPriority || d->Priority() < dMinPriority->Priority())) - dMinPriority = d; // this is the one with the lowest priority below Setup.PrimaryLimit - } } } - if (d == PrimaryDvbApi) { // the PrimaryDvbApi was the only one that was free - if (Priority < Setup.PrimaryLimit) - return NULL; // not enough priority to use the PrimaryDvbApi - if (dMinPriority) // there's one that must not use the PrimaryDvbApi... - d = dMinPriority; // ...so let's kick out that one + if (!d && Ca > MAXDVBAPI) { + // We didn't find one the easy way, so now we have to try harder: + int ShiftLevel = -1; + for (int i = 0; i < NumDvbApis; i++) { + if (Provides[i]) { // this device is basicly able to do the job, but for some reason we didn't get it above + int sl = dvbApi[i]->CanShift(Ca, Priority); // asks this device to shift its job to another device + if (sl >= 0 && (ShiftLevel < 0 || sl < ShiftLevel)) { + d = dvbApi[i]; // found one that can be shifted with the fewest number of subsequent shifts + ShiftLevel = sl; + } + } + } } - return (d // we found one... - && (!d->Recording() // ...that's either not currently recording... - || d->Priority() < Priority // ...or has a lower priority... - || (!d->Ca() && Ca))) // ...or doesn't need this card - ? d : NULL; + return d; +} + +void cDvbApi::SetCaCaps(void) +{ + for (int i = 0; i < MAXCACAPS; i++) + caCaps[i] = Setup.CaCaps[CardIndex()][i]; +} + +int cDvbApi::ProvidesCa(int Ca) +{ + if (Ca == CardIndex() + 1) + return 1; // exactly _this_ card was requested + if (Ca && Ca <= MAXDVBAPI) + return 0; // a specific card was requested, but not _this_ one + int result = Ca ? 0 : 1; // by default every card can provide FTA + int others = Ca ? 1 : 0; + for (int i = 0; i < MAXCACAPS; i++) { + if (caCaps[i]) { + if (caCaps[i] == Ca) + result = 1; + else + others++; + } + else + break; + } + return result ? result + others : 0; } bool cDvbApi::Probe(const char *FileName) @@ -1854,7 +1911,7 @@ bool cDvbApi::Init(void) void cDvbApi::Cleanup(void) { - for (int i = 0; i < MAXDVBAPI; i++) { + for (int i = 0; i < NumDvbApis; i++) { delete dvbApi[i]; dvbApi[i] = NULL; } @@ -2148,6 +2205,11 @@ void cDvbApi::Flush(void) #endif } +int cDvbApi::Priority(void) +{ + return (this == PrimaryDvbApi && !Recording()) ? Setup.PrimaryLimit - 1 : priority; +} + int cDvbApi::SetModeRecord(void) { // Sets up the DVB device for recording @@ -2262,7 +2324,7 @@ eSetChannelResult cDvbApi::SetChannel(int ChannelNumber, int Frequency, char Pol // If this card can't receive this channel, we must not actually switch // the channel here, because that would irritate the driver when we // start replaying in Transfer Mode immediately after switching the channel: - bool NeedsTransferMode = (this == PrimaryDvbApi && Ca && Ca != CardIndex() + 1); + bool NeedsTransferMode = (this == PrimaryDvbApi && !ProvidesCa(Ca)); if (!NeedsTransferMode) { @@ -2504,7 +2566,7 @@ void cDvbApi::StopRecord(void) if (recordBuffer) { delete recordBuffer; recordBuffer = NULL; - ca = 0; + ca = -1; priority = -1; } } @@ -2703,7 +2765,7 @@ void cEITScanner::Process(void) time_t now = time(NULL); if (now - lastScan > ScanTimeout && now - lastActivity > ActivityTimeout) { for (int i = 0; i < MAXDVBAPI; i++) { - cDvbApi *DvbApi = cDvbApi::GetDvbApi(i + 1, MAXPRIORITY); + cDvbApi *DvbApi = cDvbApi::GetDvbApi(i + 1, MAXPRIORITY + 1); if (DvbApi) { if (DvbApi != cDvbApi::PrimaryDvbApi || (cDvbApi::NumDvbApis == 1 && Setup.EPGScanTimeout && now - lastActivity > Setup.EPGScanTimeout * 3600)) { if (!(DvbApi->Recording() || DvbApi->Replaying() || DvbApi->Transferring())) { diff --git a/dvbapi.h b/dvbapi.h index 06028f0b..396b5c21 100644 --- a/dvbapi.h +++ b/dvbapi.h @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: dvbapi.h 1.63 2002/02/24 12:38:08 kls Exp $ + * $Id: dvbapi.h 1.64 2002/03/03 14:51:20 kls Exp $ */ #ifndef __DVBAPI_H @@ -94,12 +94,16 @@ private: public: ~cDvbApi(); -#define MAXDVBAPI 4 +#define MAXDVBAPI 4 // the maximum number of DVB cards in the system +#define MAXCACAPS 16 // the maximum number of different CA values per DVB card + static int NumDvbApis; private: static cDvbApi *dvbApi[MAXDVBAPI]; static int useDvbApi; int cardIndex; + int caCaps[MAXCACAPS]; + int CanShift(int Ca, int Priority); public: static cDvbApi *PrimaryDvbApi; static void SetUseDvbApi(int n); @@ -110,9 +114,10 @@ public: // Sets the primary DVB device to 'n' (which must be in the range // 1...NumDvbApis) and returns true if this was possible. static cDvbApi *GetDvbApi(int Ca, int Priority); - // Selects a free DVB device, starting with the highest device number - // (but avoiding, if possible, the PrimaryDvbApi). - // If Ca is not 0, the device with the given number will be returned. + // Selects a free DVB device, avoiding the PrimaryDvbApi if possible. + // If Ca is not 0, the device with the given number will be returned + // in case Ca is <= MAXDVBAPI, or the device that provides the given + // value in its caCaps. // If all DVB devices are currently recording, the one recording the // lowest priority timer (if any) that is lower than the given Priority // will be returned. @@ -120,6 +125,15 @@ public: // recording and stop recording if necessary. int CardIndex(void) { return cardIndex; } // Returns the card index of this DvbApi (0 ... MAXDVBAPI - 1). + void SetCaCaps(void); + // Sets the CaCaps of this DVB device according to the Setup data. + int ProvidesCa(int Ca); + // Checks whether this DVB device provides the given value in its + // caCaps. Returns 0 if the value is not provided, 1 if only this + // value is provided, and > 1 if this and other values are provided. + // If the given value is equal to the number of this DVB device, + // 1 is returned. If it is 0 (FTA), 1 plus the number of other values + // in caCaps is returned. static bool Probe(const char *FileName); // Probes for existing DVB devices. static bool Init(void); @@ -204,16 +218,17 @@ private: cPlayBuffer *replayBuffer; int ca; int priority; - int Priority(void) { return priority; } + int Priority(void); // Returns the priority of the current recording session (0..MAXPRIORITY), - // or -1 if no recording is currently active. + // or -1 if no recording is currently active. The primary DVB device will + // always return at least Setup.PrimaryLimit-1. int SetModeRecord(void); // Initiates recording mode and returns the file handle to read from. void SetModeReplay(void); void SetModeNormal(bool FromRecording); public: int Ca(void) { return ca; } - // Returns the ca of the current recording session (0..MAXDVBAPI). + // Returns the ca of the current recording session. int SecondsToFrames(int Seconds); // Returns the number of frames corresponding to the given number of seconds. bool Recording(void); diff --git a/i18n.c b/i18n.c index 08397157..d75f3302 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.57 2002/02/24 12:54:12 kls Exp $ + * $Id: i18n.c 1.58 2002/03/03 16:12:00 kls Exp $ * * Slovenian translations provided by Miha Setina * Italian translations provided by Alberto Carraro @@ -1176,6 +1176,16 @@ const tPhrase Phrases[] = { "", // TODO "Näytä toiston tila", }, + { "CICAM DVB", + "CICAM DVB", + "", // TODO + "", // TODO + "", // TODO + "", // TODO + "", // TODO + "", // TODO + "", // TODO + }, // The days of the week: { "MTWTFSS", "MDMDFSS", diff --git a/menu.c b/menu.c index 28e5d4d8..b1e7e49e 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.159 2002/02/24 12:55:49 kls Exp $ + * $Id: menu.c 1.160 2002/03/03 16:12:29 kls Exp $ */ #include "menu.h" @@ -585,6 +585,60 @@ void cMenuEditStraItem::Set(void) SetValue(strings[*value]); } +// --- cMenuEditCaItem ------------------------------------------------------- + +class cMenuEditCaItem : public cMenuEditIntItem { +private: + const cCaDefinition *ca; + bool allowCardNr; +protected: + virtual void Set(void); +public: + cMenuEditCaItem(const char *Name, int *Value, bool AllowCardNr = false); + eOSState ProcessKey(eKeys Key); + }; + +cMenuEditCaItem::cMenuEditCaItem(const char *Name, int *Value, bool AllowCardNr) +:cMenuEditIntItem(Name, Value, 0) +{ + ca = CaDefinitions.Get(*Value); + allowCardNr = AllowCardNr; + Set(); +} + +void cMenuEditCaItem::Set(void) +{ + if (ca) + SetValue(ca->Description()); + else + cMenuEditIntItem::Set(); +} + +eOSState cMenuEditCaItem::ProcessKey(eKeys Key) +{ + eOSState state = cMenuEditItem::ProcessKey(Key); + + if (state == osUnknown) { + if (NORMALKEY(Key) == kLeft) { // TODO might want to increase the delta if repeated quickly? + if (ca && ca->Prev()) { + ca = (cCaDefinition *)ca->Prev(); + *value = ca->Number(); + } + } + else if (NORMALKEY(Key) == kRight) { + if (ca && ca->Next() && (allowCardNr || ((cCaDefinition *)ca->Next())->Number() > MAXDVBAPI)) { + ca = (cCaDefinition *)ca->Next(); + *value = ca->Number(); + } + } + else + return cMenuEditIntItem::ProcessKey(Key); + Set(); + state = osContinue; + } + return state; +} + // --- cMenuEditChannel ------------------------------------------------------ class cMenuEditChannel : public cOsdMenu { @@ -613,7 +667,7 @@ cMenuEditChannel::cMenuEditChannel(int Index) Add(new cMenuEditIntItem( tr("Dpid1"), &data.dpid1, 0, 0x1FFF)); Add(new cMenuEditIntItem( tr("Dpid2"), &data.dpid2, 0, 0x1FFF)); Add(new cMenuEditIntItem( tr("Tpid"), &data.tpid, 0, 0x1FFF)); - Add(new cMenuEditIntItem( tr("CA"), &data.ca, 0, cDvbApi::NumDvbApis)); + Add(new cMenuEditCaItem( tr("CA"), &data.ca, true)); Add(new cMenuEditIntItem( tr("Pnr"), &data.pnr, 0)); } } @@ -1880,6 +1934,13 @@ void cMenuSetup::Set(void) Add(new cMenuEditIntItem( tr("MinUserInactivity"), &data.MinUserInactivity)); Add(new cMenuEditBoolItem(tr("MultiSpeedMode"), &data.MultiSpeedMode)); Add(new cMenuEditBoolItem(tr("ShowReplayMode"), &data.ShowReplayMode)); + for (int d = 0; d < cDvbApi::NumDvbApis; d++) { + for (int i = 0; i < 2; i++) { + char buffer[32]; + snprintf(buffer, sizeof(buffer), "%s%d %d", tr("CICAM DVB"), d + 1, i + 1); + Add(new cMenuEditCaItem(buffer, &data.CaCaps[d][i])); + } + } } eOSState cMenuSetup::ProcessKey(eKeys Key) diff --git a/vdr.c b/vdr.c index 90c1d843..a246be11 100644 --- a/vdr.c +++ b/vdr.c @@ -22,7 +22,7 @@ * * The project's page is at http://www.cadsoft.de/people/kls/vdr * - * $Id: vdr.c 1.97 2002/02/24 12:55:10 kls Exp $ + * $Id: vdr.c 1.98 2002/03/03 14:56:03 kls Exp $ */ #include @@ -252,6 +252,7 @@ int main(int argc, char *argv[]) Timers.Load(AddDirectory(ConfigDirectory, "timers.conf")); Commands.Load(AddDirectory(ConfigDirectory, "commands.conf")); SVDRPhosts.Load(AddDirectory(ConfigDirectory, "svdrphosts.conf"), true); + CaDefinitions.Load(AddDirectory(ConfigDirectory, "ca.conf"), true); #if defined(REMOTE_LIRC) Keys.SetDummyValues(); #elif !defined(REMOTE_NONE)