Version 1.1.28

- Using masks in EIT filtering to reduce the number of filters (thanks to Andreas
  Schultz).
- Fixed handling Ca descriptors (thanks to Stefan Huelswitt).
- Now only those Ca descriptors are sent to a CAM that are actually understood
  by that CAM.
- Re-enabled CAM communication during replay and on non-Ca channels. This requires
  a DVB driver with firmware version 2613 or later.
- It is now possible to do simultaneous recording and replay with a single DVB
  card, even with encrypted channels. This requires the use of the Link Layer
  firmware, version 2613 or higher; the -icam firmware is still limited to live
  encrypted channels only. Finally we have time shift for encrypted channels on
  single card systems!
- Enhanced detection of pending user I/O from CAMs to avoid sluggish reaction
  to remote control keypresses.
- Implemented "pause live video". You can now press "Menu/Yellow" or "Pause" on
  your remote control while watching live video to start an instant recording
  of the current programme and immediately start replaying that recording.
This commit is contained in:
Klaus Schmidinger 2003-04-21 18:00:00 +02:00
parent 9f91980146
commit 21a52ccb6d
15 changed files with 240 additions and 138 deletions

View File

@ -196,6 +196,7 @@ Andreas Schultz <aschultz@warp10.net>
for pointing out some unnecessary #includes in eit.c and a problem with for pointing out some unnecessary #includes in eit.c and a problem with
cMenuRecordings::Del(), which caused warnings with gcc-3.2 cMenuRecordings::Del(), which caused warnings with gcc-3.2
for suggesting a Make.config file for suggesting a Make.config file
for making EIT filtering use masks to reduce the number of filters
Aaron Holtzman Aaron Holtzman
for writing 'ac3dec' for writing 'ac3dec'

20
HISTORY
View File

@ -2033,3 +2033,23 @@ Video Disk Recorder Revision History
applies to the RCU remote control in case of errors during startup. applies to the RCU remote control in case of errors during startup.
- Fixed handling of Ca parameters with values <= MAXDEVICES, which don't indicate - Fixed handling of Ca parameters with values <= MAXDEVICES, which don't indicate
an actual encrypted channel (thanks to Stefan Huelswitt for reporting this one). an actual encrypted channel (thanks to Stefan Huelswitt for reporting this one).
2003-04-21: Version 1.1.28
- Using masks in EIT filtering to reduce the number of filters (thanks to Andreas
Schultz).
- Fixed handling Ca descriptors (thanks to Stefan Huelswitt).
- Now only those Ca descriptors are sent to a CAM that are actually understood
by that CAM.
- Re-enabled CAM communication during replay and on non-Ca channels. This requires
a DVB driver with firmware version 2613 or later.
- It is now possible to do simultaneous recording and replay with a single DVB
card, even with encrypted channels. This requires the use of the Link Layer
firmware, version 2613 or higher; the -icam firmware is still limited to live
encrypted channels only. Finally we have time shift for encrypted channels on
single card systems!
- Enhanced detection of pending user I/O from CAMs to avoid sluggish reaction
to remote control keypresses.
- Implemented "pause live video". You can now press "Menu/Yellow" or "Pause" on
your remote control while watching live video to start an instant recording
of the current programme and immediately start replaying that recording.

18
MANUAL
View File

@ -19,7 +19,7 @@ Video Disk Recorder User's Manual
Back - Menu off VDR menu VDR menu Discard VDR menu Recordings menu Back - Menu off VDR menu VDR menu Discard VDR menu Recordings menu
Red - Record Edit Edit ABC/abc Play/Commands(2) Jump Red - Record Edit Edit ABC/abc Play/Commands(2) Jump
Green - Language New New Ins/Ovr Rewind Skip -60s Green - Language New New Ins/Ovr Rewind Skip -60s
Yellow - - Delete Delete Delete Delete Skip +60s Yellow - Pause live Delete Delete Delete Delete Skip +60s
Blue - Stop/Resume Mark On/Off(1) - Summary Stop Blue - Stop/Resume Mark On/Off(1) - Summary Stop
0..9 Ch select - - - Numeric inp. Exec cmd(2) Editing 0..9 Ch select - - - Numeric inp. Exec cmd(2) Editing
@ -31,7 +31,7 @@ Video Disk Recorder User's Manual
following functions: following functions:
Play resume normal replay Play resume normal replay
Pause pause replay Pause pause replay or live video
Stop stop replay Stop stop replay
Record instant recording Record instant recording
FastFwd fast forward FastFwd fast forward
@ -191,6 +191,20 @@ Video Disk Recorder User's Manual
Stop instant recording by pressing the "Menu" button and selecting Stop instant recording by pressing the "Menu" button and selecting
"Stop Recording", or by disabling the timer. "Stop Recording", or by disabling the timer.
* Pausing live video
If you want to pause the live programme you are just watching, simple press
"Menu/Yellow" or "Pause" on your remote control. VDR will start an instant
recording of the current channel (just as if you had pressed "Menu/Red" or
"Record") and immediately begin replaying that recording. Replay will be
put into "pause" mode, so you can attend to whatever it was that disturbed
your live viewing session. Once you're back, simply press the "Up" or "Play"
button and you'll be watching the current channel in time shift mode, right
from the point where you left off. The instant recording VDR has started
will use the same parameters for priority, lifetime and recording duration
as any other instant recording, so by default it will record 3 hours (which
should be enough for any normal broadcast).
* Replaying a Recording * Replaying a Recording
All recordings are listed in the "Recordings" menu. Browse through the All recordings are listed in the "Recordings" menu. Browse through the

View File

@ -59,7 +59,7 @@ Studio Universal:12071:h:S19.2E:27500:2047:2048:0:101:36:0:0:0
Premiere Serie:12031:h:S19.2E:27500:1023:1024:0:101:16:0:0:0 Premiere Serie:12031:h:S19.2E:27500:1023:1024:0:101:16:0:0:0
Disney Channel:11758:h:S19.2E:27500:2559:2560:0:101:34:0:0:0 Disney Channel:11758:h:S19.2E:27500:2559:2560:0:101:34:0:0:0
Premiere Nostalgie:12031:h:S19.2E:27500:2559:2560:0:101:516:0:0:0 Premiere Nostalgie:12031:h:S19.2E:27500:2559:2560:0:101:516:0:0:0
Discovery Channel:12031:h:S19.2E:27500:1791:1792:0:101:14:0:0:0 Discovery Channel:11758:h:S19.2E:27500:1023:1024:8181:101:14:0:0:0
Planet:12090:v:S19.2E:27500:1279:1280:0:101:13:0:0:0 Planet:12090:v:S19.2E:27500:1279:1280:0:101:13:0:0:0
Fox Kids:11758:h:S19.2E:27500:1279:1280:0:101:28:0:0:0 Fox Kids:11758:h:S19.2E:27500:1279:1280:0:101:28:0:0:0
Junior:11758:h:S19.2E:27500:255:256:0:101:19:0:0:0 Junior:11758:h:S19.2E:27500:255:256:0:101:19:0:0:0

61
ci.c
View File

@ -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: ci.c 1.9 2003/03/23 15:18:40 kls Exp $ * $Id: ci.c 1.14 2003/04/20 09:52:45 kls Exp $
*/ */
/* XXX TODO /* XXX TODO
@ -625,6 +625,7 @@ public:
const cCiTransportConnection *Tc(void) { return tc; } const cCiTransportConnection *Tc(void) { return tc; }
int SessionId(void) { return sessionId; } int SessionId(void) { return sessionId; }
int ResourceId(void) { return resourceId; } int ResourceId(void) { return resourceId; }
virtual bool HasUserIO(void) { return false; }
virtual bool Process(int Length = 0, const uint8_t *Data = NULL); virtual bool Process(int Length = 0, const uint8_t *Data = NULL);
}; };
@ -769,7 +770,7 @@ public:
cCiApplicationInformation::cCiApplicationInformation(int SessionId, cCiTransportConnection *Tc) cCiApplicationInformation::cCiApplicationInformation(int SessionId, cCiTransportConnection *Tc)
:cCiSession(SessionId, RI_APPLICATION_INFORMATION, Tc) :cCiSession(SessionId, RI_APPLICATION_INFORMATION, Tc)
{ {
dbgprotocol("New Aplication Information (session id %d)\n", SessionId); dbgprotocol("New Application Information (session id %d)\n", SessionId);
state = 0; state = 0;
creationTime = time(NULL); creationTime = time(NULL);
menuString = NULL; menuString = NULL;
@ -827,12 +828,17 @@ bool cCiApplicationInformation::EnterMenu(void)
// --- cCiConditionalAccessSupport ------------------------------------------- // --- cCiConditionalAccessSupport -------------------------------------------
#define MAXCASYSTEMIDS 16
class cCiConditionalAccessSupport : public cCiSession { class cCiConditionalAccessSupport : public cCiSession {
private: private:
int state; int state;
int numCaSystemIds;
unsigned short caSystemIds[MAXCASYSTEMIDS + 1]; // list is zero terminated!
public: public:
cCiConditionalAccessSupport(int SessionId, cCiTransportConnection *Tc); cCiConditionalAccessSupport(int SessionId, cCiTransportConnection *Tc);
virtual bool Process(int Length = 0, const uint8_t *Data = NULL); virtual bool Process(int Length = 0, const uint8_t *Data = NULL);
const unsigned short *GetCaSystemIds(void) { return caSystemIds; }
bool SendPMT(cCiCaPmt &CaPmt); bool SendPMT(cCiCaPmt &CaPmt);
}; };
@ -841,6 +847,7 @@ cCiConditionalAccessSupport::cCiConditionalAccessSupport(int SessionId, cCiTrans
{ {
dbgprotocol("New Conditional Access Support (session id %d)\n", SessionId); dbgprotocol("New Conditional Access Support (session id %d)\n", SessionId);
state = 0; state = 0;
caSystemIds[numCaSystemIds = 0] = 0;
} }
bool cCiConditionalAccessSupport::Process(int Length, const uint8_t *Data) bool cCiConditionalAccessSupport::Process(int Length, const uint8_t *Data)
@ -853,9 +860,16 @@ bool cCiConditionalAccessSupport::Process(int Length, const uint8_t *Data)
int l = 0; int l = 0;
const uint8_t *d = GetData(Data, l); const uint8_t *d = GetData(Data, l);
while (l > 1) { while (l > 1) {
dbgprotocol(" %04X", ((unsigned int)(*d) << 8) | *(d + 1)); unsigned short id = ((unsigned short)(*d) << 8) | *(d + 1);
dbgprotocol(" %04X", id);
d += 2; d += 2;
l -= 2; l -= 2;
if (numCaSystemIds < MAXCASYSTEMIDS) {
caSystemIds[numCaSystemIds++] = id;
caSystemIds[numCaSystemIds] = 0;
}
else
esyslog("ERROR: too many CA system IDs!");
} }
dbgprotocol("\n"); dbgprotocol("\n");
} }
@ -996,6 +1010,7 @@ public:
cCiMMI(int SessionId, cCiTransportConnection *Tc); cCiMMI(int SessionId, cCiTransportConnection *Tc);
virtual ~cCiMMI(); virtual ~cCiMMI();
virtual bool Process(int Length = 0, const uint8_t *Data = NULL); virtual bool Process(int Length = 0, const uint8_t *Data = NULL);
virtual bool HasUserIO(void) { return menu || enquiry; }
cCiMenu *Menu(void); cCiMenu *Menu(void);
cCiEnquiry *Enquiry(void); cCiEnquiry *Enquiry(void);
bool SendMenuAnswer(uint8_t Selection); bool SendMenuAnswer(uint8_t Selection);
@ -1273,7 +1288,8 @@ void cCiCaPmt::AddCaDescriptor(int Length, uint8_t *Data)
cCiHandler::cCiHandler(int Fd, int NumSlots) cCiHandler::cCiHandler(int Fd, int NumSlots)
{ {
numSlots = NumSlots; numSlots = NumSlots;
enabled = true; newCaSupport = false;
hasUserIO = false;
for (int i = 0; i < MAX_CI_SESSION; i++) for (int i = 0; i < MAX_CI_SESSION; i++)
sessions[i] = NULL; sessions[i] = NULL;
tpl = new cCiTransportLayer(Fd, numSlots); tpl = new cCiTransportLayer(Fd, numSlots);
@ -1299,12 +1315,14 @@ cCiHandler *cCiHandler::CreateCiHandler(const char *FileName)
if (Caps.slot_type == CA_CI_LINK) if (Caps.slot_type == CA_CI_LINK)
return new cCiHandler(fd_ca, NumSlots); return new cCiHandler(fd_ca, NumSlots);
else else
esyslog("ERROR: CAM doesn't support link layer interface"); isyslog("CAM doesn't support link layer interface");
} }
esyslog("ERROR: no CAM slots found"); else
esyslog("ERROR: no CAM slots found");
} }
else else
LOG_ERROR_STR(FileName); LOG_ERROR_STR(FileName);
close(fd_ca);
} }
return NULL; return NULL;
} }
@ -1358,7 +1376,8 @@ cCiSession *cCiHandler::CreateSession(int ResourceId)
switch (ResourceId) { switch (ResourceId) {
case RI_RESOURCE_MANAGER: return sessions[i] = new cCiResourceManager(i + 1, tc); case RI_RESOURCE_MANAGER: return sessions[i] = new cCiResourceManager(i + 1, tc);
case RI_APPLICATION_INFORMATION: return sessions[i] = new cCiApplicationInformation(i + 1, tc); case RI_APPLICATION_INFORMATION: return sessions[i] = new cCiApplicationInformation(i + 1, tc);
case RI_CONDITIONAL_ACCESS_SUPPORT: return sessions[i] = new cCiConditionalAccessSupport(i + 1, tc); case RI_CONDITIONAL_ACCESS_SUPPORT: newCaSupport = true;
return sessions[i] = new cCiConditionalAccessSupport(i + 1, tc);
case RI_HOST_CONTROL: break; //XXX case RI_HOST_CONTROL: break; //XXX
case RI_DATE_TIME: return sessions[i] = new cCiDateTime(i + 1, tc); case RI_DATE_TIME: return sessions[i] = new cCiDateTime(i + 1, tc);
case RI_MMI: return sessions[i] = new cCiMMI(i + 1, tc); case RI_MMI: return sessions[i] = new cCiMMI(i + 1, tc);
@ -1426,8 +1445,6 @@ int cCiHandler::CloseAllSessions(int Slot)
bool cCiHandler::Process(void) bool cCiHandler::Process(void)
{ {
if (!enabled)
return false;
bool result = true; bool result = true;
cMutexLock MutexLock(&mutex); cMutexLock MutexLock(&mutex);
for (int Slot = 0; Slot < numSlots; Slot++) { for (int Slot = 0; Slot < numSlots; Slot++) {
@ -1466,10 +1483,14 @@ bool cCiHandler::Process(void)
tpl->NewConnection(Slot); tpl->NewConnection(Slot);
} }
} }
bool UserIO = false;
for (int i = 0; i < MAX_CI_SESSION; i++) { for (int i = 0; i < MAX_CI_SESSION; i++) {
if (sessions[i]) if (sessions[i] && sessions[i]->Process())
sessions[i]->Process(); UserIO |= sessions[i]->HasUserIO();
} }
hasUserIO = UserIO;
if (newCaSupport)
newCaSupport = result = false; // triggers new SetCaPmt at caller!
return result; return result;
} }
@ -1502,16 +1523,18 @@ cCiEnquiry *cCiHandler::GetEnquiry(void)
return NULL; return NULL;
} }
bool cCiHandler::SetCaPmt(cCiCaPmt &CaPmt) const unsigned short *cCiHandler::GetCaSystemIds(int Slot)
{ {
cMutexLock MutexLock(&mutex); cMutexLock MutexLock(&mutex);
bool result = false; cCiConditionalAccessSupport *cas = (cCiConditionalAccessSupport *)GetSessionByResourceId(RI_CONDITIONAL_ACCESS_SUPPORT, Slot);
for (int Slot = 0; Slot < numSlots; Slot++) { return cas ? cas->GetCaSystemIds() : NULL;
cCiConditionalAccessSupport *cas = (cCiConditionalAccessSupport *)GetSessionByResourceId(RI_CONDITIONAL_ACCESS_SUPPORT, Slot); }
if (cas)
result |= cas->SendPMT(CaPmt); bool cCiHandler::SetCaPmt(cCiCaPmt &CaPmt, int Slot)
} {
return result; cMutexLock MutexLock(&mutex);
cCiConditionalAccessSupport *cas = (cCiConditionalAccessSupport *)GetSessionByResourceId(RI_CONDITIONAL_ACCESS_SUPPORT, Slot);
return cas && cas->SendPMT(CaPmt);
} }
bool cCiHandler::Reset(int Slot) bool cCiHandler::Reset(int Slot)

11
ci.h
View File

@ -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: ci.h 1.4 2003/03/23 15:18:40 kls Exp $ * $Id: ci.h 1.7 2003/04/20 09:21:23 kls Exp $
*/ */
#ifndef __CI_H #ifndef __CI_H
@ -80,7 +80,8 @@ class cCiHandler {
private: private:
cMutex mutex; cMutex mutex;
int numSlots; int numSlots;
bool enabled; bool newCaSupport;
bool hasUserIO;
cCiSession *sessions[MAX_CI_SESSION]; cCiSession *sessions[MAX_CI_SESSION];
cCiTransportLayer *tpl; cCiTransportLayer *tpl;
cCiTransportConnection *tc; cCiTransportConnection *tc;
@ -96,12 +97,14 @@ private:
public: public:
~cCiHandler(); ~cCiHandler();
static cCiHandler *CreateCiHandler(const char *FileName); static cCiHandler *CreateCiHandler(const char *FileName);
void SetEnabled(bool Enabled) { enabled = Enabled; } int NumSlots(void) { return numSlots; }
bool Process(void); bool Process(void);
bool HasUserIO(void) { return hasUserIO; }
bool EnterMenu(int Slot); bool EnterMenu(int Slot);
cCiMenu *GetMenu(void); cCiMenu *GetMenu(void);
cCiEnquiry *GetEnquiry(void); cCiEnquiry *GetEnquiry(void);
bool SetCaPmt(cCiCaPmt &CaPmt); const unsigned short *GetCaSystemIds(int Slot);
bool SetCaPmt(cCiCaPmt &CaPmt, int Slot);
bool Reset(int Slot); bool Reset(int Slot);
}; };

View File

@ -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: config.h 1.152 2003/04/12 09:35:50 kls Exp $ * $Id: config.h 1.153 2003/04/13 14:02:02 kls Exp $
*/ */
#ifndef __CONFIG_H #ifndef __CONFIG_H
@ -19,7 +19,7 @@
#include "device.h" #include "device.h"
#include "tools.h" #include "tools.h"
#define VDRVERSION "1.1.27" #define VDRVERSION "1.1.28"
#define MAXPRIORITY 99 #define MAXPRIORITY 99
#define MAXLIFETIME 99 #define MAXLIFETIME 99

View File

@ -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.51 2003/04/12 15:06:11 kls Exp $ * $Id: dvbdevice.c 1.54 2003/04/19 14:24:25 kls Exp $
*/ */
#include "dvbdevice.h" #include "dvbdevice.h"
@ -116,13 +116,14 @@ bool cDvbTuner::IsTunedTo(const cChannel *Channel) const
void cDvbTuner::Set(const cChannel *Channel, bool Tune) void cDvbTuner::Set(const cChannel *Channel, bool Tune)
{ {
cMutexLock MutexLock(&mutex); cMutexLock MutexLock(&mutex);
channel = *Channel; bool CaChange = !(Channel->GetChannelID() == channel.GetChannelID());
if (Tune) if (Tune)
tunerStatus = tsSet; tunerStatus = tsSet;
else if (tunerStatus == tsCam) else if (tunerStatus == tsCam && CaChange)
tunerStatus = tsTuned; tunerStatus = tsTuned;
if (Channel->Ca()) if (Channel->Ca() && CaChange)
startTime = time(NULL); startTime = time(NULL);
channel = *Channel;
newSet.Broadcast(); newSet.Broadcast();
} }
@ -264,27 +265,29 @@ void cDvbTuner::Action(void)
} }
} }
if (tunerStatus >= tsLocked) { if (tunerStatus >= tsLocked) {
if (ciHandler && channel.Ca()) { if (ciHandler) {
if (ciHandler->Process()) { if (ciHandler->Process()) {
if (tunerStatus != tsCam) {//XXX TODO update in case the CA descriptors have changed if (tunerStatus != tsCam) {//XXX TODO update in case the CA descriptors have changed
uchar buffer[2048]; for (int Slot = 0; Slot < ciHandler->NumSlots(); Slot++) {
int length = cSIProcessor::GetCaDescriptors(channel.Source(), channel.Frequency(), channel.Sid(), sizeof(buffer), buffer); uchar buffer[2048];
if (length > 0) { int length = cSIProcessor::GetCaDescriptors(channel.Source(), channel.Frequency(), channel.Sid(), ciHandler->GetCaSystemIds(Slot), sizeof(buffer), buffer);
cCiCaPmt CaPmt(channel.Sid()); if (length > 0) {
CaPmt.AddCaDescriptor(length, buffer); cCiCaPmt CaPmt(channel.Sid());
if (channel.Vpid()) CaPmt.AddCaDescriptor(length, buffer);
CaPmt.AddPid(channel.Vpid()); if (channel.Vpid())
if (channel.Apid1()) CaPmt.AddPid(channel.Vpid());
CaPmt.AddPid(channel.Apid1()); if (channel.Apid1())
if (channel.Apid2()) CaPmt.AddPid(channel.Apid1());
CaPmt.AddPid(channel.Apid2()); if (channel.Apid2())
if (channel.Dpid1()) CaPmt.AddPid(channel.Apid2());
CaPmt.AddPid(channel.Dpid1()); if (channel.Dpid1())
if (ciHandler->SetCaPmt(CaPmt)) { CaPmt.AddPid(channel.Dpid1());
tunerStatus = tsCam; if (ciHandler->SetCaPmt(CaPmt, Slot)) {
startTime = 0; tunerStatus = tsCam;
} startTime = 0;
} }
}
}
} }
} }
else else
@ -588,7 +591,8 @@ bool cDvbDevice::ProvidesChannel(const cChannel *Channel, int Priority, bool *Ne
if (!HasPid(Channel->Vpid())) { if (!HasPid(Channel->Vpid())) {
#ifdef DO_MULTIPLE_RECORDINGS #ifdef DO_MULTIPLE_RECORDINGS
if (Channel->Ca() > CACONFBASE) if (Channel->Ca() > CACONFBASE)
needsDetachReceivers = true; needsDetachReceivers = !ciHandler // only LL-firmware can do non-live CA channels
|| Ca() != Channel->Ca();
else if (!IsPrimaryDevice()) else if (!IsPrimaryDevice())
result = true; result = true;
#ifdef DO_REC_AND_PLAY_ON_PRIMARY_DEVICE #ifdef DO_REC_AND_PLAY_ON_PRIMARY_DEVICE
@ -609,7 +613,7 @@ bool cDvbDevice::ProvidesChannel(const cChannel *Channel, int Priority, bool *Ne
bool cDvbDevice::SetChannelDevice(const cChannel *Channel, bool LiveView) bool cDvbDevice::SetChannelDevice(const cChannel *Channel, bool LiveView)
{ {
bool IsEncrypted = Channel->Ca() > CACONFBASE; bool IsEncrypted = Channel->Ca() > CACONFBASE && !ciHandler; // only LL-firmware can do non-live CA channels
bool DoTune = !dvbTuner->IsTunedTo(Channel); bool DoTune = !dvbTuner->IsTunedTo(Channel);
@ -714,7 +718,7 @@ int cDvbDevice::NumAudioTracksDevice(void) const
int n = 0; int n = 0;
if (aPid1) if (aPid1)
n++; n++;
if (Ca() <= MAXDEVICES && aPid2 && aPid1 != aPid2) // a Ca recording session blocks switching live audio tracks if (Ca() <= MAXDEVICES && aPid2 && aPid1 != aPid2) // a CA recording session blocks switching live audio tracks
n++; n++;
return n; return n;
} }
@ -746,7 +750,7 @@ bool cDvbDevice::CanReplay(void) const
if (Receiving()) if (Receiving())
return false; return false;
#endif #endif
return cDevice::CanReplay() && Ca() <= MAXDEVICES; // we can only replay if there is no Ca recording going on return cDevice::CanReplay() && (Ca() <= MAXDEVICES || ciHandler); // with non-LL-firmware we can only replay if there is no CA recording going on
} }
bool cDvbDevice::SetPlayMode(ePlayMode PlayMode) bool cDvbDevice::SetPlayMode(ePlayMode PlayMode)
@ -775,15 +779,11 @@ bool cDvbDevice::SetPlayMode(ePlayMode PlayMode)
CHECK(ioctl(fd_audio, AUDIO_SET_MUTE, false)); CHECK(ioctl(fd_audio, AUDIO_SET_MUTE, false));
if (siProcessor) if (siProcessor)
siProcessor->SetStatus(true); siProcessor->SetStatus(true);
if (ciHandler)
ciHandler->SetEnabled(true);
break; break;
case pmAudioVideo: case pmAudioVideo:
case pmAudioOnlyBlack: case pmAudioOnlyBlack:
if (siProcessor) if (siProcessor)
siProcessor->SetStatus(false); siProcessor->SetStatus(false);
if (ciHandler)
ciHandler->SetEnabled(false);
CHECK(ioctl(fd_video, VIDEO_SET_BLANK, true)); CHECK(ioctl(fd_video, VIDEO_SET_BLANK, true));
CHECK(ioctl(fd_audio, AUDIO_SELECT_SOURCE, AUDIO_SOURCE_MEMORY)); CHECK(ioctl(fd_audio, AUDIO_SELECT_SOURCE, AUDIO_SOURCE_MEMORY));
CHECK(ioctl(fd_audio, AUDIO_SET_AV_SYNC, PlayMode == pmAudioVideo)); CHECK(ioctl(fd_audio, AUDIO_SET_AV_SYNC, PlayMode == pmAudioVideo));
@ -794,8 +794,6 @@ bool cDvbDevice::SetPlayMode(ePlayMode PlayMode)
case pmAudioOnly: case pmAudioOnly:
if (siProcessor) if (siProcessor)
siProcessor->SetStatus(false); siProcessor->SetStatus(false);
if (ciHandler)
ciHandler->SetEnabled(false);
CHECK(ioctl(fd_video, VIDEO_SET_BLANK, true)); CHECK(ioctl(fd_video, VIDEO_SET_BLANK, true));
CHECK(ioctl(fd_audio, AUDIO_STOP, true)); CHECK(ioctl(fd_audio, AUDIO_STOP, true));
CHECK(ioctl(fd_audio, AUDIO_CLEAR_BUFFER)); CHECK(ioctl(fd_audio, AUDIO_CLEAR_BUFFER));
@ -807,8 +805,6 @@ bool cDvbDevice::SetPlayMode(ePlayMode PlayMode)
case pmExtern_THIS_SHOULD_BE_AVOIDED: case pmExtern_THIS_SHOULD_BE_AVOIDED:
if (siProcessor) if (siProcessor)
siProcessor->SetStatus(false); siProcessor->SetStatus(false);
if (ciHandler)
ciHandler->SetEnabled(false);
close(fd_video); close(fd_video);
close(fd_audio); close(fd_audio);
fd_video = fd_audio = -1; fd_video = fd_audio = -1;

91
eit.c
View File

@ -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.68 2003/04/12 11:27:31 kls Exp $ * $Id: eit.c 1.72 2003/04/21 13:21:54 kls Exp $
***************************************************************************/ ***************************************************************************/
#include "eit.h" #include "eit.h"
@ -1002,34 +1002,38 @@ bool cEIT::IsPresentFollowing()
// --- cCaDescriptor --------------------------------------------------------- // --- cCaDescriptor ---------------------------------------------------------
class cCaDescriptor : public cListObject { class cCaDescriptor : public cListObject {
friend class cCaDescriptors; friend class cSIProcessor;
private: private:
int source; int source;
int transponder; int transponder;
int serviceId; int serviceId;
int caSystem; int caSystem;
unsigned int providerId;
int caPid;
int length; int length;
uchar *data; uchar *data;
public: public:
cCaDescriptor(int Source, int Transponder, int ServiceId, int CaSystem, int CaPid, int Length, uchar *Data); cCaDescriptor(int Source, int Transponder, int ServiceId, int CaSystem, unsigned int ProviderId, int CaPid, int Length, uchar *Data);
virtual ~cCaDescriptor(); virtual ~cCaDescriptor();
int Length(void) const { return length; } int Length(void) const { return length; }
const uchar *Data(void) const { return data; } const uchar *Data(void) const { return data; }
}; };
cCaDescriptor::cCaDescriptor(int Source, int Transponder, int ServiceId, int CaSystem, int CaPid, int Length, uchar *Data) cCaDescriptor::cCaDescriptor(int Source, int Transponder, int ServiceId, int CaSystem, unsigned int ProviderId, int CaPid, int Length, uchar *Data)
{ {
source = Source; source = Source;
transponder = Transponder; transponder = Transponder;
serviceId = ServiceId; serviceId = ServiceId;
caSystem = CaSystem; caSystem = CaSystem;
providerId = ProviderId;
caPid = CaPid;
length = Length + 6; length = Length + 6;
data = MALLOC(uchar, length); data = MALLOC(uchar, length);
data[0] = DESCR_CA; data[0] = DESCR_CA;
data[1] = length - 2; data[1] = length - 2;
data[2] = (caSystem >> 8) & 0xFF; data[2] = (caSystem >> 8) & 0xFF;
data[3] = caSystem & 0xFF; data[3] = caSystem & 0xFF;
data[4] = ((CaPid >> 8) & 0xFF) | 0xE0; data[4] = ((CaPid >> 8) & 0x1F) | 0xE0;
data[5] = CaPid & 0xFF; data[5] = CaPid & 0xFF;
if (Length) if (Length)
memcpy(&data[6], Data, Length); memcpy(&data[6], Data, Length);
@ -1037,7 +1041,7 @@ cCaDescriptor::cCaDescriptor(int Source, int Transponder, int ServiceId, int CaS
#ifdef DEBUG_CA_DESCRIPTORS #ifdef DEBUG_CA_DESCRIPTORS
char buffer[1024]; char buffer[1024];
char *q = buffer; char *q = buffer;
q += sprintf(q, "CAM: %04X %5d %4d", source, transponder, serviceId); q += sprintf(q, "CAM: %04X %5d %5d %04X %6X %04X -", source, transponder, serviceId, caSystem, providerId, caPid);
for (int i = 0; i < length; i++) for (int i = 0; i < length; i++)
q += sprintf(q, " %02X", data[i]); q += sprintf(q, " %02X", data[i]);
dsyslog(buffer); dsyslog(buffer);
@ -1049,26 +1053,6 @@ cCaDescriptor::~cCaDescriptor()
free(data); 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
@ -1077,7 +1061,7 @@ const cCaDescriptor *cCaDescriptors::Get(int Source, int Transponder, int Servic
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; cList<cCaDescriptor> cSIProcessor::caDescriptors;
cMutex cSIProcessor::caDescriptorsMutex; 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);
@ -1094,7 +1078,6 @@ cSIProcessor::cSIProcessor(const char *FileName)
filters = NULL; filters = NULL;
if (!numSIProcessors++) { // the first one creates them 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);
@ -1111,7 +1094,6 @@ cSIProcessor::~cSIProcessor()
free(filters); free(filters);
if (!--numSIProcessors) { // the last one deletes them if (!--numSIProcessors) { // the last one deletes them
delete schedules; delete schedules;
delete caDescriptors;
} }
free(fileName); free(fileName);
} }
@ -1176,12 +1158,9 @@ void cSIProcessor::SetStatus(bool On)
AddFilter(0x00, 0x00); // PAT 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, 0xfe); // event info, actual(0x4e)/other(0x4f) TS, present/following
AddFilter(0x12, 0x4f); // event info, other TS, present/following AddFilter(0x12, 0x50, 0xfe); // event info, actual TS, schedule(0x50)/schedule for another 4 days(0x51)
AddFilter(0x12, 0x50); // event info, actual TS, schedule AddFilter(0x12, 0x60, 0xfe); // event info, other TS, schedule(0x60)/schedule for another 4 days(0x61)
AddFilter(0x12, 0x60); // event info, other TS, schedule
AddFilter(0x12, 0x51); // event info, actual TS, schedule for another 4 days
AddFilter(0x12, 0x61); // event info, other TS, schedule for another 4 days
} }
} }
@ -1351,7 +1330,7 @@ void cSIProcessor::Action()
/** Add a filter with packet identifier pid and /** Add a filter with packet identifier pid and
table identifer tid */ table identifer tid */
bool cSIProcessor::AddFilter(unsigned short pid, u_char tid) bool cSIProcessor::AddFilter(unsigned short pid, u_char tid, u_char mask)
{ {
dmx_sct_filter_params sctFilterParams; dmx_sct_filter_params sctFilterParams;
memset(&sctFilterParams, 0, sizeof(sctFilterParams)); memset(&sctFilterParams, 0, sizeof(sctFilterParams));
@ -1359,7 +1338,7 @@ bool cSIProcessor::AddFilter(unsigned short pid, u_char tid)
sctFilterParams.timeout = 0; sctFilterParams.timeout = 0;
sctFilterParams.flags = DMX_IMMEDIATE_START; sctFilterParams.flags = DMX_IMMEDIATE_START;
sctFilterParams.filter.filter[0] = tid; sctFilterParams.filter.filter[0] = tid;
sctFilterParams.filter.mask[0] = 0xFF; sctFilterParams.filter.mask[0] = mask;
for (int a = 0; a < MAX_FILTERS; a++) for (int a = 0; a < MAX_FILTERS; a++)
{ {
@ -1443,36 +1422,40 @@ void cSIProcessor::TriggerDump(void)
lastDump = 0; lastDump = 0;
} }
void cSIProcessor::NewCaDescriptor(struct Descriptor *d, int ProgramID) void cSIProcessor::NewCaDescriptor(struct Descriptor *d, int ServiceId)
{ {
if (DescriptorTag(d) == DESCR_CA) { if (DescriptorTag(d) == DESCR_CA) {
struct CaDescriptor *cd = (struct CaDescriptor *)d; struct CaDescriptor *cd = (struct CaDescriptor *)d;
if (!caDescriptors->Get(currentSource, currentTransponder, ProgramID, cd->CA_type)) { cMutexLock MutexLock(&caDescriptorsMutex);
cMutexLock MutexLock(&caDescriptorsMutex);
caDescriptors->Add(new cCaDescriptor(currentSource, currentTransponder, ProgramID, cd->CA_type, cd->CA_PID, cd->DataLength, cd->Data)); for (cCaDescriptor *ca = caDescriptors.First(); ca; ca = caDescriptors.Next(ca)) {
} if (ca->source == currentSource && ca->transponder == currentTransponder && ca->serviceId == ServiceId && ca->caSystem == cd->CA_type && ca->providerId == cd->ProviderID && ca->caPid == cd->CA_PID)
return;
}
caDescriptors.Add(new cCaDescriptor(currentSource, currentTransponder, ServiceId, cd->CA_type, cd->ProviderID, cd->CA_PID, cd->DataLength, cd->Data));
//XXX update??? //XXX update???
} }
} }
int cSIProcessor::GetCaDescriptors(int Source, int Transponder, int ServiceId, int BufSize, uchar *Data) int cSIProcessor::GetCaDescriptors(int Source, int Transponder, int ServiceId, const unsigned short *CaSystemIds, int BufSize, uchar *Data)
{ {
if (!CaSystemIds || !*CaSystemIds)
return 0;
if (BufSize > 0 && Data) { if (BufSize > 0 && Data) {
cMutexLock MutexLock(&caDescriptorsMutex); cMutexLock MutexLock(&caDescriptorsMutex);
int length = 0; int length = 0;
for (int i = -1; ; i--) { do {
const cCaDescriptor *d = caDescriptors->Get(Source, Transponder, ServiceId, i); for (cCaDescriptor *d = caDescriptors.First(); d; d = caDescriptors.Next(d)) {
if (d) { if (d->source == Source && d->transponder == Transponder && d->serviceId == ServiceId && d->caSystem == *CaSystemIds) {
if (length + d->Length() <= BufSize) { if (length + d->Length() <= BufSize) {
memcpy(Data + length, d->Data(), d->Length()); memcpy(Data + length, d->Data(), d->Length());
length += d->Length(); length += d->Length();
}
else
return -1;
} }
else
return -1;
} }
else } while (*++CaSystemIds);
break;
}
return length; return length;
} }
return -1; return -1;

14
eit.h
View File

@ -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.25 2003/04/12 10:59:26 kls Exp $ * $Id: eit.h 1.28 2003/04/21 13:22:06 kls Exp $
***************************************************************************/ ***************************************************************************/
#ifndef __EIT_H #ifndef __EIT_H
@ -135,14 +135,13 @@ typedef struct sip_filter {
}SIP_FILTER; }SIP_FILTER;
class cCaDescriptor; 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 cList<cCaDescriptor> caDescriptors;
static cMutex caDescriptorsMutex; static cMutex caDescriptorsMutex;
static const char *epgDataFileName; static const char *epgDataFileName;
static time_t lastDump; static time_t lastDump;
@ -155,10 +154,10 @@ private:
char *fileName; char *fileName;
bool active; bool active;
void Action(void); void Action(void);
bool AddFilter(unsigned short pid, u_char tid); bool AddFilter(unsigned short pid, u_char tid, u_char mask = 0xFF);
bool DelFilter(unsigned short pid, u_char tid); bool DelFilter(unsigned short pid, u_char tid);
bool ShutDownFilters(void); bool ShutDownFilters(void);
void NewCaDescriptor(struct Descriptor *d, int ProgramID); void NewCaDescriptor(struct Descriptor *d, int ServiceId);
public: public:
cSIProcessor(const char *FileName); cSIProcessor(const char *FileName);
~cSIProcessor(); ~cSIProcessor();
@ -168,10 +167,11 @@ 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); static int GetCaDescriptors(int Source, int Transponder, int ServiceId, const unsigned short *CaSystemIds, int BufSize, uchar *Data);
///< Gets all CA descriptors for a given channel. ///< Gets all CA descriptors for a given channel.
///< Copies all available CA descriptors for the given Source, Transponder and ServiceId ///< Copies all available CA descriptors for the given Source, Transponder and ServiceId
///< into the provided buffer at Data (at most BufSize bytes). ///< into the provided buffer at Data (at most BufSize bytes). Only those CA descriptors
///< are copied that match one of the given CA system IDs.
///< \return Returns the number of bytes copied into Data (0 if no CA descriptors are ///< \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. ///< 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);

18
i18n.c
View File

@ -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.105 2003/04/12 09:39:35 kls Exp $ * $Id: i18n.c 1.106 2003/04/21 14:05:17 kls Exp $
* *
* Translations provided by: * Translations provided by:
* *
@ -3411,6 +3411,22 @@ const tI18nPhrase Phrases[] = {
"Caut inregistrari...", "Caut inregistrari...",
"Felvett adások böngészése...", "Felvett adások böngészése...",
}, },
{ "Pausing live video...",
"Live-Signal wird angehalten...",
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
},
{ "This plugin has no setup parameters!", { "This plugin has no setup parameters!",
"Dieses Plugin hat keine Setup-Parameter!", "Dieses Plugin hat keine Setup-Parameter!",
"",// TODO "",// TODO

31
menu.c
View File

@ -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.235 2003/04/12 09:40:48 kls Exp $ * $Id: menu.c 1.237 2003/04/21 14:57:13 kls Exp $
*/ */
#include "menu.h" #include "menu.h"
@ -1636,7 +1636,7 @@ cOsdObject *CamControl(void)
cDevice *Device = cDevice::GetDevice(d); cDevice *Device = cDevice::GetDevice(d);
if (Device) { if (Device) {
cCiHandler *CiHandler = Device->CiHandler(); cCiHandler *CiHandler = Device->CiHandler();
if (CiHandler) { if (CiHandler && CiHandler->HasUserIO()) {
cCiMenu *CiMenu = CiHandler->GetMenu(); cCiMenu *CiMenu = CiHandler->GetMenu();
if (CiMenu) if (CiMenu)
return new cMenuCam(CiMenu); return new cMenuCam(CiMenu);
@ -2488,7 +2488,7 @@ void cMenuMain::Set(const char *Plugin)
// Color buttons: // Color buttons:
SetHelp(tr("Record"), cDevice::PrimaryDevice()->NumAudioTracks() > 1 ? tr("Language") : NULL, NULL, replaying ? tr("Button$Stop") : cReplayControl::LastReplayed() ? tr("Resume") : NULL); SetHelp(tr("Record"), cDevice::PrimaryDevice()->NumAudioTracks() > 1 ? tr("Language") : NULL, replaying ? NULL : tr("Pause"), replaying ? tr("Button$Stop") : cReplayControl::LastReplayed() ? tr("Resume") : NULL);
Display(); Display();
lastActivity = time(NULL); lastActivity = time(NULL);
} }
@ -2560,6 +2560,9 @@ eOSState cMenuMain::ProcessKey(eKeys Key)
} }
} }
break; break;
case kYellow: if (!HasSubMenu())
state = osPause;
break;
case kBlue: if (!HasSubMenu()) case kBlue: if (!HasSubMenu())
state = replaying ? osStopReplay : cReplayControl::LastReplayed() ? osReplay : osContinue; state = replaying ? osStopReplay : cReplayControl::LastReplayed() ? osReplay : osContinue;
break; break;
@ -2936,6 +2939,8 @@ cRecordControl::cRecordControl(cDevice *Device, cTimer *Timer)
if (device->AttachReceiver(recorder)) { if (device->AttachReceiver(recorder)) {
Recording.WriteSummary(); Recording.WriteSummary();
cStatus::MsgRecording(device, Recording.Name()); cStatus::MsgRecording(device, Recording.Name());
if (!Timer && !cReplayControl::LastReplayed()) // an instant recording, maybe from cRecordControls::PauseLiveVideo()
cReplayControl::SetRecording(fileName, Recording.Name());
} }
else else
DELETENULL(recorder); DELETENULL(recorder);
@ -3073,6 +3078,26 @@ bool cRecordControls::StopPrimary(bool DoIt)
return false; return false;
} }
bool cRecordControls::PauseLiveVideo(void)
{
Interface->Open(Setup.OSDwidth, -1);
Interface->Status(tr("Pausing live video..."));
Interface->Flush();
cReplayControl::SetRecording(NULL, NULL); // make sure the new cRecordControl will set cReplayControl::LastReplayed()
if (Start()) {
sleep(2); // allow recorded file to fill up enough to start replaying
cReplayControl *rc = new cReplayControl;
cControl::Launch(rc);
cControl::Attach();
sleep(1); // allow device to replay some frames, so we have a picture
Interface->Close();
rc->ProcessKey(kPause); // pause, allowing replay mode display
return true;
}
Interface->Close();
return false;
}
const char *cRecordControls::GetInstantId(const char *LastInstantId) const char *cRecordControls::GetInstantId(const char *LastInstantId)
{ {
for (int i = 0; i < MAXRECORDCONTROLS; i++) { for (int i = 0; i < MAXRECORDCONTROLS; i++) {

3
menu.h
View File

@ -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.h 1.53 2003/01/12 14:54:05 kls Exp $ * $Id: menu.h 1.54 2003/04/21 13:40:45 kls Exp $
*/ */
#ifndef __MENU_H #ifndef __MENU_H
@ -135,6 +135,7 @@ public:
static void Stop(const char *InstantId); static void Stop(const char *InstantId);
static void Stop(cDevice *Device); static void Stop(cDevice *Device);
static bool StopPrimary(bool DoIt = false); static bool StopPrimary(bool DoIt = false);
static bool PauseLiveVideo(void);
static const char *GetInstantId(const char *LastInstantId); static const char *GetInstantId(const char *LastInstantId);
static cRecordControl *GetRecordControl(const char *FileName); static cRecordControl *GetRecordControl(const char *FileName);
static void Process(time_t t); static void Process(time_t t);

3
osd.h
View File

@ -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: osd.h 1.38 2002/12/08 12:21:26 kls Exp $ * $Id: osd.h 1.39 2003/04/21 10:27:41 kls Exp $
*/ */
#ifndef __OSD_H #ifndef __OSD_H
@ -30,6 +30,7 @@ enum eOSState { osUnknown,
osPlugin, osPlugin,
osSetup, osSetup,
osCommands, osCommands,
osPause,
osRecord, osRecord,
osReplay, osReplay,
osStopRecord, osStopRecord,

35
vdr.c
View File

@ -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.149 2003/04/12 13:57:45 kls Exp $ * $Id: vdr.c 1.150 2003/04/21 14:41:41 kls Exp $
*/ */
#include <getopt.h> #include <getopt.h>
@ -553,6 +553,26 @@ int main(int argc, char *argv[])
cDisplayVolume::Process(key); cDisplayVolume::Process(key);
key = kNone; // nobody else needs to see these keys key = kNone; // nobody else needs to see these keys
break; break;
// Pausing live video:
case kPause:
if (!cControl::Control()) {
DELETENULL(Menu);
Temp = NULL;
if (!cRecordControls::PauseLiveVideo())
Interface->Error(tr("No free DVB device to record!"));
key = kNone; // nobody else needs to see this key
}
break;
// Instant recording:
case kRecord:
if (!cControl::Control()) {
if (cRecordControls::Start())
;//XXX Interface->Info(tr("Recording"));
else
Interface->Error(tr("No free DVB device to record!"));
key = kNone; // nobody else needs to see this key
}
break;
// Power off: // Power off:
case kPower: isyslog("Power button pressed"); case kPower: isyslog("Power button pressed");
DELETENULL(Menu); DELETENULL(Menu);
@ -577,6 +597,12 @@ int main(int argc, char *argv[])
if (state == osUnknown && ISMODELESSKEY(key) && cControl::Control() && Interact != cControl::Control()) if (state == osUnknown && ISMODELESSKEY(key) && cControl::Control() && Interact != cControl::Control())
state = cControl::Control()->ProcessKey(key); state = cControl::Control()->ProcessKey(key);
switch (state) { switch (state) {
case osPause: DELETENULL(Menu);
cControl::Shutdown(); // just in case
Temp = NULL;
if (!cRecordControls::PauseLiveVideo())
Interface->Error(tr("No free DVB device to record!"));
break;
case osRecord: DELETENULL(Menu); case osRecord: DELETENULL(Menu);
Temp = NULL; Temp = NULL;
if (cRecordControls::Start()) if (cRecordControls::Start())
@ -652,13 +678,6 @@ int main(int argc, char *argv[])
break; break;
// Viewing Control: // Viewing Control:
case kOk: LastChannel = -1; break; // forces channel display case kOk: LastChannel = -1; break; // forces channel display
// Instant recording:
case kRecord:
if (cRecordControls::Start())
;//XXX Interface->Info(tr("Recording"));
else
Interface->Error(tr("No free DVB device to record!"));
break;
// Key macros: // Key macros:
case kRed: case kRed:
case kGreen: case kGreen: