mirror of
https://github.com/VDR4Arch/vdr.git
synced 2023-10-10 13:36:52 +02:00
Implemented 'Link Layer' based CAM support
This commit is contained in:
parent
43b582a04d
commit
4e15f6d658
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
|
See INSTALL for information how to do this. Some function descriptions have
|
||||||
already been adapted to Doxygen, more will follow.
|
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 the 'channels.conf' entries for "Studio Universal" and "Disney Channel".
|
||||||
- Fixed handling channels in the "Channels" menu in case there are ':@nnn' group
|
- 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
|
- 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
|
(sometimes in time shift with heavy system load the index file was closed too
|
||||||
early by the replay thread).
|
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
|
# See the main source file 'vdr.c' for copyright information and
|
||||||
# how to reach the author.
|
# 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:
|
.DELETE_ON_ERROR:
|
||||||
|
|
||||||
@ -32,7 +32,7 @@ INCLUDES = -I$(DVBDIR)/include
|
|||||||
|
|
||||||
DTVLIB = $(DTVDIR)/libdtv.a
|
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\
|
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\
|
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\
|
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
|
* See the main source file 'vdr.c' for copyright information and
|
||||||
* how to reach the author.
|
* 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"
|
#include "device.h"
|
||||||
@ -47,6 +47,7 @@ cDevice::cDevice(void)
|
|||||||
mute = false;
|
mute = false;
|
||||||
volume = Setup.CurrentVolume;
|
volume = Setup.CurrentVolume;
|
||||||
|
|
||||||
|
ciHandler = NULL;
|
||||||
player = NULL;
|
player = NULL;
|
||||||
|
|
||||||
playerDetached = false;
|
playerDetached = false;
|
||||||
@ -67,6 +68,7 @@ cDevice::~cDevice()
|
|||||||
Detach(player);
|
Detach(player);
|
||||||
for (int i = 0; i < MAXRECEIVERS; i++)
|
for (int i = 0; i < MAXRECEIVERS; i++)
|
||||||
Detach(receiver[i]);
|
Detach(receiver[i]);
|
||||||
|
delete ciHandler;
|
||||||
}
|
}
|
||||||
|
|
||||||
void cDevice::SetUseDevice(int n)
|
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
|
* See the main source file 'vdr.c' for copyright information and
|
||||||
* how to reach the author.
|
* 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
|
#ifndef __DEVICE_H
|
||||||
#define __DEVICE_H
|
#define __DEVICE_H
|
||||||
|
|
||||||
|
#include "ci.h"
|
||||||
#include "thread.h"
|
#include "thread.h"
|
||||||
#include "tools.h"
|
#include "tools.h"
|
||||||
|
|
||||||
@ -211,6 +212,13 @@ protected:
|
|||||||
///< Type indicates some special types of PIDs, which the device may
|
///< Type indicates some special types of PIDs, which the device may
|
||||||
///< need to set in a specific way.
|
///< need to set in a specific way.
|
||||||
|
|
||||||
|
// Common Interface facilities:
|
||||||
|
|
||||||
|
protected:
|
||||||
|
cCiHandler *ciHandler;
|
||||||
|
public:
|
||||||
|
cCiHandler *CiHandler(void) { return ciHandler; }
|
||||||
|
|
||||||
// Image Grab facilities
|
// Image Grab facilities
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
48
dvbdevice.c
48
dvbdevice.c
@ -4,7 +4,7 @@
|
|||||||
* See the main source file 'vdr.c' for copyright information and
|
* See the main source file 'vdr.c' for copyright information and
|
||||||
* how to reach the author.
|
* 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"
|
#include "dvbdevice.h"
|
||||||
@ -43,6 +43,7 @@ extern "C" {
|
|||||||
#define DEV_DVB_DEMUX "demux"
|
#define DEV_DVB_DEMUX "demux"
|
||||||
#define DEV_DVB_VIDEO "video"
|
#define DEV_DVB_VIDEO "video"
|
||||||
#define DEV_DVB_AUDIO "audio"
|
#define DEV_DVB_AUDIO "audio"
|
||||||
|
#define DEV_DVB_CA "ca"
|
||||||
|
|
||||||
static const char *DvbName(const char *Name, int n)
|
static const char *DvbName(const char *Name, int n)
|
||||||
{
|
{
|
||||||
@ -68,30 +69,34 @@ private:
|
|||||||
int fd_frontend;
|
int fd_frontend;
|
||||||
int cardIndex;
|
int cardIndex;
|
||||||
fe_type_t frontendType;
|
fe_type_t frontendType;
|
||||||
|
cCiHandler *ciHandler;
|
||||||
cChannel channel;
|
cChannel channel;
|
||||||
const char *diseqcCommands;
|
const char *diseqcCommands;
|
||||||
bool active;
|
bool active;
|
||||||
eTunerStatus tunerStatus;
|
eTunerStatus tunerStatus;
|
||||||
|
bool caSet;
|
||||||
cMutex mutex;
|
cMutex mutex;
|
||||||
cCondVar newSet;
|
cCondVar newSet;
|
||||||
bool SetFrontend(void);
|
bool SetFrontend(void);
|
||||||
virtual void Action(void);
|
virtual void Action(void);
|
||||||
public:
|
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();
|
virtual ~cDvbTuner();
|
||||||
bool IsTunedTo(const cChannel *Channel) const;
|
bool IsTunedTo(const cChannel *Channel) const;
|
||||||
void Set(const cChannel *Channel);
|
void Set(const cChannel *Channel, bool Tune);
|
||||||
bool Locked(void) { return tunerStatus == tsLocked; }
|
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;
|
fd_frontend = Fd_Frontend;
|
||||||
cardIndex = CardIndex;
|
cardIndex = CardIndex;
|
||||||
frontendType = FrontendType;
|
frontendType = FrontendType;
|
||||||
|
ciHandler = CiHandler;
|
||||||
diseqcCommands = NULL;
|
diseqcCommands = NULL;
|
||||||
active = false;
|
active = false;
|
||||||
tunerStatus = tsIdle;
|
tunerStatus = tsIdle;
|
||||||
|
caSet = false;
|
||||||
Start();
|
Start();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -108,11 +113,13 @@ bool cDvbTuner::IsTunedTo(const cChannel *Channel) const
|
|||||||
return tunerStatus != tsIdle && channel.Source() == Channel->Source() && channel.Frequency() == Channel->Frequency();
|
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);
|
cMutexLock MutexLock(&mutex);
|
||||||
channel = *Channel;
|
channel = *Channel;
|
||||||
tunerStatus = tsSet;
|
if (Tune)
|
||||||
|
tunerStatus = tsSet;
|
||||||
|
caSet = false;
|
||||||
newSet.Broadcast();
|
newSet.Broadcast();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -251,6 +258,30 @@ void cDvbTuner::Action(void)
|
|||||||
continue;
|
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);
|
newSet.TimedWait(mutex, 1000);
|
||||||
}
|
}
|
||||||
dsyslog("tuner thread ended on device %d (pid=%d)", cardIndex + 1, getpid());
|
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));
|
siProcessor = new cSIProcessor(DvbName(DEV_DVB_DEMUX, n));
|
||||||
if (ioctl(fd_frontend, FE_GET_INFO, &feinfo) >= 0) {
|
if (ioctl(fd_frontend, FE_GET_INFO, &feinfo) >= 0) {
|
||||||
frontendType = feinfo.type;
|
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
|
else
|
||||||
LOG_ERROR;
|
LOG_ERROR;
|
||||||
@ -616,8 +648,8 @@ bool cDvbDevice::SetChannelDevice(const cChannel *Channel, bool LiveView)
|
|||||||
DelPid(pidHandles[ptDolby].pid);
|
DelPid(pidHandles[ptDolby].pid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dvbTuner->Set(Channel, DoTune);
|
||||||
if (DoTune) {
|
if (DoTune) {
|
||||||
dvbTuner->Set(Channel);
|
|
||||||
/*XXX do we still need this???
|
/*XXX do we still need this???
|
||||||
if (!(status & FE_HAS_LOCK)) {
|
if (!(status & FE_HAS_LOCK)) {
|
||||||
esyslog("ERROR: channel %d not locked on DVB card %d!", Channel->Number(), CardIndex() + 1);
|
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 *
|
* the Free Software Foundation; either version 2 of the License, or *
|
||||||
* (at your option) any later version. *
|
* (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"
|
#include "eit.h"
|
||||||
@ -985,6 +985,68 @@ bool cEIT::IsPresentFollowing()
|
|||||||
return false;
|
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 ----------------------------------------------------------
|
// --- cSIProcessor ----------------------------------------------------------
|
||||||
|
|
||||||
#define MAX_FILTERS 20
|
#define MAX_FILTERS 20
|
||||||
@ -993,6 +1055,8 @@ bool cEIT::IsPresentFollowing()
|
|||||||
int cSIProcessor::numSIProcessors = 0;
|
int cSIProcessor::numSIProcessors = 0;
|
||||||
cSchedules *cSIProcessor::schedules = NULL;
|
cSchedules *cSIProcessor::schedules = NULL;
|
||||||
cMutex cSIProcessor::schedulesMutex;
|
cMutex cSIProcessor::schedulesMutex;
|
||||||
|
cCaDescriptors *cSIProcessor::caDescriptors = NULL;
|
||||||
|
cMutex cSIProcessor::caDescriptorsMutex;
|
||||||
const char *cSIProcessor::epgDataFileName = EPGDATAFILENAME;
|
const char *cSIProcessor::epgDataFileName = EPGDATAFILENAME;
|
||||||
time_t cSIProcessor::lastDump = time(NULL);
|
time_t cSIProcessor::lastDump = time(NULL);
|
||||||
|
|
||||||
@ -1003,9 +1067,13 @@ cSIProcessor::cSIProcessor(const char *FileName)
|
|||||||
masterSIProcessor = numSIProcessors == 0; // the first one becomes the 'master'
|
masterSIProcessor = numSIProcessors == 0; // the first one becomes the 'master'
|
||||||
currentSource = 0;
|
currentSource = 0;
|
||||||
currentTransponder = 0;
|
currentTransponder = 0;
|
||||||
|
pmtIndex = 0;
|
||||||
|
pmtPid = 0;
|
||||||
filters = NULL;
|
filters = NULL;
|
||||||
if (!numSIProcessors++) // the first one creates it
|
if (!numSIProcessors++) { // the first one creates them
|
||||||
schedules = new cSchedules;
|
schedules = new cSchedules;
|
||||||
|
caDescriptors = new cCaDescriptors;
|
||||||
|
}
|
||||||
filters = (SIP_FILTER *)calloc(MAX_FILTERS, sizeof(SIP_FILTER));
|
filters = (SIP_FILTER *)calloc(MAX_FILTERS, sizeof(SIP_FILTER));
|
||||||
SetStatus(true);
|
SetStatus(true);
|
||||||
Start();
|
Start();
|
||||||
@ -1019,8 +1087,10 @@ cSIProcessor::~cSIProcessor()
|
|||||||
Cancel(3);
|
Cancel(3);
|
||||||
ShutDownFilters();
|
ShutDownFilters();
|
||||||
free(filters);
|
free(filters);
|
||||||
if (!--numSIProcessors) // the last one deletes it
|
if (!--numSIProcessors) { // the last one deletes them
|
||||||
delete schedules;
|
delete schedules;
|
||||||
|
delete caDescriptors;
|
||||||
|
}
|
||||||
free(fileName);
|
free(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1075,9 +1145,13 @@ const char *cSIProcessor::GetEpgDataFileName(void)
|
|||||||
|
|
||||||
void cSIProcessor::SetStatus(bool On)
|
void cSIProcessor::SetStatus(bool On)
|
||||||
{
|
{
|
||||||
|
LOCK_THREAD;
|
||||||
ShutDownFilters();
|
ShutDownFilters();
|
||||||
|
pmtIndex = 0;
|
||||||
|
pmtPid = 0;
|
||||||
if (On)
|
if (On)
|
||||||
{
|
{
|
||||||
|
AddFilter(0x00, 0x00); // PAT
|
||||||
AddFilter(0x14, 0x70); // TDT
|
AddFilter(0x14, 0x70); // TDT
|
||||||
AddFilter(0x14, 0x73); // TOT
|
AddFilter(0x14, 0x73); // TOT
|
||||||
AddFilter(0x12, 0x4e); // event info, actual TS, present/following
|
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
|
/** use the vbi device to parse all relevant SI
|
||||||
information and let the classes corresponding
|
information and let the classes corresponding
|
||||||
to the tables write their information to the disk */
|
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" : "");
|
dsyslog("EIT processing thread started (pid=%d)%s", getpid(), masterSIProcessor ? " - master" : "");
|
||||||
|
|
||||||
time_t lastCleanup = time(NULL);
|
time_t lastCleanup = time(NULL);
|
||||||
|
time_t lastPmtScan = time(NULL);
|
||||||
|
|
||||||
active = true;
|
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);
|
//dsyslog("Received pid 0x%02x with table ID 0x%02x and length of %04d\n", pid, buf[0], seclen);
|
||||||
switch (pid)
|
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:
|
case 0x14:
|
||||||
if (buf[0] == 0x70)
|
if (buf[0] == 0x70)
|
||||||
{
|
{
|
||||||
@ -1188,7 +1296,28 @@ void cSIProcessor::Action()
|
|||||||
dsyslog("Received stuffing section in EIT\n");
|
dsyslog("Received stuffing section in EIT\n");
|
||||||
break;
|
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;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1229,7 +1358,7 @@ bool cSIProcessor::AddFilter(u_char pid, u_char tid)
|
|||||||
filters[a].inuse = true;
|
filters[a].inuse = true;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
esyslog("ERROR: can't set filter");
|
esyslog("ERROR: can't set filter (pid=%d, tid=%02X)", pid, tid);
|
||||||
close(filters[a].handle);
|
close(filters[a].handle);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -1248,6 +1377,21 @@ bool cSIProcessor::AddFilter(u_char pid, u_char tid)
|
|||||||
return false;
|
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)
|
bool cSIProcessor::ShutDownFilters(void)
|
||||||
{
|
{
|
||||||
@ -1283,3 +1427,26 @@ void cSIProcessor::TriggerDump(void)
|
|||||||
cMutexLock MutexLock(&schedulesMutex);
|
cMutexLock MutexLock(&schedulesMutex);
|
||||||
lastDump = 0;
|
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 *
|
* the Free Software Foundation; either version 2 of the License, or *
|
||||||
* (at your option) any later version. *
|
* (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
|
#ifndef __EIT_H
|
||||||
@ -134,21 +134,29 @@ typedef struct sip_filter {
|
|||||||
|
|
||||||
}SIP_FILTER;
|
}SIP_FILTER;
|
||||||
|
|
||||||
|
class cCaDescriptor;
|
||||||
|
class cCaDescriptors;
|
||||||
|
|
||||||
class cSIProcessor : public cThread {
|
class cSIProcessor : public cThread {
|
||||||
private:
|
private:
|
||||||
static int numSIProcessors;
|
static int numSIProcessors;
|
||||||
static cSchedules *schedules;
|
static cSchedules *schedules;
|
||||||
static cMutex schedulesMutex;
|
static cMutex schedulesMutex;
|
||||||
|
static cCaDescriptors *caDescriptors;
|
||||||
|
static cMutex caDescriptorsMutex;
|
||||||
static const char *epgDataFileName;
|
static const char *epgDataFileName;
|
||||||
static time_t lastDump;
|
static time_t lastDump;
|
||||||
bool masterSIProcessor;
|
bool masterSIProcessor;
|
||||||
int currentSource;
|
int currentSource;
|
||||||
int currentTransponder;
|
int currentTransponder;
|
||||||
|
int pmtIndex;
|
||||||
|
int pmtPid;
|
||||||
SIP_FILTER *filters;
|
SIP_FILTER *filters;
|
||||||
char *fileName;
|
char *fileName;
|
||||||
bool active;
|
bool active;
|
||||||
void Action(void);
|
void Action(void);
|
||||||
bool AddFilter(u_char pid, u_char tid);
|
bool AddFilter(u_char pid, u_char tid);
|
||||||
|
bool DelFilter(u_char pid, u_char tid);
|
||||||
bool ShutDownFilters(void);
|
bool ShutDownFilters(void);
|
||||||
public:
|
public:
|
||||||
cSIProcessor(const char *FileName);
|
cSIProcessor(const char *FileName);
|
||||||
@ -159,6 +167,12 @@ public:
|
|||||||
// Caller must provide a cMutexLock which has to survive the entire
|
// Caller must provide a cMutexLock which has to survive the entire
|
||||||
// time the returned cSchedules is accessed. Once the cSchedules is no
|
// time the returned cSchedules is accessed. Once the cSchedules is no
|
||||||
// longer used, the cMutexLock must be destroyed.
|
// 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 bool Read(FILE *f = NULL);
|
||||||
static void Clear(void);
|
static void Clear(void);
|
||||||
void SetStatus(bool On);
|
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
|
* See the main source file 'vdr.c' for copyright information and
|
||||||
* how to reach the author.
|
* 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:
|
* Translations provided by:
|
||||||
*
|
*
|
||||||
@ -664,6 +664,38 @@ const tI18nPhrase Phrases[] = {
|
|||||||
"Suprascrie",
|
"Suprascrie",
|
||||||
"Átírni",
|
"Átírni",
|
||||||
},
|
},
|
||||||
|
{ "Menu",
|
||||||
|
"Menü",
|
||||||
|
"Meni",
|
||||||
|
"Menu",
|
||||||
|
"Menu",
|
||||||
|
"Menu",
|
||||||
|
"Menu",
|
||||||
|
"Meny",
|
||||||
|
"Valikko",
|
||||||
|
"Menu",
|
||||||
|
"Menu",
|
||||||
|
"Menou",
|
||||||
|
"Meny",
|
||||||
|
"Meniu",
|
||||||
|
"Menü",
|
||||||
|
},
|
||||||
|
{ "Reset",
|
||||||
|
"Reset",
|
||||||
|
"",//TODO
|
||||||
|
"",//TODO
|
||||||
|
"",//TODO
|
||||||
|
"",//TODO
|
||||||
|
"",//TODO
|
||||||
|
"",//TODO
|
||||||
|
"",//TODO
|
||||||
|
"",//TODO
|
||||||
|
"",//TODO
|
||||||
|
"",//TODO
|
||||||
|
"",//TODO
|
||||||
|
"",//TODO
|
||||||
|
"",//TODO
|
||||||
|
},
|
||||||
// Confirmations:
|
// Confirmations:
|
||||||
{ "Delete channel?",
|
{ "Delete channel?",
|
||||||
"Kanal löschen?",
|
"Kanal löschen?",
|
||||||
@ -1580,6 +1612,54 @@ const tI18nPhrase Phrases[] = {
|
|||||||
"Spatiu scazut pe disc!",
|
"Spatiu scazut pe disc!",
|
||||||
"A merev lemez majdnem tele!",
|
"A merev lemez majdnem tele!",
|
||||||
},
|
},
|
||||||
|
{ "Can't open CAM menu!",
|
||||||
|
"CAM-Menü kann nicht geö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ückgesetzt!",
|
||||||
|
"",//TODO
|
||||||
|
"",//TODO
|
||||||
|
"",//TODO
|
||||||
|
"",//TODO
|
||||||
|
"",//TODO
|
||||||
|
"",//TODO
|
||||||
|
"",//TODO
|
||||||
|
"",//TODO
|
||||||
|
"",//TODO
|
||||||
|
"",//TODO
|
||||||
|
"",//TODO
|
||||||
|
"",//TODO
|
||||||
|
"",//TODO
|
||||||
|
},
|
||||||
// Setup pages:
|
// Setup pages:
|
||||||
{ "OSD",
|
{ "OSD",
|
||||||
"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 */
|
/* Iso639LanguageDescriptor */
|
||||||
|
|
||||||
struct Iso639LanguageDescriptor {
|
struct Iso639LanguageDescriptor {
|
||||||
|
@ -705,6 +705,12 @@ void siParseDescriptor (struct LIST *Descriptors, u_char *Buffer)
|
|||||||
HILO (CastTimeShiftedEventDescriptor(Ptr)->reference_event_id));
|
HILO (CastTimeShiftedEventDescriptor(Ptr)->reference_event_id));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case DESCR_CA:
|
||||||
|
CreateConditionalAccessDescriptor (Descriptor,
|
||||||
|
*(Ptr + 1) + 2, // we'll need the entire raw data!
|
||||||
|
Ptr);
|
||||||
|
break;
|
||||||
|
|
||||||
case DESCR_ISO_639_LANGUAGE:
|
case DESCR_ISO_639_LANGUAGE:
|
||||||
CreateIso639LanguageDescriptor (Descriptor,
|
CreateIso639LanguageDescriptor (Descriptor,
|
||||||
CastIso639LanguageDescriptor(Buffer)->lang_code1,
|
CastIso639LanguageDescriptor(Buffer)->lang_code1,
|
||||||
@ -790,7 +796,6 @@ void siParseDescriptor (struct LIST *Descriptors, u_char *Buffer)
|
|||||||
case DESCR_DATA_STREAM_ALIGN:
|
case DESCR_DATA_STREAM_ALIGN:
|
||||||
case DESCR_TARGET_BACKGRID:
|
case DESCR_TARGET_BACKGRID:
|
||||||
case DESCR_VIDEO_WINDOW:
|
case DESCR_VIDEO_WINDOW:
|
||||||
case DESCR_CA:
|
|
||||||
case DESCR_SYSTEM_CLOCK:
|
case DESCR_SYSTEM_CLOCK:
|
||||||
case DESCR_MULTIPLEX_BUFFER_UTIL:
|
case DESCR_MULTIPLEX_BUFFER_UTIL:
|
||||||
case DESCR_COPYRIGHT:
|
case DESCR_COPYRIGHT:
|
||||||
|
173
menu.c
173
menu.c
@ -4,7 +4,7 @@
|
|||||||
* See the main source file 'vdr.c' for copyright information and
|
* See the main source file 'vdr.c' for copyright information and
|
||||||
* how to reach the author.
|
* 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"
|
#include "menu.h"
|
||||||
@ -1521,6 +1521,117 @@ eOSState cMenuCommands::ProcessKey(eKeys Key)
|
|||||||
return state;
|
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 ----------------------------------------------------
|
// --- cMenuRecordingItem ----------------------------------------------------
|
||||||
|
|
||||||
class cMenuRecordingItem : public cOsdItem {
|
class cMenuRecordingItem : public cOsdItem {
|
||||||
@ -1950,6 +2061,12 @@ eOSState cMenuSetupLNB::ProcessKey(eKeys Key)
|
|||||||
// --- cMenuSetupCICAM -------------------------------------------------------
|
// --- cMenuSetupCICAM -------------------------------------------------------
|
||||||
|
|
||||||
class cMenuSetupCICAM : public cMenuSetupBase {
|
class cMenuSetupCICAM : public cMenuSetupBase {
|
||||||
|
private:
|
||||||
|
int helpKeys;
|
||||||
|
void SetHelpKeys(void);
|
||||||
|
cCiHandler *GetCurrentCiHandler(void);
|
||||||
|
eOSState Menu(void);
|
||||||
|
eOSState Reset(void);
|
||||||
public:
|
public:
|
||||||
cMenuSetupCICAM(void);
|
cMenuSetupCICAM(void);
|
||||||
virtual eOSState ProcessKey(eKeys Key);
|
virtual eOSState ProcessKey(eKeys Key);
|
||||||
@ -1957,6 +2074,7 @@ public:
|
|||||||
|
|
||||||
cMenuSetupCICAM::cMenuSetupCICAM(void)
|
cMenuSetupCICAM::cMenuSetupCICAM(void)
|
||||||
{
|
{
|
||||||
|
helpKeys = -1;
|
||||||
SetSection(tr("CICAM"));
|
SetSection(tr("CICAM"));
|
||||||
for (int d = 0; d < cDevice::NumDevices(); d++) {
|
for (int d = 0; d < cDevice::NumDevices(); d++) {
|
||||||
for (int i = 0; i < 2; i++) {
|
for (int i = 0; i < 2; i++) {
|
||||||
@ -1965,6 +2083,46 @@ cMenuSetupCICAM::cMenuSetupCICAM(void)
|
|||||||
Add(new cMenuEditCaItem(buffer, &data.CaCaps[d][i]));
|
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)
|
eOSState cMenuSetupCICAM::ProcessKey(eKeys Key)
|
||||||
@ -1973,6 +2131,19 @@ eOSState cMenuSetupCICAM::ProcessKey(eKeys Key)
|
|||||||
|
|
||||||
if (state == osBack && Key == kOk)
|
if (state == osBack && Key == kOk)
|
||||||
cDevice::SetCaCaps();
|
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;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
27
menu.h
27
menu.h
@ -4,12 +4,13 @@
|
|||||||
* See the main source file 'vdr.c' for copyright information and
|
* See the main source file 'vdr.c' for copyright information and
|
||||||
* how to reach the author.
|
* 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
|
#ifndef __MENU_H
|
||||||
#define __MENU_H
|
#define __MENU_H
|
||||||
|
|
||||||
|
#include "ci.h"
|
||||||
#include "device.h"
|
#include "device.h"
|
||||||
#include "osd.h"
|
#include "osd.h"
|
||||||
#include "dvbplayer.h"
|
#include "dvbplayer.h"
|
||||||
@ -58,6 +59,30 @@ public:
|
|||||||
eOSState ProcessKey(eKeys Key);
|
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 cMenuRecordingItem;
|
||||||
|
|
||||||
class cMenuRecordings : public cOsdMenu {
|
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
|
* 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>
|
#include <getopt.h>
|
||||||
@ -468,6 +468,9 @@ int main(int argc, char *argv[])
|
|||||||
Timer->SetPending(true);
|
Timer->SetPending(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// CAM control:
|
||||||
|
if (!Menu)
|
||||||
|
Menu = CamControl();
|
||||||
// User Input:
|
// User Input:
|
||||||
cOsdObject *Interact = Menu ? Menu : cControl::Control();
|
cOsdObject *Interact = Menu ? Menu : cControl::Control();
|
||||||
eKeys key = Interface->GetKey(!Interact || !Interact->NeedsFastResponse());
|
eKeys key = Interface->GetKey(!Interact || !Interact->NeedsFastResponse());
|
||||||
|
Loading…
Reference in New Issue
Block a user