From 6de23d7d96720f89cbc864bbf504fe466e224497 Mon Sep 17 00:00:00 2001 From: Klaus Schmidinger Date: Sun, 21 Aug 2005 08:56:49 +0200 Subject: Now waiting at startup until all DVB devices are ready --- HISTORY | 6 +++++- ci.c | 18 +++++++++++++++++- ci.h | 5 ++++- device.c | 21 ++++++++++++++++++++- device.h | 13 ++++++++++++- dvbdevice.c | 11 ++++++++++- dvbdevice.h | 3 ++- vdr.c | 5 ++++- 8 files changed, 74 insertions(+), 8 deletions(-) diff --git a/HISTORY b/HISTORY index 25304454..dce1b460 100644 --- a/HISTORY +++ b/HISTORY @@ -3700,8 +3700,12 @@ Video Disk Recorder Revision History - Removed the VIDEO_STILLPICTURE_WORKS_WITH_VDR_FRAMES stuff from cDvbDevice::StillPicture(), since apparently the VIDEO_STILLPICTURE call works. -2005-08-20: Version 1.3.30 +2005-08-21: Version 1.3.30 - Improved responsiveness inside CAM menus. - Added handling of the 'Close MMI' tag to avoid error log messages with CAMs that actually use it. +- Now waiting at startup until all DVB devices are ready. This includes having + all CAMs initialized and ready to decrypt, so that no more "channel not + available" happens if VDR is started with the current channel being an encrypted + one, or a timer on such a channel hits right after starting VDR. diff --git a/ci.c b/ci.c index 9bca64df..b99c5495 100644 --- a/ci.c +++ b/ci.c @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: ci.c 1.25 2005/08/20 12:16:23 kls Exp $ + * $Id: ci.c 1.26 2005/08/20 15:27:35 kls Exp $ */ #include "ci.h" @@ -1354,6 +1354,8 @@ cCiHandler::cCiHandler(int Fd, int NumSlots) hasUserIO = false; for (int i = 0; i < MAX_CI_SESSION; i++) sessions[i] = NULL; + for (int i = 0; i < MAX_CI_SLOT; i++) + moduleReady[i] = false; tpl = new cCiTransportLayer(Fd, numSlots); tc = NULL; } @@ -1506,6 +1508,19 @@ int cCiHandler::CloseAllSessions(int Slot) return result; } +bool cCiHandler::Ready(void) +{ + cMutexLock MutexLock(&mutex); + for (int Slot = 0; Slot < numSlots; Slot++) { + if (moduleReady[Slot]) { + cCiConditionalAccessSupport *cas = (cCiConditionalAccessSupport *)GetSessionByResourceId(RI_CONDITIONAL_ACCESS_SUPPORT, Slot); + if (!cas || !*cas->GetCaSystemIds()) + return false; + } + } + return true; +} + bool cCiHandler::Process(void) { bool result = true; @@ -1543,6 +1558,7 @@ bool cCiHandler::Process(void) } else if (tpl->ModuleReady(Slot)) { dbgprotocol("Module ready in slot %d\n", Slot); + moduleReady[Slot] = true; tpl->NewConnection(Slot); } } diff --git a/ci.h b/ci.h index 7ae2b96e..9d718951 100644 --- a/ci.h +++ b/ci.h @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: ci.h 1.13 2004/02/08 14:36:23 kls Exp $ + * $Id: ci.h 1.14 2005/08/20 14:56:11 kls Exp $ */ #ifndef __CI_H @@ -77,6 +77,7 @@ public: }; #define MAX_CI_SESSION 16 //XXX +#define MAX_CI_SLOT 16 class cCiSession; class cCiTransportLayer; @@ -89,6 +90,7 @@ private: int numSlots; bool newCaSupport; bool hasUserIO; + bool moduleReady[MAX_CI_SLOT]; cCiSession *sessions[MAX_CI_SESSION]; cCiTransportLayer *tpl; cCiTransportConnection *tc; @@ -105,6 +107,7 @@ public: ~cCiHandler(); static cCiHandler *CreateCiHandler(const char *FileName); int NumSlots(void) { return numSlots; } + bool Ready(void); bool Process(void); bool HasUserIO(void) { return hasUserIO; } bool EnterMenu(int Slot); diff --git a/device.c b/device.c index 9fcc420b..2f614988 100644 --- a/device.c +++ b/device.c @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: device.c 1.105 2005/08/14 10:52:08 kls Exp $ + * $Id: device.c 1.106 2005/08/21 08:56:49 kls Exp $ */ #include "device.h" @@ -195,6 +195,20 @@ cDevice::~cDevice() delete pesAssembler; } +bool cDevice::WaitForAllDevicesReady(int Timeout) +{ + for (time_t t0 = time(NULL); time(NULL) - t0 < Timeout; ) { + bool ready = true; + for (int i = 0; i < numDevices; i++) { + if (device[i] && !device[i]->Ready()) + ready = false; + } + if (ready) + return true; + } + return false; +} + void cDevice::SetUseDevice(int n) { if (n < MAXDEVICES) @@ -1103,6 +1117,11 @@ int cDevice::CanShift(int Ca, int Priority, int UsedCards) const XXX*/ } +bool cDevice::Ready(void) +{ + return true; +} + int cDevice::ProvidesCa(const cChannel *Channel) const { int Ca = Channel->Ca(); diff --git a/device.h b/device.h index fc9ba3a1..c7075cbd 100644 --- a/device.h +++ b/device.h @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: device.h 1.61 2005/08/13 11:44:13 kls Exp $ + * $Id: device.h 1.62 2005/08/21 08:52:20 kls Exp $ */ #ifndef __DEVICE_H @@ -102,6 +102,12 @@ private: public: static int NumDevices(void) { return numDevices; } ///< Returns the total number of devices. + static bool WaitForAllDevicesReady(int Timeout = 0); + ///< Waits until all devices have become ready, or the given Timeout + ///< (seconds) has expired. While waiting, the Ready() function of each + ///< device is called in turn, until they all return true. + ///< \return True if all devices have become ready within the given + ///< timeout. static void SetUseDevice(int n); ///< Sets the 'useDevice' flag of the given device. ///< If this function is not called before initializing, all devices @@ -136,6 +142,11 @@ private: protected: cDevice(void); virtual ~cDevice(); + virtual bool Ready(void); + ///< Returns true if this device is ready. Devices with conditional + ///< access hardware may need some time until they are up and running. + ///< This function is called in a loop at startup until all devices + ///< are ready (see WaitForAllDevicesReady()). static int NextCardIndex(int n = 0); ///< Calculates the next card index. ///< Each device in a given machine must have a unique card index, which diff --git a/dvbdevice.c b/dvbdevice.c index ccd9a982..c47717bb 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.134 2005/08/15 14:05:23 kls Exp $ + * $Id: dvbdevice.c 1.135 2005/08/20 15:22:36 kls Exp $ */ #include "dvbdevice.h" @@ -478,6 +478,15 @@ bool cDvbDevice::HasDecoder(void) const return fd_video >= 0 && fd_audio >= 0; } +bool cDvbDevice::Ready(void) +{ + if (ciHandler) { + ciHandler->Process(); + return ciHandler->Ready(); + } + return true; +} + int cDvbDevice::ProvidesCa(const cChannel *Channel) const { if (Channel->Ca() >= 0x0100 && ciHandler) { diff --git a/dvbdevice.h b/dvbdevice.h index 4a705367..7da7e4f1 100644 --- a/dvbdevice.h +++ b/dvbdevice.h @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: dvbdevice.h 1.34 2005/02/20 11:17:07 kls Exp $ + * $Id: dvbdevice.h 1.35 2005/08/20 15:20:15 kls Exp $ */ #ifndef __DVBDEVICE_H @@ -42,6 +42,7 @@ protected: public: cDvbDevice(int n); virtual ~cDvbDevice(); + virtual bool Ready(void); virtual int ProvidesCa(const cChannel *Channel) const; virtual bool HasDecoder(void) const; diff --git a/vdr.c b/vdr.c index c8f57a2b..c98ee0d6 100644 --- a/vdr.c +++ b/vdr.c @@ -22,7 +22,7 @@ * * The project's page is at http://www.cadsoft.de/vdr * - * $Id: vdr.c 1.210 2005/08/20 11:24:42 kls Exp $ + * $Id: vdr.c 1.211 2005/08/21 08:47:06 kls Exp $ */ #include @@ -65,6 +65,7 @@ #define CHANNELSAVEDELTA 600 // seconds before saving channels.conf after automatic modifications #define LASTCAMMENUTIMEOUT 3 // seconds to run the main loop 'fast' after a CAM menu has been closed // in order to react on a possible new CAM menu as soon as possible +#define DEVICEREADYTIMEOUT 30 // seconds to wait until all devices are ready #define EXIT(v) { ExitCode = (v); goto Exit; } @@ -520,6 +521,8 @@ int main(int argc, char *argv[]) // Channel: + if (!cDevice::WaitForAllDevicesReady(DEVICEREADYTIMEOUT)) + dsyslog("not all devices ready after %d seconds", DEVICEREADYTIMEOUT); Channels.SwitchTo(Setup.CurrentChannel); if (MuteAudio) cDevice::PrimaryDevice()->ToggleMute(); -- cgit v1.2.3