diff options
-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(); |