diff options
author | Klaus Schmidinger <kls (at) cadsoft (dot) de> | 2003-02-09 18:00:00 +0100 |
---|---|---|
committer | Klaus Schmidinger <kls (at) cadsoft (dot) de> | 2003-02-09 18:00:00 +0100 |
commit | b09aaa00a58ec72d0331a01f31b3df16d43ce90b (patch) | |
tree | 92e95c191cf4d07eccc3226c100daac7eaa57af3 | |
parent | 8c5d735d3279230f6471e474a946a5733054df43 (diff) | |
download | vdr-patch-lnbsharing-b09aaa00a58ec72d0331a01f31b3df16d43ce90b.tar.gz vdr-patch-lnbsharing-b09aaa00a58ec72d0331a01f31b3df16d43ce90b.tar.bz2 |
Version 1.1.24vdr-1.1.24
- Improved CAM handling (thanks to Reinhard Walter Buchner for a great deal of help
in debugging this). It is now possible to insert the CAM in any of the two slots,
to insert and remove it while VDR is running and even to have two CAMs inserted.
- Turning SI filtering off and on when switching channels.
- Timers are now processed even if an OSD menu is open (except for menus that
explicitly handle timers).
-rw-r--r-- | CONTRIBUTORS | 1 | ||||
-rw-r--r-- | HISTORY | 9 | ||||
-rw-r--r-- | channels.conf | 1 | ||||
-rw-r--r-- | ci.c | 314 | ||||
-rw-r--r-- | ci.h | 11 | ||||
-rw-r--r-- | config.h | 4 | ||||
-rw-r--r-- | dvbdevice.c | 51 | ||||
-rw-r--r-- | menu.c | 36 | ||||
-rw-r--r-- | timers.h | 7 | ||||
-rw-r--r-- | vdr.c | 6 |
10 files changed, 260 insertions, 180 deletions
diff --git a/CONTRIBUTORS b/CONTRIBUTORS index ae550b8..a6663d9 100644 --- a/CONTRIBUTORS +++ b/CONTRIBUTORS @@ -446,6 +446,7 @@ Oliver Endriss <o.endriss@gmx.de> Reinhard Walter Buchner <rw.buchner@freenet.de> for adding some satellites to 'sources.conf' for his help in testing tuning with "Motor-DiSEqC" + for his help in debugging CAM support Lauri Tischler <lauri.tischler@efore.fi> for helping to test and debug the new channel source and DiSEqC handling @@ -1947,3 +1947,12 @@ Video Disk Recorder Revision History - Fixed a new/delete malloc/free mismatch in ringbuffer.c (thanks to Stefan Huelswitt for reporting this one). - Improved CAM handling. + +2003-02-09: Version 1.1.24 + +- Improved CAM handling (thanks to Reinhard Walter Buchner for a great deal of help + in debugging this). It is now possible to insert the CAM in any of the two slots, + to insert and remove it while VDR is running and even to have two CAMs inserted. +- Turning SI filtering off and on when switching channels. +- Timers are now processed even if an OSD menu is open (except for menus that + explicitly handle timers). diff --git a/channels.conf b/channels.conf index 8d7f567..0dc0a28 100644 --- a/channels.conf +++ b/channels.conf @@ -150,6 +150,7 @@ QVC Germany:12552:v:S19.2E:22000:165:166:0:0:12100:0:0:0 Tele 5:12480:v:S19.2E:27500:1535:1536:0:0:51:0:0:0 :@201 Sky Sky One:106:h:S28.2E:0:160:80:0:301:222:0:0:0 +Sky One Mix:107:h:S28.2E:0:160:80:0:301:919:0:0:0 itv2:226:h:S28.2E:0:160:80:0:301:451:0:0:0 sci-fi:130:h:S28.2E:0:160:80:0:301:161:0:0:0 Paramount Comedy:127:h:S28.2E:0:160:80:0:301:185:0:0:0 @@ -4,15 +4,11 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: ci.c 1.3 2003/02/02 15:49:52 kls Exp $ + * $Id: ci.c 1.5 2003/02/09 14:47:57 kls Exp $ */ /* XXX TODO -- handle slots separately -- use return values - update CA descriptors in case they change -- dynamically react on CAM insert/remove -- implement CAM reset (per slot) XXX*/ #include "ci.h" @@ -215,7 +211,7 @@ int cTPDU::Write(int fd) int cTPDU::Read(int fd) { - size = read(fd, data, sizeof(data)); + size = safe_read(fd, data, sizeof(data)); if (size < 0) { esyslog("ERROR: %m"); size = 0; @@ -229,15 +225,15 @@ void cTPDU::Dump(bool Outgoing) { if (DumpTPDUDataTransfer) { #define MAX_DUMP 256 - printf("%s ", Outgoing ? "-->" : "<--"); + fprintf(stderr, "%s ", Outgoing ? "-->" : "<--"); for (int i = 0; i < size && i < MAX_DUMP; i++) - printf("%02X ", data[i]); - printf("%s\n", size >= MAX_DUMP ? "..." : ""); + fprintf(stderr, "%02X ", data[i]); + fprintf(stderr, "%s\n", size >= MAX_DUMP ? "..." : ""); if (!Outgoing) { - printf(" "); + fprintf(stderr, " "); for (int i = 0; i < size && i < MAX_DUMP; i++) - printf("%2c ", isprint(data[i]) ? data[i] : '.'); - printf("%s\n", size >= MAX_DUMP ? "..." : ""); + fprintf(stderr, "%2c ", isprint(data[i]) ? data[i] : '.'); + fprintf(stderr, "%s\n", size >= MAX_DUMP ? "..." : ""); } } } @@ -288,6 +284,7 @@ private: public: cCiTransportConnection(void); ~cCiTransportConnection(); + int Slot(void) const { return slot; } int SendData(int Length, const uint8_t *Data); int RecvData(void); const uint8_t *Data(int &Length); @@ -324,15 +321,15 @@ int cCiTransportConnection::SendTPDU(uint8_t Tag, int Length, const uint8_t *Dat return TPDU.Write(fd); } +#define CAM_READ_TIMEOUT 3500 // ms + int cCiTransportConnection::RecvTPDU(void) { - //XXX poll, timeout??? struct pollfd pfd[1]; pfd[0].fd = fd; pfd[0].events = POLLIN; lastResponse = ERROR; - if (poll(pfd, 1, 3500/*XXX*/) && (pfd[0].revents & POLLIN))//XXX - if (tpdu->Read(fd) == OK && tpdu->Tcid() == tcid) { + if (poll(pfd, 1, CAM_READ_TIMEOUT) && (pfd[0].revents & POLLIN) && tpdu->Read(fd) == OK && tpdu->Tcid() == tcid) { switch (state) { case stIDLE: break; case stCREATION: if (tpdu->Tag() == T_CTC_REPLY) { @@ -363,6 +360,10 @@ int cCiTransportConnection::RecvTPDU(void) break; } } + else { + esyslog("ERROR: CAM: Read failed: slot %d, tcid %d\n", slot, tcid); + Init(-1, slot, tcid); + } return lastResponse; } @@ -385,11 +386,8 @@ int cCiTransportConnection::SendData(int Length, const uint8_t *Data) int cCiTransportConnection::RecvData(void) { - if (SendTPDU(T_RCV) == OK) { - if (RecvTPDU() == OK) { - //XXX - } - } + if (SendTPDU(T_RCV) == OK) + return RecvTPDU(); return ERROR; } @@ -398,12 +396,26 @@ const uint8_t *cCiTransportConnection::Data(int &Length) return tpdu->Data(Length); } +#define MAX_CONNECT_RETRIES 20 + int cCiTransportConnection::CreateConnection(void) { if (state == stIDLE) { if (SendTPDU(T_CREATE_TC) == OK) { state = stCREATION; - return OK; + if (RecvTPDU() == T_CTC_REPLY) + return OK; + // the following is a workaround for CAMs that don't quite follow the specs... + else { + for (int i = 0; i < MAX_CONNECT_RETRIES; i++) { + dsyslog("CAM: retrying to establish connection"); + if (RecvTPDU() == T_CTC_REPLY) { + dsyslog("CAM: connection established"); + return OK; + } + } + return ERROR; + } } } return ERROR; @@ -412,9 +424,8 @@ int cCiTransportConnection::CreateConnection(void) int cCiTransportConnection::Poll(void) { if (state == stACTIVE) { - if (SendTPDU(T_DATA_LAST) == OK) { + if (SendTPDU(T_DATA_LAST) == OK) return RecvTPDU(); - } } return ERROR; } @@ -428,11 +439,12 @@ private: int fd; int numSlots; cCiTransportConnection tc[MAX_CI_CONNECT]; - bool ResetSlot(int Slot); public: cCiTransportLayer(int Fd, int NumSlots); - cCiTransportConnection *NewConnection(void); - int Process(void); + cCiTransportConnection *NewConnection(int Slot); + bool ResetSlot(int Slot); + bool ModuleReady(int Slot); + cCiTransportConnection *Process(int Slot); }; cCiTransportLayer::cCiTransportLayer(int Fd, int NumSlots) @@ -441,46 +453,28 @@ cCiTransportLayer::cCiTransportLayer(int Fd, int NumSlots) numSlots = NumSlots; for (int s = 0; s < numSlots; s++) ResetSlot(s); - for (int i = 0; i < MAX_CI_CONNECT; i++) - tc[i].Init(fd, 0/*XXX*/, i + 1); } -cCiTransportConnection *cCiTransportLayer::NewConnection(void) +cCiTransportConnection *cCiTransportLayer::NewConnection(int Slot) { for (int i = 0; i < MAX_CI_CONNECT; i++) { if (tc[i].State() == stIDLE) { - if (tc[i].CreateConnection() == OK) { - if (tc[i].RecvTPDU() == T_CTC_REPLY) - return &tc[i]; - } + dbgprotocol("Creating connection: slot %d, tcid %d\n", Slot, i + 1); + tc[i].Init(fd, Slot, i + 1); + if (tc[i].CreateConnection() == OK) + return &tc[i]; break; } } return NULL; } -#define CA_RESET_TIMEOUT 3 // seconds - bool cCiTransportLayer::ResetSlot(int Slot) { dbgprotocol("Resetting slot %d...", Slot); - ca_slot_info_t sinfo; - sinfo.num = Slot; if (ioctl(fd, CA_RESET, 1 << Slot) != -1) { - time_t t0 = time(NULL); - do { - if (ioctl(fd, CA_GET_SLOT_INFO, &sinfo) != -1) { - ioctl(fd, CA_GET_SLOT_INFO, &sinfo); - if ((sinfo.flags & CA_CI_MODULE_READY) != 0) { - dbgprotocol("ok.\n"); - return true; - } - } - else { - esyslog("ERROR: can't get info on CAM slot %d: %m", Slot); - break; - } - } while (time(NULL) - t0 < CA_RESET_TIMEOUT); + dbgprotocol("ok.\n"); + return true; } else esyslog("ERROR: can't reset CAM slot %d: %m", Slot); @@ -488,35 +482,55 @@ bool cCiTransportLayer::ResetSlot(int Slot) return false; } -int cCiTransportLayer::Process(void) +bool cCiTransportLayer::ModuleReady(int Slot) +{ + ca_slot_info_t sinfo; + sinfo.num = Slot; + if (ioctl(fd, CA_GET_SLOT_INFO, &sinfo) != -1) + return sinfo.flags & CA_CI_MODULE_READY; + else + esyslog("ERROR: can't get info on CAM slot %d: %m", Slot); + return false; +} + +cCiTransportConnection *cCiTransportLayer::Process(int Slot) { for (int i = 0; i < MAX_CI_CONNECT; i++) { cCiTransportConnection *Tc = &tc[i]; - if (Tc->State() == stACTIVE) { - if (!Tc->DataAvailable()) { - if (Tc->Poll() != OK) - ;//XXX continue; - } - switch (Tc->LastResponse()) { - case T_REQUEST_TC: - //XXX - break; - case T_DATA_MORE: - case T_DATA_LAST: - case T_CTC_REPLY: - case T_SB: - if (Tc->DataAvailable()) - Tc->RecvData(); - break; - case TIMEOUT: - case ERROR: - default: - //XXX Tc->state = stIDLE;//XXX Init()??? + if (Tc->Slot() == Slot) { + switch (Tc->State()) { + case stCREATION: + case stACTIVE: + if (!Tc->DataAvailable()) { + if (Tc->Poll() != OK) + ;//XXX continue; + } + switch (Tc->LastResponse()) { + case T_REQUEST_TC: + //XXX + break; + case T_DATA_MORE: + case T_DATA_LAST: + case T_CTC_REPLY: + case T_SB: + if (Tc->DataAvailable()) + Tc->RecvData(); + break; + case TIMEOUT: + case ERROR: + default: + //XXX Tc->state = stIDLE;//XXX Init()??? + return NULL; + break; + } + //XXX this will only work with _one_ transport connection per slot! + return Tc; break; + default: ; } } } - return OK; + return NULL; } // -- cCiSession ------------------------------------------------------------- @@ -608,6 +622,7 @@ protected: public: cCiSession(int SessionId, int ResourceId, cCiTransportConnection *Tc); virtual ~cCiSession(); + const cCiTransportConnection *Tc(void) { return tc; } int SessionId(void) { return sessionId; } int ResourceId(void) { return resourceId; } virtual bool Process(int Length = 0, const uint8_t *Data = NULL); @@ -1261,9 +1276,7 @@ cCiHandler::cCiHandler(int Fd, int NumSlots) for (int i = 0; i < MAX_CI_SESSION; i++) sessions[i] = NULL; tpl = new cCiTransportLayer(Fd, numSlots); - tc = tpl->NewConnection(); - if (!tc) - isyslog("CAM: no CAM detected"); + tc = NULL; } cCiHandler::~cCiHandler() @@ -1281,14 +1294,9 @@ cCiHandler *cCiHandler::CreateCiHandler(const char *FileName) if (ioctl(fd_ca, CA_GET_CAP, &Caps) == 0) { int NumSlots = Caps.slot_num; if (NumSlots > 0) { - dsyslog("CAM: found %d CAM slots", NumSlots); - if (Caps.slot_type == CA_CI_LINK) { - cCiHandler *CiHandler = new cCiHandler(fd_ca, NumSlots); - // drive the initial data exchange: - for (int i = 0; i < 20; i++) //XXX make this dynamic??? - CiHandler->Process(); - return CiHandler; - } + //XXX dsyslog("CAM: found %d CAM slots", NumSlots); // TODO let's do this only once we can be sure that there _really_ is a CAM adapter! + if (Caps.slot_type == CA_CI_LINK) + return new cCiHandler(fd_ca, NumSlots); else esyslog("ERROR: CAM doesn't support link layer interface"); } @@ -1320,7 +1328,7 @@ bool cCiHandler::Send(uint8_t Tag, int SessionId, int ResourceId, int Status) *(short *)p = htons(SessionId); p += 2; buffer[1] = p - buffer - 2; // length - return tc->SendData(p - buffer, buffer) == OK; + return tc && tc->SendData(p - buffer, buffer) == OK; } cCiSession *cCiHandler::GetSessionBySessionId(int SessionId) @@ -1332,10 +1340,10 @@ cCiSession *cCiHandler::GetSessionBySessionId(int SessionId) return NULL; } -cCiSession *cCiHandler::GetSessionByResourceId(int ResourceId) +cCiSession *cCiHandler::GetSessionByResourceId(int ResourceId, int Slot) { for (int i = 0; i < MAX_CI_SESSION; i++) { - if (sessions[i] && sessions[i]->ResourceId() == ResourceId) + if (sessions[i] && sessions[i]->Tc()->Slot() == Slot && sessions[i]->ResourceId() == ResourceId) return sessions[i]; } return NULL; @@ -1343,7 +1351,7 @@ cCiSession *cCiHandler::GetSessionByResourceId(int ResourceId) cCiSession *cCiHandler::CreateSession(int ResourceId) { - if (!GetSessionByResourceId(ResourceId)) { + if (!GetSessionByResourceId(ResourceId, tc->Slot())) { for (int i = 0; i < MAX_CI_SESSION; i++) { if (!sessions[i]) { switch (ResourceId) { @@ -1403,81 +1411,107 @@ bool cCiHandler::CloseSession(int SessionId) return false; } -bool cCiHandler::Process(void) -{ - if (tc) { - cMutexLock MutexLock(&mutex); - if (tpl->Process() == OK) { - int Length; - const uint8_t *Data = tc->Data(Length); - if (Data && Length > 1) { - switch (*Data) { - case ST_SESSION_NUMBER: if (Length > 4) { - int SessionId = ntohs(*(short *)&Data[2]); - cCiSession *Session = GetSessionBySessionId(SessionId); - if (Session) - return Session->Process(Length - 4, Data + 4); - else { - esyslog("ERROR: unknown session id: %d", SessionId); - return false; - } - } - break; - case ST_OPEN_SESSION_REQUEST: return OpenSession(Length, Data); - case ST_CLOSE_SESSION_REQUEST: if (Length == 4) - return CloseSession(ntohs(*(short *)&Data[2])); - break; - case ST_CREATE_SESSION_RESPONSE: //XXX fall through to default - case ST_CLOSE_SESSION_RESPONSE: //XXX fall through to default - default: esyslog("ERROR: unknown session tag: %02X", *Data); - return false; - } - return true; - } - for (int i = 0; i < MAX_CI_SESSION; i++) { - if (sessions[i]) - sessions[i]->Process();//XXX retval??? +int cCiHandler::CloseAllSessions(int Slot) +{ + int result = 0; + for (int i = 0; i < MAX_CI_SESSION; i++) { + if (sessions[i] && sessions[i]->Tc()->Slot() == Slot) { + CloseSession(sessions[i]->SessionId()); + result++; + } + } + return result; +} + +void cCiHandler::Process(void) +{ + cMutexLock MutexLock(&mutex); + for (int Slot = 0; Slot < numSlots; Slot++) { + tc = tpl->Process(Slot); + if (tc) { + int Length; + const uint8_t *Data = tc->Data(Length); + if (Data && Length > 1) { + switch (*Data) { + case ST_SESSION_NUMBER: if (Length > 4) { + int SessionId = ntohs(*(short *)&Data[2]); + cCiSession *Session = GetSessionBySessionId(SessionId); + if (Session) + Session->Process(Length - 4, Data + 4); + else + esyslog("ERROR: unknown session id: %d", SessionId); + } + break; + case ST_OPEN_SESSION_REQUEST: OpenSession(Length, Data); + break; + case ST_CLOSE_SESSION_REQUEST: if (Length == 4) + CloseSession(ntohs(*(short *)&Data[2])); + break; + case ST_CREATE_SESSION_RESPONSE: //XXX fall through to default + case ST_CLOSE_SESSION_RESPONSE: //XXX fall through to default + default: esyslog("ERROR: unknown session tag: %02X", *Data); + } } - } - } - return false; + } + else { + if (!CloseAllSessions(Slot)) { + if (tpl->ModuleReady(Slot)) { + dbgprotocol("Module ready in slot %d\n", Slot); + tpl->NewConnection(Slot); + } + } + } + } + for (int i = 0; i < MAX_CI_SESSION; i++) { + if (sessions[i]) + sessions[i]->Process(); + } } -bool cCiHandler::EnterMenu(void) +bool cCiHandler::EnterMenu(int Slot) { cMutexLock MutexLock(&mutex); - //XXX slots??? - cCiApplicationInformation *api = (cCiApplicationInformation *)GetSessionByResourceId(RI_APPLICATION_INFORMATION); + cCiApplicationInformation *api = (cCiApplicationInformation *)GetSessionByResourceId(RI_APPLICATION_INFORMATION, Slot); return api ? api->EnterMenu() : false; } cCiMenu *cCiHandler::GetMenu(void) { cMutexLock MutexLock(&mutex); - //XXX slots??? - cCiMMI *mmi = (cCiMMI *)GetSessionByResourceId(RI_MMI); - return mmi ? mmi->Menu() : NULL; + for (int Slot = 0; Slot < numSlots; Slot++) { + cCiMMI *mmi = (cCiMMI *)GetSessionByResourceId(RI_MMI, Slot); + if (mmi) + return mmi->Menu(); + } + return NULL; } cCiEnquiry *cCiHandler::GetEnquiry(void) { cMutexLock MutexLock(&mutex); - //XXX slots??? - cCiMMI *mmi = (cCiMMI *)GetSessionByResourceId(RI_MMI); - return mmi ? mmi->Enquiry() : NULL; + for (int Slot = 0; Slot < numSlots; Slot++) { + cCiMMI *mmi = (cCiMMI *)GetSessionByResourceId(RI_MMI, Slot); + if (mmi) + return mmi->Enquiry(); + } + return NULL; } bool cCiHandler::SetCaPmt(cCiCaPmt &CaPmt) { cMutexLock MutexLock(&mutex); - //XXX slots??? - cCiConditionalAccessSupport *cas = (cCiConditionalAccessSupport *)GetSessionByResourceId(RI_CONDITIONAL_ACCESS_SUPPORT); - return cas ? cas->SendPMT(CaPmt) : false; + bool result = false; + for (int Slot = 0; Slot < numSlots; Slot++) { + cCiConditionalAccessSupport *cas = (cCiConditionalAccessSupport *)GetSessionByResourceId(RI_CONDITIONAL_ACCESS_SUPPORT, Slot); + if (cas) + result |= cas->SendPMT(CaPmt); + } + return result; } -bool cCiHandler::Reset(void) +bool cCiHandler::Reset(int Slot) { cMutexLock MutexLock(&mutex); - //XXX slots??? - return false;//XXX not yet implemented + CloseAllSessions(Slot); + return tpl->ResetSlot(Slot); } @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: ci.h 1.1 2003/01/06 12:31:09 kls Exp $ + * $Id: ci.h 1.2 2003/02/09 11:44:00 kls Exp $ */ #ifndef __CI_H @@ -86,20 +86,21 @@ private: int ResourceIdToInt(const uint8_t *Data); bool Send(uint8_t Tag, int SessionId, int ResourceId = 0, int Status = -1); cCiSession *GetSessionBySessionId(int SessionId); - cCiSession *GetSessionByResourceId(int ResourceId); + cCiSession *GetSessionByResourceId(int ResourceId, int Slot); cCiSession *CreateSession(int ResourceId); bool OpenSession(int Length, const uint8_t *Data); bool CloseSession(int SessionId); + int CloseAllSessions(int Slot); cCiHandler(int Fd, int NumSlots); public: ~cCiHandler(); static cCiHandler *CreateCiHandler(const char *FileName); - bool Process(void); - bool EnterMenu(void); + void Process(void); + bool EnterMenu(int Slot); cCiMenu *GetMenu(void); cCiEnquiry *GetEnquiry(void); bool SetCaPmt(cCiCaPmt &CaPmt); - bool Reset(void); + bool Reset(int Slot); }; #endif //__CI_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.147 2003/01/26 19:50:19 kls Exp $ + * $Id: config.h 1.148 2003/02/08 10:25:44 kls Exp $ */ #ifndef __CONFIG_H @@ -19,7 +19,7 @@ #include "device.h" #include "tools.h" -#define VDRVERSION "1.1.23" +#define VDRVERSION "1.1.24" #define MAXPRIORITY 99 #define MAXLIFETIME 99 diff --git a/dvbdevice.c b/dvbdevice.c index 1ffe067..e587f69 100644 --- a/dvbdevice.c +++ b/dvbdevice.c @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: dvbdevice.c 1.42 2003/02/02 15:31:31 kls Exp $ + * $Id: dvbdevice.c 1.44 2003/02/09 12:41:14 kls Exp $ */ #include "dvbdevice.h" @@ -238,6 +238,7 @@ bool cDvbTuner::SetFrontend(void) void cDvbTuner::Action(void) { + time_t StartTime = time(NULL); dsyslog("tuner thread started on device %d (pid=%d)", cardIndex + 1, getpid()); active = true; while (active) { @@ -258,24 +259,28 @@ void cDvbTuner::Action(void) continue; } } - if (ciHandler && !caSet) {//XXX TODO update in case the CA descriptors have changed - uchar buffer[2048]; - int length = cSIProcessor::GetCaDescriptors(channel.Source(), channel.Frequency(), channel.Sid(), sizeof(buffer), buffer); - if (length > 0) { - cCiCaPmt CaPmt(channel.Sid()); - CaPmt.AddCaDescriptor(length, buffer); - if (channel.Vpid()) - CaPmt.AddPid(channel.Vpid()); - if (channel.Apid1()) - CaPmt.AddPid(channel.Apid1()); - if (channel.Apid2()) - CaPmt.AddPid(channel.Apid2()); - if (channel.Dpid1()) - CaPmt.AddPid(channel.Dpid1()); - caSet = ciHandler->SetCaPmt(CaPmt); + if (ciHandler) { + ciHandler->Process(); + if (!caSet) {//XXX TODO update in case the CA descriptors have changed + uchar buffer[2048]; + int length = cSIProcessor::GetCaDescriptors(channel.Source(), channel.Frequency(), channel.Sid(), sizeof(buffer), buffer); + if (length > 0) { + cCiCaPmt CaPmt(channel.Sid()); + CaPmt.AddCaDescriptor(length, buffer); + if (channel.Vpid()) + CaPmt.AddPid(channel.Vpid()); + if (channel.Apid1()) + CaPmt.AddPid(channel.Apid1()); + if (channel.Apid2()) + CaPmt.AddPid(channel.Apid2()); + if (channel.Dpid1()) + CaPmt.AddPid(channel.Dpid1()); + caSet = ciHandler->SetCaPmt(CaPmt); + } } } - newSet.TimedWait(mutex, 1000); + // in the beginning we loop more often to let the CAM connection start up fast + newSet.TimedWait(mutex, (ciHandler && (time(NULL) - StartTime < 20)) ? 100 : 1000); } dsyslog("tuner thread ended on device %d (pid=%d)", cardIndex + 1, getpid()); } @@ -617,10 +622,12 @@ bool cDvbDevice::SetChannelDevice(const cChannel *Channel, bool LiveView) StartTransferMode = false; #endif - // Stop setting system time: + // Stop SI filtering: - if (siProcessor) + if (siProcessor) { siProcessor->SetCurrentTransponder(0, 0); + siProcessor->SetStatus(false); + } // Turn off live PIDs if necessary: @@ -669,10 +676,12 @@ bool cDvbDevice::SetChannelDevice(const cChannel *Channel, bool LiveView) else if (StartTransferMode) cControl::Launch(new cTransferControl(this, Channel->Vpid(), Channel->Apid1(), Channel->Apid2(), Channel->Dpid1(), Channel->Dpid2())); - // Start setting system time: + // Start SI filtering: - if (siProcessor) + if (siProcessor) { siProcessor->SetCurrentTransponder(Channel->Source(), Channel->Frequency()); + siProcessor->SetStatus(true); + } return true; } @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: menu.c 1.232 2003/01/19 14:59:46 kls Exp $ + * $Id: menu.c 1.234 2003/02/09 12:55:38 kls Exp $ */ #include "menu.h" @@ -837,6 +837,7 @@ private: void SetFirstDayItem(void); public: cMenuEditTimer(int Index, bool New = false); + virtual ~cMenuEditTimer(); virtual eOSState ProcessKey(eKeys Key); }; @@ -860,6 +861,12 @@ cMenuEditTimer::cMenuEditTimer(int Index, bool New) Add(new cMenuEditStrItem( tr("File"), data.file, sizeof(data.file), tr(FileNameChars))); SetFirstDayItem(); } + Timers.IncBeingEdited(); +} + +cMenuEditTimer::~cMenuEditTimer() +{ + Timers.DecBeingEdited(); } void cMenuEditTimer::SetFirstDayItem(void) @@ -964,6 +971,7 @@ private: cTimer *CurrentTimer(void); public: cMenuTimers(void); + virtual ~cMenuTimers(); virtual eOSState ProcessKey(eKeys Key); }; @@ -980,6 +988,12 @@ cMenuTimers::cMenuTimers(void) if (Setup.SortTimers) Sort(); SetHelp(tr("Edit"), tr("New"), tr("Delete"), Setup.SortTimers ? tr("On/Off") : tr("Mark")); + Timers.IncBeingEdited(); +} + +cMenuTimers::~cMenuTimers() +{ + Timers.DecBeingEdited(); } cTimer *cMenuTimers::CurrentTimer(void) @@ -1537,6 +1551,7 @@ cMenuCam::cMenuCam(cCiMenu *CiMenu) Add(new cOsdItem(ciMenu->SubTitleText())); Add(new cOsdItem(ciMenu->BottomText())); Display(); + dsyslog("CAM: Menu - %s", ciMenu->TitleText()); } cMenuCam::~cMenuCam() @@ -1622,7 +1637,6 @@ cOsdObject *CamControl(void) if (Device) { cCiHandler *CiHandler = Device->CiHandler(); if (CiHandler) { - CiHandler->Process(); cCiMenu *CiMenu = CiHandler->GetMenu(); if (CiMenu) return new cMenuCam(CiMenu); @@ -2069,7 +2083,7 @@ class cMenuSetupCICAM : public cMenuSetupBase { private: int helpKeys; void SetHelpKeys(void); - cCiHandler *GetCurrentCiHandler(void); + cCiHandler *GetCurrentCiHandler(int *Slot = NULL); eOSState Menu(void); eOSState Reset(void); public: @@ -2091,9 +2105,11 @@ cMenuSetupCICAM::cMenuSetupCICAM(void) SetHelpKeys(); } -cCiHandler *cMenuSetupCICAM::GetCurrentCiHandler(void) +cCiHandler *cMenuSetupCICAM::GetCurrentCiHandler(int *Slot) { cDevice *Device = cDevice::GetDevice(Current() / 2); + if (Slot) + *Slot = Current() % 2; return Device ? Device->CiHandler() : NULL; } @@ -2112,8 +2128,9 @@ void cMenuSetupCICAM::SetHelpKeys(void) eOSState cMenuSetupCICAM::Menu(void) { - cCiHandler *CiHandler = GetCurrentCiHandler(); - if (CiHandler && CiHandler->EnterMenu()) + int Slot = 0; + cCiHandler *CiHandler = GetCurrentCiHandler(&Slot); + if (CiHandler && CiHandler->EnterMenu(Slot)) return osEnd; // the CAM menu will be executed explicitly from the main loop else Interface->Error(tr("Can't open CAM menu!")); @@ -2122,9 +2139,12 @@ eOSState cMenuSetupCICAM::Menu(void) eOSState cMenuSetupCICAM::Reset(void) { - cCiHandler *CiHandler = GetCurrentCiHandler(); - if (CiHandler && CiHandler->Reset()) + int Slot = 0; + cCiHandler *CiHandler = GetCurrentCiHandler(&Slot); + if (CiHandler && CiHandler->Reset(Slot)) { Interface->Info(tr("CAM has been reset")); + return osEnd; + } else Interface->Error(tr("Can't reset CAM!")); return osContinue; @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: timers.h 1.3 2002/11/24 11:50:56 kls Exp $ + * $Id: timers.h 1.4 2003/02/09 12:49:45 kls Exp $ */ #ifndef __TIMERS_H @@ -80,10 +80,15 @@ public: }; class cTimers : public cConfig<cTimer> { +private: + int beingEdited; public: cTimer *GetTimer(cTimer *Timer); cTimer *GetMatch(time_t t); cTimer *GetNextActiveTimer(void); + int BeingEdited(void) { return beingEdited; } + void IncBeingEdited(void) { beingEdited++; } + void DecBeingEdited(void) { beingEdited--; } }; extern cTimers Timers; @@ -22,7 +22,7 @@ * * The project's page is at http://www.cadsoft.de/people/kls/vdr * - * $Id: vdr.c 1.141 2003/01/26 11:56:31 kls Exp $ + * $Id: vdr.c 1.143 2003/02/09 13:13:42 kls Exp $ */ #include <getopt.h> @@ -459,7 +459,7 @@ int main(int argc, char *argv[]) LastChannel = cDevice::CurrentChannel(); } // Timers and Recordings: - if (!Menu) { + if (!Timers.BeingEdited()) { time_t Now = time(NULL); // must do both following calls with the exact same time! cRecordControls::Process(Now); cTimer *Timer = Timers.GetMatch(Now); @@ -469,7 +469,7 @@ int main(int argc, char *argv[]) } } // CAM control: - if (!Menu) + if (!Interface->IsOpen()) Menu = CamControl(); // User Input: cOsdObject *Interact = Menu ? Menu : cControl::Control(); |