mirror of
				https://github.com/vdr-projects/vdr.git
				synced 2025-03-01 10:50:46 +00:00 
			
		
		
		
	Implemented 'Link Layer' based CAM support
This commit is contained in:
		
							
								
								
									
										5
									
								
								HISTORY
									
									
									
									
									
								
							
							
						
						
									
										5
									
								
								HISTORY
									
									
									
									
									
								
							@@ -1899,7 +1899,7 @@ Video Disk Recorder Revision History
 | 
			
		||||
  See INSTALL for information how to do this. Some function descriptions have
 | 
			
		||||
  already been adapted to Doxygen, more will follow.
 | 
			
		||||
 | 
			
		||||
2002-12-23: Version 1.1.21
 | 
			
		||||
2003-01-06: Version 1.1.21
 | 
			
		||||
 | 
			
		||||
- Fixed the 'channels.conf' entries for "Studio Universal" and "Disney Channel".
 | 
			
		||||
- Fixed handling channels in the "Channels" menu in case there are ':@nnn' group
 | 
			
		||||
@@ -1908,3 +1908,6 @@ Video Disk Recorder Revision History
 | 
			
		||||
- Increased the timeout until an index file is considerd no longer to be written
 | 
			
		||||
  (sometimes in time shift with heavy system load the index file was closed too
 | 
			
		||||
  early by the replay thread).
 | 
			
		||||
- Implemented "Link Layer" based CAM support, which hopefully will solve the
 | 
			
		||||
  problems with CAMs we had in the past. To use this you need the driver version
 | 
			
		||||
  2002-01-06 or higher (with the new firmware supporting the "Link Layer" protocol).
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										4
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										4
									
								
								Makefile
									
									
									
									
									
								
							@@ -4,7 +4,7 @@
 | 
			
		||||
# See the main source file 'vdr.c' for copyright information and
 | 
			
		||||
# how to reach the author.
 | 
			
		||||
#
 | 
			
		||||
# $Id: Makefile 1.55 2002/12/15 15:15:55 kls Exp $
 | 
			
		||||
# $Id: Makefile 1.56 2003/01/06 12:28:09 kls Exp $
 | 
			
		||||
 | 
			
		||||
.DELETE_ON_ERROR:
 | 
			
		||||
 | 
			
		||||
@@ -32,7 +32,7 @@ INCLUDES = -I$(DVBDIR)/include
 | 
			
		||||
 | 
			
		||||
DTVLIB   = $(DTVDIR)/libdtv.a
 | 
			
		||||
 | 
			
		||||
OBJS = audio.o channels.o config.o cutter.o device.o diseqc.o dvbdevice.o dvbosd.o\
 | 
			
		||||
OBJS = audio.o channels.o ci.o config.o cutter.o device.o diseqc.o dvbdevice.o dvbosd.o\
 | 
			
		||||
       dvbplayer.o dvbspu.o eit.o eitscan.o font.o i18n.o interface.o keys.o\
 | 
			
		||||
       lirc.o menu.o menuitems.o osdbase.o osd.o player.o plugin.o rcu.o\
 | 
			
		||||
       receiver.o recorder.o recording.o remote.o remux.o ringbuffer.o sources.o\
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										105
									
								
								ci.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										105
									
								
								ci.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,105 @@
 | 
			
		||||
/*
 | 
			
		||||
 * ci.h: Common Interface
 | 
			
		||||
 *
 | 
			
		||||
 * 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 $
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef __CI_H
 | 
			
		||||
#define __CI_H
 | 
			
		||||
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include "thread.h"
 | 
			
		||||
 | 
			
		||||
class cCiMMI;
 | 
			
		||||
 | 
			
		||||
class cCiMenu {
 | 
			
		||||
  friend class cCiMMI;
 | 
			
		||||
private:
 | 
			
		||||
  enum { MAX_CIMENU_ENTRIES = 64 }; ///< XXX is there a specified maximum?
 | 
			
		||||
  cCiMMI *mmi;
 | 
			
		||||
  bool selectable;
 | 
			
		||||
  char *titleText;
 | 
			
		||||
  char *subTitleText;
 | 
			
		||||
  char *bottomText;
 | 
			
		||||
  char *entries[MAX_CIMENU_ENTRIES];
 | 
			
		||||
  int numEntries;
 | 
			
		||||
  bool AddEntry(char *s);
 | 
			
		||||
  cCiMenu(cCiMMI *MMI, bool Selectable);
 | 
			
		||||
public:
 | 
			
		||||
  ~cCiMenu();
 | 
			
		||||
  const char *TitleText(void) { return titleText; }
 | 
			
		||||
  const char *SubTitleText(void) { return subTitleText; }
 | 
			
		||||
  const char *BottomText(void) { return bottomText; }
 | 
			
		||||
  const char *Entry(int n) { return n < numEntries ? entries[n] : NULL; }
 | 
			
		||||
  int NumEntries(void) { return numEntries; }
 | 
			
		||||
  bool Selectable(void) { return selectable; }
 | 
			
		||||
  bool Select(int Index);
 | 
			
		||||
  bool Cancel(void);
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
class cCiEnquiry {
 | 
			
		||||
  friend class cCiMMI;
 | 
			
		||||
private:
 | 
			
		||||
  cCiMMI *mmi;
 | 
			
		||||
  char *text;
 | 
			
		||||
  bool blind;
 | 
			
		||||
  int expectedLength;
 | 
			
		||||
  cCiEnquiry(cCiMMI *MMI);
 | 
			
		||||
public:
 | 
			
		||||
  ~cCiEnquiry();
 | 
			
		||||
  const char *Text(void) { return text; }
 | 
			
		||||
  bool Blind(void) { return blind; }
 | 
			
		||||
  int ExpectedLength(void) { return expectedLength; }
 | 
			
		||||
  bool Reply(const char *s);
 | 
			
		||||
  bool Cancel(void);
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
class cCiCaPmt {
 | 
			
		||||
  friend class cCiConditionalAccessSupport;
 | 
			
		||||
private:
 | 
			
		||||
  int length;
 | 
			
		||||
  int esInfoLengthPos;
 | 
			
		||||
  uint8_t capmt[2048]; ///< XXX is there a specified maximum?
 | 
			
		||||
public:
 | 
			
		||||
  cCiCaPmt(int ProgramNumber);
 | 
			
		||||
  void AddPid(int Pid);
 | 
			
		||||
  void AddCaDescriptor(int Length, uint8_t *Data);
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
#define MAX_CI_SESSION  16 //XXX
 | 
			
		||||
 | 
			
		||||
class cCiSession;
 | 
			
		||||
class cCiTransportLayer;
 | 
			
		||||
class cCiTransportConnection;
 | 
			
		||||
 | 
			
		||||
class cCiHandler {
 | 
			
		||||
private:
 | 
			
		||||
  cMutex mutex;
 | 
			
		||||
  int numSlots;
 | 
			
		||||
  cCiSession *sessions[MAX_CI_SESSION];
 | 
			
		||||
  cCiTransportLayer *tpl;
 | 
			
		||||
  cCiTransportConnection *tc;
 | 
			
		||||
  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 *CreateSession(int ResourceId);
 | 
			
		||||
  bool OpenSession(int Length, const uint8_t *Data);
 | 
			
		||||
  bool CloseSession(int SessionId);
 | 
			
		||||
  cCiHandler(int Fd, int NumSlots);
 | 
			
		||||
public:
 | 
			
		||||
  ~cCiHandler();
 | 
			
		||||
  static cCiHandler *CreateCiHandler(const char *FileName);
 | 
			
		||||
  bool Process(void);
 | 
			
		||||
  bool EnterMenu(void);
 | 
			
		||||
  cCiMenu *GetMenu(void);
 | 
			
		||||
  cCiEnquiry *GetEnquiry(void);
 | 
			
		||||
  bool SetCaPmt(cCiCaPmt &CaPmt);
 | 
			
		||||
  bool Reset(void);
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
#endif //__CI_H
 | 
			
		||||
							
								
								
									
										4
									
								
								device.c
									
									
									
									
									
								
							
							
						
						
									
										4
									
								
								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.35 2002/11/10 10:17:57 kls Exp $
 | 
			
		||||
 * $Id: device.c 1.36 2003/01/03 15:41:14 kls Exp $
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "device.h"
 | 
			
		||||
@@ -47,6 +47,7 @@ cDevice::cDevice(void)
 | 
			
		||||
  mute = false;
 | 
			
		||||
  volume = Setup.CurrentVolume;
 | 
			
		||||
 | 
			
		||||
  ciHandler = NULL;
 | 
			
		||||
  player = NULL;
 | 
			
		||||
 | 
			
		||||
  playerDetached = false;
 | 
			
		||||
@@ -67,6 +68,7 @@ cDevice::~cDevice()
 | 
			
		||||
  Detach(player);
 | 
			
		||||
  for (int i = 0; i < MAXRECEIVERS; i++)
 | 
			
		||||
      Detach(receiver[i]);
 | 
			
		||||
  delete ciHandler;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void cDevice::SetUseDevice(int n)
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										10
									
								
								device.h
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								device.h
									
									
									
									
									
								
							@@ -4,12 +4,13 @@
 | 
			
		||||
 * See the main source file 'vdr.c' for copyright information and
 | 
			
		||||
 * how to reach the author.
 | 
			
		||||
 *
 | 
			
		||||
 * $Id: device.h 1.28 2002/12/15 14:40:11 kls Exp $
 | 
			
		||||
 * $Id: device.h 1.29 2003/01/03 15:43:48 kls Exp $
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef __DEVICE_H
 | 
			
		||||
#define __DEVICE_H
 | 
			
		||||
 | 
			
		||||
#include "ci.h"
 | 
			
		||||
#include "thread.h"
 | 
			
		||||
#include "tools.h"
 | 
			
		||||
 | 
			
		||||
@@ -211,6 +212,13 @@ protected:
 | 
			
		||||
         ///< Type indicates some special types of PIDs, which the device may
 | 
			
		||||
         ///< need to set in a specific way.
 | 
			
		||||
 | 
			
		||||
// Common Interface facilities:
 | 
			
		||||
 | 
			
		||||
protected:
 | 
			
		||||
  cCiHandler *ciHandler;
 | 
			
		||||
public:
 | 
			
		||||
  cCiHandler *CiHandler(void) { return ciHandler; }
 | 
			
		||||
 | 
			
		||||
// Image Grab facilities
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										48
									
								
								dvbdevice.c
									
									
									
									
									
								
							
							
						
						
									
										48
									
								
								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.40 2002/12/14 10:52:13 kls Exp $
 | 
			
		||||
 * $Id: dvbdevice.c 1.41 2003/01/06 14:44:27 kls Exp $
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "dvbdevice.h"
 | 
			
		||||
@@ -43,6 +43,7 @@ extern "C" {
 | 
			
		||||
#define DEV_DVB_DEMUX     "demux"
 | 
			
		||||
#define DEV_DVB_VIDEO     "video"
 | 
			
		||||
#define DEV_DVB_AUDIO     "audio"
 | 
			
		||||
#define DEV_DVB_CA        "ca"
 | 
			
		||||
 | 
			
		||||
static const char *DvbName(const char *Name, int n)
 | 
			
		||||
{
 | 
			
		||||
@@ -68,30 +69,34 @@ private:
 | 
			
		||||
  int fd_frontend;
 | 
			
		||||
  int cardIndex;
 | 
			
		||||
  fe_type_t frontendType;
 | 
			
		||||
  cCiHandler *ciHandler;
 | 
			
		||||
  cChannel channel;
 | 
			
		||||
  const char *diseqcCommands;
 | 
			
		||||
  bool active;
 | 
			
		||||
  eTunerStatus tunerStatus;
 | 
			
		||||
  bool caSet;
 | 
			
		||||
  cMutex mutex;
 | 
			
		||||
  cCondVar newSet;
 | 
			
		||||
  bool SetFrontend(void);
 | 
			
		||||
  virtual void Action(void);
 | 
			
		||||
public:
 | 
			
		||||
  cDvbTuner(int Fd_Frontend, int CardIndex, fe_type_t FrontendType);
 | 
			
		||||
  cDvbTuner(int Fd_Frontend, int CardIndex, fe_type_t FrontendType, cCiHandler *CiHandler);
 | 
			
		||||
  virtual ~cDvbTuner();
 | 
			
		||||
  bool IsTunedTo(const cChannel *Channel) const;
 | 
			
		||||
  void Set(const cChannel *Channel);
 | 
			
		||||
  void Set(const cChannel *Channel, bool Tune);
 | 
			
		||||
  bool Locked(void) { return tunerStatus == tsLocked; }
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
cDvbTuner::cDvbTuner(int Fd_Frontend, int CardIndex, fe_type_t FrontendType)
 | 
			
		||||
cDvbTuner::cDvbTuner(int Fd_Frontend, int CardIndex, fe_type_t FrontendType, cCiHandler *CiHandler)
 | 
			
		||||
{
 | 
			
		||||
  fd_frontend = Fd_Frontend;
 | 
			
		||||
  cardIndex = CardIndex;
 | 
			
		||||
  frontendType = FrontendType;
 | 
			
		||||
  ciHandler = CiHandler;
 | 
			
		||||
  diseqcCommands = NULL;
 | 
			
		||||
  active = false;
 | 
			
		||||
  tunerStatus = tsIdle;
 | 
			
		||||
  caSet = false;
 | 
			
		||||
  Start();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -108,11 +113,13 @@ bool cDvbTuner::IsTunedTo(const cChannel *Channel) const
 | 
			
		||||
  return tunerStatus != tsIdle && channel.Source() == Channel->Source() && channel.Frequency() == Channel->Frequency();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void cDvbTuner::Set(const cChannel *Channel)
 | 
			
		||||
void cDvbTuner::Set(const cChannel *Channel, bool Tune)
 | 
			
		||||
{
 | 
			
		||||
  cMutexLock MutexLock(&mutex);
 | 
			
		||||
  channel = *Channel;
 | 
			
		||||
  tunerStatus = tsSet;
 | 
			
		||||
  if (Tune)
 | 
			
		||||
     tunerStatus = tsSet;
 | 
			
		||||
  caSet = false;
 | 
			
		||||
  newSet.Broadcast();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -251,6 +258,30 @@ 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());
 | 
			
		||||
              if (channel.Vpid()) {
 | 
			
		||||
                 CaPmt.AddPid(channel.Vpid());
 | 
			
		||||
                 CaPmt.AddCaDescriptor(length, buffer);
 | 
			
		||||
                 }
 | 
			
		||||
              if (channel.Apid1()) {
 | 
			
		||||
                 CaPmt.AddPid(channel.Apid1());
 | 
			
		||||
                 CaPmt.AddCaDescriptor(length, buffer);
 | 
			
		||||
                 }
 | 
			
		||||
              if (channel.Apid2()) {
 | 
			
		||||
                 CaPmt.AddPid(channel.Apid2());
 | 
			
		||||
                 CaPmt.AddCaDescriptor(length, buffer);
 | 
			
		||||
                 }
 | 
			
		||||
              if (channel.Dpid1()) {
 | 
			
		||||
                 CaPmt.AddPid(channel.Dpid1());
 | 
			
		||||
                 CaPmt.AddCaDescriptor(length, buffer);
 | 
			
		||||
                 }
 | 
			
		||||
              caSet = ciHandler->SetCaPmt(CaPmt);
 | 
			
		||||
              }
 | 
			
		||||
           }
 | 
			
		||||
        newSet.TimedWait(mutex, 1000);
 | 
			
		||||
        }
 | 
			
		||||
  dsyslog("tuner thread ended on device %d (pid=%d)", cardIndex + 1, getpid());
 | 
			
		||||
@@ -291,7 +322,8 @@ cDvbDevice::cDvbDevice(int n)
 | 
			
		||||
     siProcessor = new cSIProcessor(DvbName(DEV_DVB_DEMUX, n));
 | 
			
		||||
     if (ioctl(fd_frontend, FE_GET_INFO, &feinfo) >= 0) {
 | 
			
		||||
        frontendType = feinfo.type;
 | 
			
		||||
        dvbTuner = new cDvbTuner(fd_frontend, CardIndex(), frontendType);
 | 
			
		||||
        ciHandler = cCiHandler::CreateCiHandler(DvbName(DEV_DVB_CA, n));
 | 
			
		||||
        dvbTuner = new cDvbTuner(fd_frontend, CardIndex(), frontendType, ciHandler);
 | 
			
		||||
        }
 | 
			
		||||
     else
 | 
			
		||||
        LOG_ERROR;
 | 
			
		||||
@@ -616,8 +648,8 @@ bool cDvbDevice::SetChannelDevice(const cChannel *Channel, bool LiveView)
 | 
			
		||||
     DelPid(pidHandles[ptDolby].pid);
 | 
			
		||||
     }
 | 
			
		||||
 | 
			
		||||
  dvbTuner->Set(Channel, DoTune);
 | 
			
		||||
  if (DoTune) {
 | 
			
		||||
     dvbTuner->Set(Channel);
 | 
			
		||||
     /*XXX do we still need this???
 | 
			
		||||
     if (!(status & FE_HAS_LOCK)) {
 | 
			
		||||
        esyslog("ERROR: channel %d not locked on DVB card %d!", Channel->Number(), CardIndex() + 1);
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										177
									
								
								eit.c
									
									
									
									
									
								
							
							
						
						
									
										177
									
								
								eit.c
									
									
									
									
									
								
							@@ -16,7 +16,7 @@
 | 
			
		||||
 *   the Free Software Foundation; either version 2 of the License, or     *
 | 
			
		||||
 *   (at your option) any later version.                                   *
 | 
			
		||||
 *                                                                         *
 | 
			
		||||
 * $Id: eit.c 1.61 2002/11/24 14:37:38 kls Exp $
 | 
			
		||||
 * $Id: eit.c 1.62 2003/01/06 14:10:37 kls Exp $
 | 
			
		||||
 ***************************************************************************/
 | 
			
		||||
 | 
			
		||||
#include "eit.h"
 | 
			
		||||
@@ -985,6 +985,68 @@ bool cEIT::IsPresentFollowing()
 | 
			
		||||
   return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// --- cCaDescriptor ---------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
class cCaDescriptor : public cListObject {
 | 
			
		||||
  friend class cCaDescriptors;
 | 
			
		||||
private:
 | 
			
		||||
  int source;
 | 
			
		||||
  int transponder;
 | 
			
		||||
  int serviceId;
 | 
			
		||||
  int caSystem;
 | 
			
		||||
  int length;
 | 
			
		||||
  uchar *data;
 | 
			
		||||
public:
 | 
			
		||||
  cCaDescriptor(int Source, int Transponder, int ServiceId, int CaSystem, int Length, uchar *Data);
 | 
			
		||||
  virtual ~cCaDescriptor();
 | 
			
		||||
  int Length(void) const { return length; }
 | 
			
		||||
  const uchar *Data(void) const { return data; }
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
cCaDescriptor::cCaDescriptor(int Source, int Transponder, int ServiceId, int CaSystem, int Length, uchar *Data)
 | 
			
		||||
{
 | 
			
		||||
  source = Source;
 | 
			
		||||
  transponder = Transponder;
 | 
			
		||||
  serviceId = ServiceId;
 | 
			
		||||
  caSystem = CaSystem;
 | 
			
		||||
  length = Length;
 | 
			
		||||
  data = MALLOC(uchar, length);
 | 
			
		||||
  memcpy(data, Data, length);
 | 
			
		||||
  /*//XXX just while debugging...
 | 
			
		||||
  char buffer[1024];
 | 
			
		||||
  char *q = buffer;
 | 
			
		||||
  q += sprintf(q, "CAM: %04X %5d %4d", source, transponder, serviceId);
 | 
			
		||||
  for (int i = 0; i < length; i++)
 | 
			
		||||
      q += sprintf(q, " %02X", data[i]);
 | 
			
		||||
  dsyslog(buffer);
 | 
			
		||||
  *///XXX
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
cCaDescriptor::~cCaDescriptor()
 | 
			
		||||
{
 | 
			
		||||
  free(data);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// --- cCaDescriptors --------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
class cCaDescriptors : public cList<cCaDescriptor> {
 | 
			
		||||
public:
 | 
			
		||||
  const cCaDescriptor *Get(int Source, int Transponder, int ServiceId, int CaSystem);
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
const cCaDescriptor *cCaDescriptors::Get(int Source, int Transponder, int ServiceId, int CaSystem)
 | 
			
		||||
{
 | 
			
		||||
  for (cCaDescriptor *ca = First(); ca; ca = Next(ca)) {
 | 
			
		||||
      if (ca->source == Source && ca->transponder == Transponder && ca->serviceId == ServiceId) {
 | 
			
		||||
         if (CaSystem == -1 || ca->caSystem == CaSystem)
 | 
			
		||||
            return ca;
 | 
			
		||||
         if (CaSystem < 0)
 | 
			
		||||
            CaSystem++;
 | 
			
		||||
         }
 | 
			
		||||
      }
 | 
			
		||||
  return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// --- cSIProcessor ----------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
#define MAX_FILTERS 20
 | 
			
		||||
@@ -993,6 +1055,8 @@ bool cEIT::IsPresentFollowing()
 | 
			
		||||
int cSIProcessor::numSIProcessors = 0;
 | 
			
		||||
cSchedules *cSIProcessor::schedules = NULL;
 | 
			
		||||
cMutex cSIProcessor::schedulesMutex;
 | 
			
		||||
cCaDescriptors *cSIProcessor::caDescriptors = NULL;
 | 
			
		||||
cMutex cSIProcessor::caDescriptorsMutex;
 | 
			
		||||
const char *cSIProcessor::epgDataFileName = EPGDATAFILENAME;
 | 
			
		||||
time_t cSIProcessor::lastDump = time(NULL);
 | 
			
		||||
 | 
			
		||||
@@ -1003,9 +1067,13 @@ cSIProcessor::cSIProcessor(const char *FileName)
 | 
			
		||||
   masterSIProcessor = numSIProcessors == 0; // the first one becomes the 'master'
 | 
			
		||||
   currentSource = 0;
 | 
			
		||||
   currentTransponder = 0;
 | 
			
		||||
   pmtIndex = 0;
 | 
			
		||||
   pmtPid = 0;
 | 
			
		||||
   filters = NULL;
 | 
			
		||||
   if (!numSIProcessors++) // the first one creates it
 | 
			
		||||
   if (!numSIProcessors++) { // the first one creates them
 | 
			
		||||
      schedules = new cSchedules;
 | 
			
		||||
      caDescriptors = new cCaDescriptors;
 | 
			
		||||
      }
 | 
			
		||||
   filters = (SIP_FILTER *)calloc(MAX_FILTERS, sizeof(SIP_FILTER));
 | 
			
		||||
   SetStatus(true);
 | 
			
		||||
   Start();
 | 
			
		||||
@@ -1019,8 +1087,10 @@ cSIProcessor::~cSIProcessor()
 | 
			
		||||
   Cancel(3);
 | 
			
		||||
   ShutDownFilters();
 | 
			
		||||
   free(filters);
 | 
			
		||||
   if (!--numSIProcessors) // the last one deletes it
 | 
			
		||||
   if (!--numSIProcessors) { // the last one deletes them
 | 
			
		||||
      delete schedules;
 | 
			
		||||
      delete caDescriptors;
 | 
			
		||||
      }
 | 
			
		||||
   free(fileName);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -1075,9 +1145,13 @@ const char *cSIProcessor::GetEpgDataFileName(void)
 | 
			
		||||
 | 
			
		||||
void cSIProcessor::SetStatus(bool On)
 | 
			
		||||
{
 | 
			
		||||
   LOCK_THREAD;
 | 
			
		||||
   ShutDownFilters();
 | 
			
		||||
   pmtIndex = 0;
 | 
			
		||||
   pmtPid = 0;
 | 
			
		||||
   if (On)
 | 
			
		||||
   {
 | 
			
		||||
      AddFilter(0x00, 0x00);  // PAT
 | 
			
		||||
      AddFilter(0x14, 0x70);  // TDT
 | 
			
		||||
      AddFilter(0x14, 0x73);  // TOT
 | 
			
		||||
      AddFilter(0x12, 0x4e);  // event info, actual TS, present/following
 | 
			
		||||
@@ -1089,6 +1163,8 @@ void cSIProcessor::SetStatus(bool On)
 | 
			
		||||
   }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#define PMT_SCAN_TIMEOUT  10 // seconds
 | 
			
		||||
 | 
			
		||||
/** use the vbi device to parse all relevant SI
 | 
			
		||||
information and let the classes corresponding
 | 
			
		||||
to the tables write their information to the disk */
 | 
			
		||||
@@ -1097,6 +1173,7 @@ void cSIProcessor::Action()
 | 
			
		||||
   dsyslog("EIT processing thread started (pid=%d)%s", getpid(), masterSIProcessor ? " - master" : "");
 | 
			
		||||
 | 
			
		||||
   time_t lastCleanup = time(NULL);
 | 
			
		||||
   time_t lastPmtScan = time(NULL);
 | 
			
		||||
 | 
			
		||||
   active = true;
 | 
			
		||||
 | 
			
		||||
@@ -1162,6 +1239,37 @@ void cSIProcessor::Action()
 | 
			
		||||
                     //dsyslog("Received pid 0x%02x with table ID 0x%02x and length of %04d\n", pid, buf[0], seclen);
 | 
			
		||||
                     switch (pid)
 | 
			
		||||
                     {
 | 
			
		||||
                        case 0x00:
 | 
			
		||||
                           if (buf[0] == 0x00)
 | 
			
		||||
                           {
 | 
			
		||||
                              LOCK_THREAD;
 | 
			
		||||
                              if (pmtPid && time(NULL) - lastPmtScan > PMT_SCAN_TIMEOUT) {
 | 
			
		||||
                                 DelFilter(pmtPid, 0x02);
 | 
			
		||||
                                 pmtPid = 0;
 | 
			
		||||
                                 pmtIndex++;
 | 
			
		||||
                                 lastPmtScan = time(NULL);
 | 
			
		||||
                                 }
 | 
			
		||||
                              if (!pmtPid) {
 | 
			
		||||
                                 cMutexLock MutexLock(&schedulesMutex); // since the xMem... stuff is not thread safe, we need to use a "global" mutex
 | 
			
		||||
                                 struct LIST *pat = siParsePAT(buf);
 | 
			
		||||
                                 if (pat) {
 | 
			
		||||
                                    int Index = 0;
 | 
			
		||||
                                    for (struct Program *prg = (struct Program *)pat->Head; prg; prg = (struct Program *)xSucc(prg)) {
 | 
			
		||||
                                        if (prg->ProgramID) {
 | 
			
		||||
                                           if (Index++ == pmtIndex) {
 | 
			
		||||
                                              pmtPid = prg->NetworkPID;
 | 
			
		||||
                                              AddFilter(pmtPid, 0x02);
 | 
			
		||||
                                              break;
 | 
			
		||||
                                              }
 | 
			
		||||
                                           }
 | 
			
		||||
                                        }
 | 
			
		||||
                                    if (!pmtPid)
 | 
			
		||||
                                       pmtIndex = 0;
 | 
			
		||||
                                    }
 | 
			
		||||
                                 xMemFreeAll(NULL);
 | 
			
		||||
                                 }
 | 
			
		||||
                           }
 | 
			
		||||
                           break;
 | 
			
		||||
                        case 0x14:
 | 
			
		||||
                           if (buf[0] == 0x70)
 | 
			
		||||
                           {
 | 
			
		||||
@@ -1188,7 +1296,28 @@ void cSIProcessor::Action()
 | 
			
		||||
                              dsyslog("Received stuffing section in EIT\n");
 | 
			
		||||
                           break;
 | 
			
		||||
 | 
			
		||||
                        default:
 | 
			
		||||
                        default: {
 | 
			
		||||
                           LOCK_THREAD;
 | 
			
		||||
                           if (pid == pmtPid && buf[0] == 0x02 && currentSource && currentTransponder) {
 | 
			
		||||
                              cMutexLock MutexLock(&schedulesMutex); // since the xMem... stuff is not thread safe, we need to use a "global" mutex
 | 
			
		||||
                              struct Pid *pi = siParsePMT(buf);
 | 
			
		||||
                              if (pi) {
 | 
			
		||||
                                 for (struct LIST *d = (struct LIST *)pi->Descriptors; d; d = (struct LIST *)xSucc(d)) {
 | 
			
		||||
                                     if (DescriptorTag(d) == DESCR_CA) {
 | 
			
		||||
                                        uchar *Data = ((ConditionalAccessDescriptor *)d)->Data;
 | 
			
		||||
                                        int CaSystem = (Data[2] << 8) | Data[3];
 | 
			
		||||
                                        if (!caDescriptors->Get(currentSource, currentTransponder, pi->ProgramID, CaSystem)) {
 | 
			
		||||
                                           cMutexLock MutexLock(&caDescriptorsMutex);
 | 
			
		||||
                                           caDescriptors->Add(new cCaDescriptor(currentSource, currentTransponder, pi->ProgramID, CaSystem, ((ConditionalAccessDescriptor *)d)->Amount, Data));
 | 
			
		||||
                                           }
 | 
			
		||||
                                        //XXX update???
 | 
			
		||||
                                        }
 | 
			
		||||
                                     }
 | 
			
		||||
                                 }
 | 
			
		||||
                              xMemFreeAll(NULL);
 | 
			
		||||
                              lastPmtScan = 0; // this triggers the next scan
 | 
			
		||||
                              }
 | 
			
		||||
                           }
 | 
			
		||||
                           break;
 | 
			
		||||
                     }
 | 
			
		||||
                  }
 | 
			
		||||
@@ -1229,7 +1358,7 @@ bool cSIProcessor::AddFilter(u_char pid, u_char tid)
 | 
			
		||||
               filters[a].inuse = true;
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
               esyslog("ERROR: can't set filter");
 | 
			
		||||
               esyslog("ERROR: can't set filter (pid=%d, tid=%02X)", pid, tid);
 | 
			
		||||
               close(filters[a].handle);
 | 
			
		||||
               return false;
 | 
			
		||||
            }
 | 
			
		||||
@@ -1248,6 +1377,21 @@ bool cSIProcessor::AddFilter(u_char pid, u_char tid)
 | 
			
		||||
   return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool cSIProcessor::DelFilter(u_char pid, u_char tid)
 | 
			
		||||
{
 | 
			
		||||
   for (int a = 0; a < MAX_FILTERS; a++)
 | 
			
		||||
   {
 | 
			
		||||
      if (filters[a].inuse && filters[a].pid == pid && filters[a].tid == tid)
 | 
			
		||||
      {
 | 
			
		||||
         close(filters[a].handle);
 | 
			
		||||
         // dsyslog("Deregistered filter handle %04x, pid = %02d, tid = %02d", filters[a].handle, filters[a].pid, filters[a].tid);
 | 
			
		||||
         filters[a].inuse = false;
 | 
			
		||||
         return true;
 | 
			
		||||
      }
 | 
			
		||||
   }
 | 
			
		||||
   return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**  */
 | 
			
		||||
bool cSIProcessor::ShutDownFilters(void)
 | 
			
		||||
{
 | 
			
		||||
@@ -1283,3 +1427,26 @@ void cSIProcessor::TriggerDump(void)
 | 
			
		||||
  cMutexLock MutexLock(&schedulesMutex);
 | 
			
		||||
  lastDump = 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int cSIProcessor::GetCaDescriptors(int Source, int Transponder, int ServiceId, int BufSize, uchar *Data)
 | 
			
		||||
{
 | 
			
		||||
  if (BufSize > 0 && Data) {
 | 
			
		||||
     cMutexLock MutexLock(&caDescriptorsMutex);
 | 
			
		||||
     int length = 0;
 | 
			
		||||
     for (int i = -1; ; i--) {
 | 
			
		||||
         const cCaDescriptor *d = caDescriptors->Get(Source, Transponder, ServiceId, i);
 | 
			
		||||
         if (d) {
 | 
			
		||||
            if (length + d->Length() <= BufSize) {
 | 
			
		||||
               memcpy(Data + length, d->Data(), d->Length());
 | 
			
		||||
               length += d->Length();
 | 
			
		||||
               }
 | 
			
		||||
            else
 | 
			
		||||
               return -1;
 | 
			
		||||
            }
 | 
			
		||||
         else
 | 
			
		||||
            break;
 | 
			
		||||
         }
 | 
			
		||||
     return length;
 | 
			
		||||
     }
 | 
			
		||||
  return -1;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										16
									
								
								eit.h
									
									
									
									
									
								
							
							
						
						
									
										16
									
								
								eit.h
									
									
									
									
									
								
							@@ -16,7 +16,7 @@
 | 
			
		||||
 *   the Free Software Foundation; either version 2 of the License, or     *
 | 
			
		||||
 *   (at your option) any later version.                                   *
 | 
			
		||||
 *                                                                         *
 | 
			
		||||
 * $Id: eit.h 1.22 2002/11/24 12:45:55 kls Exp $
 | 
			
		||||
 * $Id: eit.h 1.23 2003/01/04 10:12:54 kls Exp $
 | 
			
		||||
 ***************************************************************************/
 | 
			
		||||
 | 
			
		||||
#ifndef __EIT_H
 | 
			
		||||
@@ -134,21 +134,29 @@ typedef struct sip_filter {
 | 
			
		||||
 | 
			
		||||
}SIP_FILTER;
 | 
			
		||||
 | 
			
		||||
class cCaDescriptor;
 | 
			
		||||
class cCaDescriptors;
 | 
			
		||||
 | 
			
		||||
class cSIProcessor : public cThread {
 | 
			
		||||
private:
 | 
			
		||||
  static int numSIProcessors;
 | 
			
		||||
  static cSchedules *schedules;
 | 
			
		||||
  static cMutex schedulesMutex;
 | 
			
		||||
  static cCaDescriptors *caDescriptors;
 | 
			
		||||
  static cMutex caDescriptorsMutex;
 | 
			
		||||
  static const char *epgDataFileName;
 | 
			
		||||
  static time_t lastDump;
 | 
			
		||||
  bool masterSIProcessor;
 | 
			
		||||
  int currentSource;
 | 
			
		||||
  int currentTransponder;
 | 
			
		||||
  int pmtIndex;
 | 
			
		||||
  int pmtPid;
 | 
			
		||||
  SIP_FILTER *filters;
 | 
			
		||||
  char *fileName;
 | 
			
		||||
  bool active;
 | 
			
		||||
  void Action(void);
 | 
			
		||||
  bool AddFilter(u_char pid, u_char tid);
 | 
			
		||||
  bool DelFilter(u_char pid, u_char tid);
 | 
			
		||||
  bool ShutDownFilters(void);
 | 
			
		||||
public:
 | 
			
		||||
  cSIProcessor(const char *FileName);
 | 
			
		||||
@@ -159,6 +167,12 @@ public:
 | 
			
		||||
         // Caller must provide a cMutexLock which has to survive the entire
 | 
			
		||||
         // time the returned cSchedules is accessed. Once the cSchedules is no
 | 
			
		||||
         // longer used, the cMutexLock must be destroyed.
 | 
			
		||||
  static int GetCaDescriptors(int Source, int Transponder, int ServiceId, int BufSize, uchar *Data);
 | 
			
		||||
         ///< Gets all CA descriptors for a given channel.
 | 
			
		||||
         ///< Copies all available CA descriptors for the given Source, Transponder and ServiceId
 | 
			
		||||
         ///< into the provided buffer at Data (at most BufSize bytes).
 | 
			
		||||
         ///< \return Returns the number of bytes copied into Data (0 if no CA descriptors are
 | 
			
		||||
         ///< available), or -1 if BufSize was too small to hold all CA descriptors.
 | 
			
		||||
  static bool Read(FILE *f = NULL);
 | 
			
		||||
  static void Clear(void);
 | 
			
		||||
  void SetStatus(bool On);
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										82
									
								
								i18n.c
									
									
									
									
									
								
							
							
						
						
									
										82
									
								
								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.100 2002/11/10 12:32:30 kls Exp $
 | 
			
		||||
 * $Id: i18n.c 1.101 2003/01/06 12:16:28 kls Exp $
 | 
			
		||||
 *
 | 
			
		||||
 * Translations provided by:
 | 
			
		||||
 *
 | 
			
		||||
@@ -664,6 +664,38 @@ const tI18nPhrase Phrases[] = {
 | 
			
		||||
    "Suprascrie",
 | 
			
		||||
    "<EFBFBD>t<EFBFBD>rni",
 | 
			
		||||
  },
 | 
			
		||||
  { "Menu",
 | 
			
		||||
    "Men<EFBFBD>",
 | 
			
		||||
    "Meni",
 | 
			
		||||
    "Menu",
 | 
			
		||||
    "Menu",
 | 
			
		||||
    "Menu",
 | 
			
		||||
    "Menu",
 | 
			
		||||
    "Meny",
 | 
			
		||||
    "Valikko",
 | 
			
		||||
    "Menu",
 | 
			
		||||
    "Menu",
 | 
			
		||||
    "Menou",
 | 
			
		||||
    "Meny",
 | 
			
		||||
    "Meniu",
 | 
			
		||||
    "Men<EFBFBD>",
 | 
			
		||||
  },
 | 
			
		||||
  { "Reset",
 | 
			
		||||
    "Reset",
 | 
			
		||||
    "",//TODO
 | 
			
		||||
    "",//TODO
 | 
			
		||||
    "",//TODO
 | 
			
		||||
    "",//TODO
 | 
			
		||||
    "",//TODO
 | 
			
		||||
    "",//TODO
 | 
			
		||||
    "",//TODO
 | 
			
		||||
    "",//TODO
 | 
			
		||||
    "",//TODO
 | 
			
		||||
    "",//TODO
 | 
			
		||||
    "",//TODO
 | 
			
		||||
    "",//TODO
 | 
			
		||||
    "",//TODO
 | 
			
		||||
  },
 | 
			
		||||
  // Confirmations:
 | 
			
		||||
  { "Delete channel?",
 | 
			
		||||
    "Kanal l<>schen?",
 | 
			
		||||
@@ -1580,6 +1612,54 @@ const tI18nPhrase Phrases[] = {
 | 
			
		||||
    "Spatiu scazut pe disc!",
 | 
			
		||||
    "A merev lemez majdnem tele!",
 | 
			
		||||
  },
 | 
			
		||||
  { "Can't open CAM menu!",
 | 
			
		||||
    "CAM-Men<65> kann nicht ge<67>ffnet werden!",
 | 
			
		||||
    "",//TODO
 | 
			
		||||
    "",//TODO
 | 
			
		||||
    "",//TODO
 | 
			
		||||
    "",//TODO
 | 
			
		||||
    "",//TODO
 | 
			
		||||
    "",//TODO
 | 
			
		||||
    "",//TODO
 | 
			
		||||
    "",//TODO
 | 
			
		||||
    "",//TODO
 | 
			
		||||
    "",//TODO
 | 
			
		||||
    "",//TODO
 | 
			
		||||
    "",//TODO
 | 
			
		||||
    "",//TODO
 | 
			
		||||
  },
 | 
			
		||||
  { "Can't reset CAM!",
 | 
			
		||||
    "CAM-Reset fehlgeschlagen!",
 | 
			
		||||
    "",//TODO
 | 
			
		||||
    "",//TODO
 | 
			
		||||
    "",//TODO
 | 
			
		||||
    "",//TODO
 | 
			
		||||
    "",//TODO
 | 
			
		||||
    "",//TODO
 | 
			
		||||
    "",//TODO
 | 
			
		||||
    "",//TODO
 | 
			
		||||
    "",//TODO
 | 
			
		||||
    "",//TODO
 | 
			
		||||
    "",//TODO
 | 
			
		||||
    "",//TODO
 | 
			
		||||
    "",//TODO
 | 
			
		||||
  },
 | 
			
		||||
  { "CAM has been reset",
 | 
			
		||||
    "CAM wurde zur<75>ckgesetzt!",
 | 
			
		||||
    "",//TODO
 | 
			
		||||
    "",//TODO
 | 
			
		||||
    "",//TODO
 | 
			
		||||
    "",//TODO
 | 
			
		||||
    "",//TODO
 | 
			
		||||
    "",//TODO
 | 
			
		||||
    "",//TODO
 | 
			
		||||
    "",//TODO
 | 
			
		||||
    "",//TODO
 | 
			
		||||
    "",//TODO
 | 
			
		||||
    "",//TODO
 | 
			
		||||
    "",//TODO
 | 
			
		||||
    "",//TODO
 | 
			
		||||
  },
 | 
			
		||||
  // Setup pages:
 | 
			
		||||
  { "OSD",
 | 
			
		||||
    "OSD",
 | 
			
		||||
 
 | 
			
		||||
@@ -315,6 +315,29 @@ struct Descriptor {
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* ConditionalAccessDescriptor */
 | 
			
		||||
 | 
			
		||||
struct ConditionalAccessDescriptor {
 | 
			
		||||
   struct NODE          Node;
 | 
			
		||||
   unsigned short       Tag;
 | 
			
		||||
   unsigned short       Amount;        /* Data */
 | 
			
		||||
   unsigned char       *Data;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define CreateConditionalAccessDescriptor(descr, amount, data) \
 | 
			
		||||
   do \
 | 
			
		||||
   { \
 | 
			
		||||
      unsigned char *tmpptr; \
 | 
			
		||||
      \
 | 
			
		||||
      xMemAlloc (amount, &tmpptr); \
 | 
			
		||||
      memcpy (tmpptr, data, amount); \
 | 
			
		||||
      xCreateNode (((struct ConditionalAccessDescriptor *)descr), NULL); \
 | 
			
		||||
      ((struct ConditionalAccessDescriptor *)descr)->Tag = DESCR_CA; \
 | 
			
		||||
      ((struct ConditionalAccessDescriptor *)descr)->Amount = amount; \
 | 
			
		||||
      ((struct ConditionalAccessDescriptor *)descr)->Data = tmpptr; \
 | 
			
		||||
   } while (0)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* Iso639LanguageDescriptor */
 | 
			
		||||
 | 
			
		||||
struct Iso639LanguageDescriptor {
 | 
			
		||||
 
 | 
			
		||||
@@ -705,6 +705,12 @@ void siParseDescriptor (struct LIST *Descriptors, u_char *Buffer)
 | 
			
		||||
            HILO (CastTimeShiftedEventDescriptor(Ptr)->reference_event_id));
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
      case DESCR_CA:
 | 
			
		||||
         CreateConditionalAccessDescriptor (Descriptor,
 | 
			
		||||
            *(Ptr + 1) + 2, // we'll need the entire raw data!
 | 
			
		||||
            Ptr);
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
      case DESCR_ISO_639_LANGUAGE:
 | 
			
		||||
         CreateIso639LanguageDescriptor (Descriptor,
 | 
			
		||||
                   CastIso639LanguageDescriptor(Buffer)->lang_code1,
 | 
			
		||||
@@ -790,7 +796,6 @@ void siParseDescriptor (struct LIST *Descriptors, u_char *Buffer)
 | 
			
		||||
      case DESCR_DATA_STREAM_ALIGN:
 | 
			
		||||
      case DESCR_TARGET_BACKGRID:
 | 
			
		||||
      case DESCR_VIDEO_WINDOW:
 | 
			
		||||
      case DESCR_CA:
 | 
			
		||||
      case DESCR_SYSTEM_CLOCK:
 | 
			
		||||
      case DESCR_MULTIPLEX_BUFFER_UTIL:
 | 
			
		||||
      case DESCR_COPYRIGHT:
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										173
									
								
								menu.c
									
									
									
									
									
								
							
							
						
						
									
										173
									
								
								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.229 2002/12/22 12:40:43 kls Exp $
 | 
			
		||||
 * $Id: menu.c 1.230 2003/01/06 13:35:38 kls Exp $
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "menu.h"
 | 
			
		||||
@@ -1521,6 +1521,117 @@ eOSState cMenuCommands::ProcessKey(eKeys Key)
 | 
			
		||||
  return state;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// --- cMenuCam --------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
cMenuCam::cMenuCam(cCiMenu *CiMenu)
 | 
			
		||||
:cOsdMenu("")
 | 
			
		||||
{
 | 
			
		||||
  ciMenu = CiMenu;
 | 
			
		||||
  selected = false;
 | 
			
		||||
  if (ciMenu->Selectable())
 | 
			
		||||
     SetHasHotkeys();
 | 
			
		||||
  SetTitle(ciMenu->TitleText() ? ciMenu->TitleText() : "CAM");
 | 
			
		||||
  for (int i = 0; i < ciMenu->NumEntries(); i++)
 | 
			
		||||
      Add(new cOsdItem(hk(ciMenu->Entry(i))));
 | 
			
		||||
  //XXX implement a clean way of displaying this:
 | 
			
		||||
  Add(new cOsdItem(ciMenu->SubTitleText()));
 | 
			
		||||
  Add(new cOsdItem(ciMenu->BottomText()));
 | 
			
		||||
  Display();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
cMenuCam::~cMenuCam()
 | 
			
		||||
{
 | 
			
		||||
  if (!selected)
 | 
			
		||||
     ciMenu->Cancel();
 | 
			
		||||
  delete ciMenu;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
eOSState cMenuCam::Select(void)
 | 
			
		||||
{
 | 
			
		||||
  if (ciMenu->Selectable()) {
 | 
			
		||||
     ciMenu->Select(Current());
 | 
			
		||||
     selected = true;
 | 
			
		||||
     return osEnd;
 | 
			
		||||
     }
 | 
			
		||||
  return osContinue;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
eOSState cMenuCam::ProcessKey(eKeys Key)
 | 
			
		||||
{
 | 
			
		||||
  eOSState state = cOsdMenu::ProcessKey(Key);
 | 
			
		||||
 | 
			
		||||
  if (state == osUnknown) {
 | 
			
		||||
     switch (Key) {
 | 
			
		||||
       case kOk:     return Select();
 | 
			
		||||
       default: break;
 | 
			
		||||
       }
 | 
			
		||||
     }
 | 
			
		||||
  return state;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// --- cMenuCamEnquiry -------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
//XXX this is just quick and dirty - make this a separate display object
 | 
			
		||||
cMenuCamEnquiry::cMenuCamEnquiry(cCiEnquiry *CiEnquiry)
 | 
			
		||||
:cOsdMenu("")
 | 
			
		||||
{
 | 
			
		||||
  ciEnquiry = CiEnquiry;
 | 
			
		||||
  replied = false;
 | 
			
		||||
  SetTitle(ciEnquiry->Text() ? ciEnquiry->Text() : "CAM");
 | 
			
		||||
  Display();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
cMenuCamEnquiry::~cMenuCamEnquiry()
 | 
			
		||||
{
 | 
			
		||||
  if (!replied)
 | 
			
		||||
     ciEnquiry->Cancel();
 | 
			
		||||
  delete ciEnquiry;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
eOSState cMenuCamEnquiry::Reply(void)
 | 
			
		||||
{
 | 
			
		||||
  ciEnquiry->Reply("1234");//XXX implement actual user input
 | 
			
		||||
  replied = true;
 | 
			
		||||
  return osEnd;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
eOSState cMenuCamEnquiry::ProcessKey(eKeys Key)
 | 
			
		||||
{
 | 
			
		||||
  eOSState state = cOsdMenu::ProcessKey(Key);
 | 
			
		||||
 | 
			
		||||
  if (state == osUnknown) {
 | 
			
		||||
     switch (Key) {
 | 
			
		||||
       case kOk:     return Reply();
 | 
			
		||||
       default: break;
 | 
			
		||||
       }
 | 
			
		||||
     }
 | 
			
		||||
  return state;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// --- CamControl ------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
cOsdObject *CamControl(void)
 | 
			
		||||
{
 | 
			
		||||
  for (int d = 0; d < cDevice::NumDevices(); d++) {
 | 
			
		||||
      cDevice *Device = cDevice::GetDevice(d);
 | 
			
		||||
      if (Device) {
 | 
			
		||||
         cCiHandler *CiHandler = Device->CiHandler();
 | 
			
		||||
         if (CiHandler) {
 | 
			
		||||
            CiHandler->Process();
 | 
			
		||||
            cCiMenu *CiMenu = CiHandler->GetMenu();
 | 
			
		||||
            if (CiMenu)
 | 
			
		||||
               return new cMenuCam(CiMenu);
 | 
			
		||||
            else {
 | 
			
		||||
               cCiEnquiry *CiEnquiry = CiHandler->GetEnquiry();
 | 
			
		||||
               if (CiEnquiry)
 | 
			
		||||
                  return new cMenuCamEnquiry(CiEnquiry);
 | 
			
		||||
               }
 | 
			
		||||
            }
 | 
			
		||||
         }
 | 
			
		||||
      }
 | 
			
		||||
  return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// --- cMenuRecordingItem ----------------------------------------------------
 | 
			
		||||
 | 
			
		||||
class cMenuRecordingItem : public cOsdItem {
 | 
			
		||||
@@ -1950,6 +2061,12 @@ eOSState cMenuSetupLNB::ProcessKey(eKeys Key)
 | 
			
		||||
// --- cMenuSetupCICAM -------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
class cMenuSetupCICAM : public cMenuSetupBase {
 | 
			
		||||
private:
 | 
			
		||||
  int helpKeys;
 | 
			
		||||
  void SetHelpKeys(void);
 | 
			
		||||
  cCiHandler *GetCurrentCiHandler(void);
 | 
			
		||||
  eOSState Menu(void);
 | 
			
		||||
  eOSState Reset(void);
 | 
			
		||||
public:
 | 
			
		||||
  cMenuSetupCICAM(void);
 | 
			
		||||
  virtual eOSState ProcessKey(eKeys Key);
 | 
			
		||||
@@ -1957,6 +2074,7 @@ public:
 | 
			
		||||
 | 
			
		||||
cMenuSetupCICAM::cMenuSetupCICAM(void)
 | 
			
		||||
{
 | 
			
		||||
  helpKeys = -1;
 | 
			
		||||
  SetSection(tr("CICAM"));
 | 
			
		||||
  for (int d = 0; d < cDevice::NumDevices(); d++) {
 | 
			
		||||
      for (int i = 0; i < 2; i++) {
 | 
			
		||||
@@ -1965,6 +2083,46 @@ cMenuSetupCICAM::cMenuSetupCICAM(void)
 | 
			
		||||
          Add(new cMenuEditCaItem(buffer, &data.CaCaps[d][i]));
 | 
			
		||||
          }
 | 
			
		||||
      }
 | 
			
		||||
  SetHelpKeys();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
cCiHandler *cMenuSetupCICAM::GetCurrentCiHandler(void)
 | 
			
		||||
{
 | 
			
		||||
  cDevice *Device = cDevice::GetDevice(Current() / 2);
 | 
			
		||||
  return Device ? Device->CiHandler() : NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void cMenuSetupCICAM::SetHelpKeys(void)
 | 
			
		||||
{
 | 
			
		||||
  int NewHelpKeys = helpKeys;
 | 
			
		||||
  NewHelpKeys = GetCurrentCiHandler() ? 1 : 0;
 | 
			
		||||
  if (NewHelpKeys != helpKeys) {
 | 
			
		||||
     switch (NewHelpKeys) {
 | 
			
		||||
       case 0: SetHelp(NULL); break;
 | 
			
		||||
       case 1: SetHelp(tr("Menu"), tr("Reset"));
 | 
			
		||||
       }
 | 
			
		||||
     helpKeys = NewHelpKeys;
 | 
			
		||||
     }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
eOSState cMenuSetupCICAM::Menu(void)
 | 
			
		||||
{
 | 
			
		||||
  cCiHandler *CiHandler = GetCurrentCiHandler();
 | 
			
		||||
  if (CiHandler && CiHandler->EnterMenu())
 | 
			
		||||
     return osEnd; // the CAM menu will be executed explicitly from the main loop
 | 
			
		||||
  else
 | 
			
		||||
     Interface->Error(tr("Can't open CAM menu!"));
 | 
			
		||||
  return osContinue;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
eOSState cMenuSetupCICAM::Reset(void)
 | 
			
		||||
{
 | 
			
		||||
  cCiHandler *CiHandler = GetCurrentCiHandler();
 | 
			
		||||
  if (CiHandler && CiHandler->Reset())
 | 
			
		||||
     Interface->Info(tr("CAM has been reset"));
 | 
			
		||||
  else
 | 
			
		||||
     Interface->Error(tr("Can't reset CAM!"));
 | 
			
		||||
  return osContinue;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
eOSState cMenuSetupCICAM::ProcessKey(eKeys Key)
 | 
			
		||||
@@ -1973,6 +2131,19 @@ eOSState cMenuSetupCICAM::ProcessKey(eKeys Key)
 | 
			
		||||
 | 
			
		||||
  if (state == osBack && Key == kOk)
 | 
			
		||||
     cDevice::SetCaCaps();
 | 
			
		||||
  else if (state == osUnknown) {
 | 
			
		||||
     switch (Key) {
 | 
			
		||||
       case kRed:    if (helpKeys == 1)
 | 
			
		||||
                        return Menu();
 | 
			
		||||
                     break;
 | 
			
		||||
       case kGreen:  if (helpKeys == 1)
 | 
			
		||||
                        return Reset();
 | 
			
		||||
                     break;
 | 
			
		||||
       default: break;
 | 
			
		||||
       }
 | 
			
		||||
     }
 | 
			
		||||
  if (Key != kNone)
 | 
			
		||||
     SetHelpKeys();
 | 
			
		||||
  return state;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										27
									
								
								menu.h
									
									
									
									
									
								
							
							
						
						
									
										27
									
								
								menu.h
									
									
									
									
									
								
							@@ -4,12 +4,13 @@
 | 
			
		||||
 * See the main source file 'vdr.c' for copyright information and
 | 
			
		||||
 * how to reach the author.
 | 
			
		||||
 *
 | 
			
		||||
 * $Id: menu.h 1.51 2002/11/30 15:55:39 kls Exp $
 | 
			
		||||
 * $Id: menu.h 1.52 2003/01/06 10:04:05 kls Exp $
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef __MENU_H
 | 
			
		||||
#define __MENU_H
 | 
			
		||||
 | 
			
		||||
#include "ci.h"
 | 
			
		||||
#include "device.h"
 | 
			
		||||
#include "osd.h"
 | 
			
		||||
#include "dvbplayer.h"
 | 
			
		||||
@@ -58,6 +59,30 @@ public:
 | 
			
		||||
  eOSState ProcessKey(eKeys Key);
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
class cMenuCam : public cOsdMenu {
 | 
			
		||||
private:
 | 
			
		||||
  cCiMenu *ciMenu;
 | 
			
		||||
  bool selected;
 | 
			
		||||
  eOSState Select(void);
 | 
			
		||||
public:
 | 
			
		||||
  cMenuCam(cCiMenu *CiMenu);
 | 
			
		||||
  virtual ~cMenuCam();
 | 
			
		||||
  virtual eOSState ProcessKey(eKeys Key);
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
class cMenuCamEnquiry : public cOsdMenu {
 | 
			
		||||
private:
 | 
			
		||||
  cCiEnquiry *ciEnquiry;
 | 
			
		||||
  bool replied;
 | 
			
		||||
  eOSState Reply(void);
 | 
			
		||||
public:
 | 
			
		||||
  cMenuCamEnquiry(cCiEnquiry *CiEnquiry);
 | 
			
		||||
  virtual ~cMenuCamEnquiry();
 | 
			
		||||
  virtual eOSState ProcessKey(eKeys Key);
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
cOsdObject *CamControl(void);
 | 
			
		||||
 | 
			
		||||
class cMenuRecordingItem;
 | 
			
		||||
 | 
			
		||||
class cMenuRecordings : public cOsdMenu {
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										5
									
								
								vdr.c
									
									
									
									
									
								
							
							
						
						
									
										5
									
								
								vdr.c
									
									
									
									
									
								
							@@ -22,7 +22,7 @@
 | 
			
		||||
 *
 | 
			
		||||
 * The project's page is at http://www.cadsoft.de/people/kls/vdr
 | 
			
		||||
 *
 | 
			
		||||
 * $Id: vdr.c 1.139 2002/12/13 14:30:00 kls Exp $
 | 
			
		||||
 * $Id: vdr.c 1.140 2003/01/06 11:14:50 kls Exp $
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <getopt.h>
 | 
			
		||||
@@ -468,6 +468,9 @@ int main(int argc, char *argv[])
 | 
			
		||||
                 Timer->SetPending(true);
 | 
			
		||||
              }
 | 
			
		||||
           }
 | 
			
		||||
        // CAM control:
 | 
			
		||||
        if (!Menu)
 | 
			
		||||
           Menu = CamControl();
 | 
			
		||||
        // User Input:
 | 
			
		||||
        cOsdObject *Interact = Menu ? Menu : cControl::Control();
 | 
			
		||||
        eKeys key = Interface->GetKey(!Interact || !Interact->NeedsFastResponse());
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user