diff options
author | Klaus Schmidinger <kls (at) cadsoft (dot) de> | 2003-04-21 18:00:00 +0200 |
---|---|---|
committer | Klaus Schmidinger <kls (at) cadsoft (dot) de> | 2003-04-21 18:00:00 +0200 |
commit | 21a52ccb6d43cce35f7a381f55ea291195416f33 (patch) | |
tree | bc7d86214e695434ca7170bff799bcc4aaca5401 | |
parent | 9f919801465f49be6b2118f54bd54df846e2f865 (diff) | |
download | vdr-patch-lnbsharing-21a52ccb6d43cce35f7a381f55ea291195416f33.tar.gz vdr-patch-lnbsharing-21a52ccb6d43cce35f7a381f55ea291195416f33.tar.bz2 |
Version 1.1.28vdr-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.
-rw-r--r-- | CONTRIBUTORS | 1 | ||||
-rw-r--r-- | HISTORY | 20 | ||||
-rw-r--r-- | MANUAL | 18 | ||||
-rw-r--r-- | channels.conf | 2 | ||||
-rw-r--r-- | ci.c | 61 | ||||
-rw-r--r-- | ci.h | 11 | ||||
-rw-r--r-- | config.h | 4 | ||||
-rw-r--r-- | dvbdevice.c | 66 | ||||
-rw-r--r-- | eit.c | 91 | ||||
-rw-r--r-- | eit.h | 14 | ||||
-rw-r--r-- | i18n.c | 18 | ||||
-rw-r--r-- | menu.c | 31 | ||||
-rw-r--r-- | menu.h | 3 | ||||
-rw-r--r-- | osd.h | 3 | ||||
-rw-r--r-- | vdr.c | 35 |
15 files changed, 240 insertions, 138 deletions
diff --git a/CONTRIBUTORS b/CONTRIBUTORS index fad8e0b..d05b928 100644 --- a/CONTRIBUTORS +++ b/CONTRIBUTORS @@ -196,6 +196,7 @@ Andreas Schultz <aschultz@warp10.net> for pointing out some unnecessary #includes in eit.c and a problem with cMenuRecordings::Del(), which caused warnings with gcc-3.2 for suggesting a Make.config file + for making EIT filtering use masks to reduce the number of filters Aaron Holtzman for writing 'ac3dec' @@ -2033,3 +2033,23 @@ Video Disk Recorder Revision History applies to the RCU remote control in case of errors during startup. - Fixed handling of Ca parameters with values <= MAXDEVICES, which don't indicate 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. @@ -19,7 +19,7 @@ Video Disk Recorder User's Manual Back - Menu off VDR menu VDR menu Discard VDR menu Recordings menu Red - Record Edit Edit ABC/abc Play/Commands(2) Jump 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 0..9 Ch select - - - Numeric inp. Exec cmd(2) Editing @@ -31,7 +31,7 @@ Video Disk Recorder User's Manual following functions: Play resume normal replay - Pause pause replay + Pause pause replay or live video Stop stop replay Record instant recording FastFwd fast forward @@ -191,6 +191,20 @@ Video Disk Recorder User's Manual Stop instant recording by pressing the "Menu" button and selecting "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 All recordings are listed in the "Recordings" menu. Browse through the diff --git a/channels.conf b/channels.conf index 2f0c7eb..13bc7e7 100644 --- a/channels.conf +++ b/channels.conf @@ -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 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 -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 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 @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * 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 @@ -625,6 +625,7 @@ public: const cCiTransportConnection *Tc(void) { return tc; } int SessionId(void) { return sessionId; } int ResourceId(void) { return resourceId; } + virtual bool HasUserIO(void) { return false; } virtual bool Process(int Length = 0, const uint8_t *Data = NULL); }; @@ -769,7 +770,7 @@ public: cCiApplicationInformation::cCiApplicationInformation(int SessionId, cCiTransportConnection *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; creationTime = time(NULL); menuString = NULL; @@ -827,12 +828,17 @@ bool cCiApplicationInformation::EnterMenu(void) // --- cCiConditionalAccessSupport ------------------------------------------- +#define MAXCASYSTEMIDS 16 + class cCiConditionalAccessSupport : public cCiSession { private: int state; + int numCaSystemIds; + unsigned short caSystemIds[MAXCASYSTEMIDS + 1]; // list is zero terminated! public: cCiConditionalAccessSupport(int SessionId, cCiTransportConnection *Tc); virtual bool Process(int Length = 0, const uint8_t *Data = NULL); + const unsigned short *GetCaSystemIds(void) { return caSystemIds; } bool SendPMT(cCiCaPmt &CaPmt); }; @@ -841,6 +847,7 @@ cCiConditionalAccessSupport::cCiConditionalAccessSupport(int SessionId, cCiTrans { dbgprotocol("New Conditional Access Support (session id %d)\n", SessionId); state = 0; + caSystemIds[numCaSystemIds = 0] = 0; } 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; const uint8_t *d = GetData(Data, l); 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; l -= 2; + if (numCaSystemIds < MAXCASYSTEMIDS) { + caSystemIds[numCaSystemIds++] = id; + caSystemIds[numCaSystemIds] = 0; + } + else + esyslog("ERROR: too many CA system IDs!"); } dbgprotocol("\n"); } @@ -996,6 +1010,7 @@ public: cCiMMI(int SessionId, cCiTransportConnection *Tc); virtual ~cCiMMI(); virtual bool Process(int Length = 0, const uint8_t *Data = NULL); + virtual bool HasUserIO(void) { return menu || enquiry; } cCiMenu *Menu(void); cCiEnquiry *Enquiry(void); bool SendMenuAnswer(uint8_t Selection); @@ -1273,7 +1288,8 @@ void cCiCaPmt::AddCaDescriptor(int Length, uint8_t *Data) cCiHandler::cCiHandler(int Fd, int NumSlots) { numSlots = NumSlots; - enabled = true; + newCaSupport = false; + hasUserIO = false; for (int i = 0; i < MAX_CI_SESSION; i++) sessions[i] = NULL; tpl = new cCiTransportLayer(Fd, numSlots); @@ -1299,12 +1315,14 @@ cCiHandler *cCiHandler::CreateCiHandler(const char *FileName) if (Caps.slot_type == CA_CI_LINK) return new cCiHandler(fd_ca, NumSlots); 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 LOG_ERROR_STR(FileName); + close(fd_ca); } return NULL; } @@ -1358,7 +1376,8 @@ cCiSession *cCiHandler::CreateSession(int ResourceId) switch (ResourceId) { 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_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_DATE_TIME: return sessions[i] = new cCiDateTime(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) { - if (!enabled) - return false; bool result = true; cMutexLock MutexLock(&mutex); for (int Slot = 0; Slot < numSlots; Slot++) { @@ -1466,10 +1483,14 @@ bool cCiHandler::Process(void) tpl->NewConnection(Slot); } } + bool UserIO = false; for (int i = 0; i < MAX_CI_SESSION; i++) { - if (sessions[i]) - sessions[i]->Process(); + if (sessions[i] && sessions[i]->Process()) + UserIO |= sessions[i]->HasUserIO(); } + hasUserIO = UserIO; + if (newCaSupport) + newCaSupport = result = false; // triggers new SetCaPmt at caller! return result; } @@ -1502,16 +1523,18 @@ cCiEnquiry *cCiHandler::GetEnquiry(void) return NULL; } -bool cCiHandler::SetCaPmt(cCiCaPmt &CaPmt) +const unsigned short *cCiHandler::GetCaSystemIds(int Slot) { cMutexLock MutexLock(&mutex); - bool result = false; - for (int Slot = 0; Slot < numSlots; Slot++) { - cCiConditionalAccessSupport *cas = (cCiConditionalAccessSupport *)GetSessionByResourceId(RI_CONDITIONAL_ACCESS_SUPPORT, Slot); - if (cas) - result |= cas->SendPMT(CaPmt); - } - return result; + cCiConditionalAccessSupport *cas = (cCiConditionalAccessSupport *)GetSessionByResourceId(RI_CONDITIONAL_ACCESS_SUPPORT, Slot); + return cas ? cas->GetCaSystemIds() : NULL; +} + +bool cCiHandler::SetCaPmt(cCiCaPmt &CaPmt, int Slot) +{ + cMutexLock MutexLock(&mutex); + cCiConditionalAccessSupport *cas = (cCiConditionalAccessSupport *)GetSessionByResourceId(RI_CONDITIONAL_ACCESS_SUPPORT, Slot); + return cas && cas->SendPMT(CaPmt); } bool cCiHandler::Reset(int Slot) @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: ci.h 1.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 @@ -80,7 +80,8 @@ class cCiHandler { private: cMutex mutex; int numSlots; - bool enabled; + bool newCaSupport; + bool hasUserIO; cCiSession *sessions[MAX_CI_SESSION]; cCiTransportLayer *tpl; cCiTransportConnection *tc; @@ -96,12 +97,14 @@ private: public: ~cCiHandler(); static cCiHandler *CreateCiHandler(const char *FileName); - void SetEnabled(bool Enabled) { enabled = Enabled; } + int NumSlots(void) { return numSlots; } bool Process(void); + bool HasUserIO(void) { return hasUserIO; } bool EnterMenu(int Slot); cCiMenu *GetMenu(void); cCiEnquiry *GetEnquiry(void); - bool SetCaPmt(cCiCaPmt &CaPmt); + const unsigned short *GetCaSystemIds(int Slot); + bool SetCaPmt(cCiCaPmt &CaPmt, int Slot); bool Reset(int Slot); }; @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * 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 @@ -19,7 +19,7 @@ #include "device.h" #include "tools.h" -#define VDRVERSION "1.1.27" +#define VDRVERSION "1.1.28" #define MAXPRIORITY 99 #define MAXLIFETIME 99 diff --git a/dvbdevice.c b/dvbdevice.c index 9bbac2d..c25ebef 100644 --- a/dvbdevice.c +++ b/dvbdevice.c @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: dvbdevice.c 1.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" @@ -116,13 +116,14 @@ bool cDvbTuner::IsTunedTo(const cChannel *Channel) const void cDvbTuner::Set(const cChannel *Channel, bool Tune) { cMutexLock MutexLock(&mutex); - channel = *Channel; + bool CaChange = !(Channel->GetChannelID() == channel.GetChannelID()); if (Tune) tunerStatus = tsSet; - else if (tunerStatus == tsCam) + else if (tunerStatus == tsCam && CaChange) tunerStatus = tsTuned; - if (Channel->Ca()) + if (Channel->Ca() && CaChange) startTime = time(NULL); + channel = *Channel; newSet.Broadcast(); } @@ -264,27 +265,29 @@ void cDvbTuner::Action(void) } } if (tunerStatus >= tsLocked) { - if (ciHandler && channel.Ca()) { + if (ciHandler) { if (ciHandler->Process()) { if (tunerStatus != tsCam) {//XXX TODO update in case the CA descriptors have changed - uchar buffer[2048]; - int length = cSIProcessor::GetCaDescriptors(channel.Source(), channel.Frequency(), channel.Sid(), sizeof(buffer), buffer); - if (length > 0) { - cCiCaPmt CaPmt(channel.Sid()); - CaPmt.AddCaDescriptor(length, buffer); - if (channel.Vpid()) - CaPmt.AddPid(channel.Vpid()); - if (channel.Apid1()) - CaPmt.AddPid(channel.Apid1()); - if (channel.Apid2()) - CaPmt.AddPid(channel.Apid2()); - if (channel.Dpid1()) - CaPmt.AddPid(channel.Dpid1()); - if (ciHandler->SetCaPmt(CaPmt)) { - tunerStatus = tsCam; - startTime = 0; - } - } + for (int Slot = 0; Slot < ciHandler->NumSlots(); Slot++) { + uchar buffer[2048]; + int length = cSIProcessor::GetCaDescriptors(channel.Source(), channel.Frequency(), channel.Sid(), ciHandler->GetCaSystemIds(Slot), sizeof(buffer), buffer); + if (length > 0) { + cCiCaPmt CaPmt(channel.Sid()); + CaPmt.AddCaDescriptor(length, buffer); + if (channel.Vpid()) + CaPmt.AddPid(channel.Vpid()); + if (channel.Apid1()) + CaPmt.AddPid(channel.Apid1()); + if (channel.Apid2()) + CaPmt.AddPid(channel.Apid2()); + if (channel.Dpid1()) + CaPmt.AddPid(channel.Dpid1()); + if (ciHandler->SetCaPmt(CaPmt, Slot)) { + tunerStatus = tsCam; + startTime = 0; + } + } + } } } else @@ -588,7 +591,8 @@ bool cDvbDevice::ProvidesChannel(const cChannel *Channel, int Priority, bool *Ne if (!HasPid(Channel->Vpid())) { #ifdef DO_MULTIPLE_RECORDINGS if (Channel->Ca() > CACONFBASE) - needsDetachReceivers = true; + needsDetachReceivers = !ciHandler // only LL-firmware can do non-live CA channels + || Ca() != Channel->Ca(); else if (!IsPrimaryDevice()) result = true; #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 IsEncrypted = Channel->Ca() > CACONFBASE; + bool IsEncrypted = Channel->Ca() > CACONFBASE && !ciHandler; // only LL-firmware can do non-live CA channels bool DoTune = !dvbTuner->IsTunedTo(Channel); @@ -714,7 +718,7 @@ int cDvbDevice::NumAudioTracksDevice(void) const int n = 0; if (aPid1) 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++; return n; } @@ -746,7 +750,7 @@ bool cDvbDevice::CanReplay(void) const if (Receiving()) return false; #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) @@ -775,15 +779,11 @@ bool cDvbDevice::SetPlayMode(ePlayMode PlayMode) CHECK(ioctl(fd_audio, AUDIO_SET_MUTE, false)); if (siProcessor) siProcessor->SetStatus(true); - if (ciHandler) - ciHandler->SetEnabled(true); break; case pmAudioVideo: case pmAudioOnlyBlack: if (siProcessor) siProcessor->SetStatus(false); - if (ciHandler) - ciHandler->SetEnabled(false); CHECK(ioctl(fd_video, VIDEO_SET_BLANK, true)); CHECK(ioctl(fd_audio, AUDIO_SELECT_SOURCE, AUDIO_SOURCE_MEMORY)); CHECK(ioctl(fd_audio, AUDIO_SET_AV_SYNC, PlayMode == pmAudioVideo)); @@ -794,8 +794,6 @@ bool cDvbDevice::SetPlayMode(ePlayMode PlayMode) case pmAudioOnly: if (siProcessor) siProcessor->SetStatus(false); - if (ciHandler) - ciHandler->SetEnabled(false); CHECK(ioctl(fd_video, VIDEO_SET_BLANK, true)); CHECK(ioctl(fd_audio, AUDIO_STOP, true)); CHECK(ioctl(fd_audio, AUDIO_CLEAR_BUFFER)); @@ -807,8 +805,6 @@ bool cDvbDevice::SetPlayMode(ePlayMode PlayMode) case pmExtern_THIS_SHOULD_BE_AVOIDED: if (siProcessor) siProcessor->SetStatus(false); - if (ciHandler) - ciHandler->SetEnabled(false); close(fd_video); close(fd_audio); fd_video = fd_audio = -1; @@ -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.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" @@ -1002,34 +1002,38 @@ bool cEIT::IsPresentFollowing() // --- cCaDescriptor --------------------------------------------------------- class cCaDescriptor : public cListObject { - friend class cCaDescriptors; + friend class cSIProcessor; private: int source; int transponder; int serviceId; int caSystem; + unsigned int providerId; + int caPid; int length; uchar *data; 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(); int Length(void) const { return length; } 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; transponder = Transponder; serviceId = ServiceId; caSystem = CaSystem; + providerId = ProviderId; + caPid = CaPid; length = Length + 6; data = MALLOC(uchar, length); data[0] = DESCR_CA; data[1] = length - 2; data[2] = (caSystem >> 8) & 0xFF; data[3] = caSystem & 0xFF; - data[4] = ((CaPid >> 8) & 0xFF) | 0xE0; + data[4] = ((CaPid >> 8) & 0x1F) | 0xE0; data[5] = CaPid & 0xFF; if (Length) memcpy(&data[6], Data, Length); @@ -1037,7 +1041,7 @@ cCaDescriptor::cCaDescriptor(int Source, int Transponder, int ServiceId, int CaS #ifdef DEBUG_CA_DESCRIPTORS char buffer[1024]; 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++) q += sprintf(q, " %02X", data[i]); dsyslog(buffer); @@ -1049,26 +1053,6 @@ 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 @@ -1077,7 +1061,7 @@ const cCaDescriptor *cCaDescriptors::Get(int Source, int Transponder, int Servic int cSIProcessor::numSIProcessors = 0; cSchedules *cSIProcessor::schedules = NULL; cMutex cSIProcessor::schedulesMutex; -cCaDescriptors *cSIProcessor::caDescriptors = NULL; +cList<cCaDescriptor> cSIProcessor::caDescriptors; cMutex cSIProcessor::caDescriptorsMutex; const char *cSIProcessor::epgDataFileName = EPGDATAFILENAME; time_t cSIProcessor::lastDump = time(NULL); @@ -1094,7 +1078,6 @@ cSIProcessor::cSIProcessor(const char *FileName) filters = NULL; if (!numSIProcessors++) { // the first one creates them schedules = new cSchedules; - caDescriptors = new cCaDescriptors; } filters = (SIP_FILTER *)calloc(MAX_FILTERS, sizeof(SIP_FILTER)); SetStatus(true); @@ -1111,7 +1094,6 @@ cSIProcessor::~cSIProcessor() free(filters); if (!--numSIProcessors) { // the last one deletes them delete schedules; - delete caDescriptors; } free(fileName); } @@ -1176,12 +1158,9 @@ void cSIProcessor::SetStatus(bool On) AddFilter(0x00, 0x00); // PAT AddFilter(0x14, 0x70); // TDT AddFilter(0x14, 0x73); // TOT - AddFilter(0x12, 0x4e); // event info, actual TS, present/following - AddFilter(0x12, 0x4f); // event info, other TS, present/following - AddFilter(0x12, 0x50); // event info, actual TS, schedule - 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 + AddFilter(0x12, 0x4e, 0xfe); // event info, actual(0x4e)/other(0x4f) TS, present/following + AddFilter(0x12, 0x50, 0xfe); // event info, actual TS, schedule(0x50)/schedule for another 4 days(0x51) + AddFilter(0x12, 0x60, 0xfe); // event info, other TS, schedule(0x60)/schedule for another 4 days(0x61) } } @@ -1351,7 +1330,7 @@ void cSIProcessor::Action() /** Add a filter with packet identifier pid and 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; memset(&sctFilterParams, 0, sizeof(sctFilterParams)); @@ -1359,7 +1338,7 @@ bool cSIProcessor::AddFilter(unsigned short pid, u_char tid) sctFilterParams.timeout = 0; sctFilterParams.flags = DMX_IMMEDIATE_START; sctFilterParams.filter.filter[0] = tid; - sctFilterParams.filter.mask[0] = 0xFF; + sctFilterParams.filter.mask[0] = mask; for (int a = 0; a < MAX_FILTERS; a++) { @@ -1443,36 +1422,40 @@ void cSIProcessor::TriggerDump(void) lastDump = 0; } -void cSIProcessor::NewCaDescriptor(struct Descriptor *d, int ProgramID) +void cSIProcessor::NewCaDescriptor(struct Descriptor *d, int ServiceId) { if (DescriptorTag(d) == DESCR_CA) { struct CaDescriptor *cd = (struct CaDescriptor *)d; - if (!caDescriptors->Get(currentSource, currentTransponder, ProgramID, cd->CA_type)) { - cMutexLock MutexLock(&caDescriptorsMutex); - caDescriptors->Add(new cCaDescriptor(currentSource, currentTransponder, ProgramID, cd->CA_type, cd->CA_PID, cd->DataLength, cd->Data)); - } + cMutexLock MutexLock(&caDescriptorsMutex); + + 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??? } } -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) { 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(); + do { + for (cCaDescriptor *d = caDescriptors.First(); d; d = caDescriptors.Next(d)) { + if (d->source == Source && d->transponder == Transponder && d->serviceId == ServiceId && d->caSystem == *CaSystemIds) { + if (length + d->Length() <= BufSize) { + memcpy(Data + length, d->Data(), d->Length()); + length += d->Length(); + } + else + return -1; } - else - return -1; } - else - break; - } + } while (*++CaSystemIds); return length; } return -1; @@ -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.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 @@ -135,14 +135,13 @@ 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 cList<cCaDescriptor> caDescriptors; static cMutex caDescriptorsMutex; static const char *epgDataFileName; static time_t lastDump; @@ -155,10 +154,10 @@ private: char *fileName; bool active; 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 ShutDownFilters(void); - void NewCaDescriptor(struct Descriptor *d, int ProgramID); + void NewCaDescriptor(struct Descriptor *d, int ServiceId); public: cSIProcessor(const char *FileName); ~cSIProcessor(); @@ -168,10 +167,11 @@ 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); + 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. ///< 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 ///< available), or -1 if BufSize was too small to hold all CA descriptors. static bool Read(FILE *f = NULL); @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * 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: * @@ -3411,6 +3411,22 @@ const tI18nPhrase Phrases[] = { "Caut inregistrari...", "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!", "Dieses Plugin hat keine Setup-Parameter!", "",// TODO @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * 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" @@ -1636,7 +1636,7 @@ cOsdObject *CamControl(void) cDevice *Device = cDevice::GetDevice(d); if (Device) { cCiHandler *CiHandler = Device->CiHandler(); - if (CiHandler) { + if (CiHandler && CiHandler->HasUserIO()) { cCiMenu *CiMenu = CiHandler->GetMenu(); if (CiMenu) return new cMenuCam(CiMenu); @@ -2488,7 +2488,7 @@ void cMenuMain::Set(const char *Plugin) // 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(); lastActivity = time(NULL); } @@ -2560,6 +2560,9 @@ eOSState cMenuMain::ProcessKey(eKeys Key) } } break; + case kYellow: if (!HasSubMenu()) + state = osPause; + break; case kBlue: if (!HasSubMenu()) state = replaying ? osStopReplay : cReplayControl::LastReplayed() ? osReplay : osContinue; break; @@ -2936,6 +2939,8 @@ cRecordControl::cRecordControl(cDevice *Device, cTimer *Timer) if (device->AttachReceiver(recorder)) { Recording.WriteSummary(); cStatus::MsgRecording(device, Recording.Name()); + if (!Timer && !cReplayControl::LastReplayed()) // an instant recording, maybe from cRecordControls::PauseLiveVideo() + cReplayControl::SetRecording(fileName, Recording.Name()); } else DELETENULL(recorder); @@ -3073,6 +3078,26 @@ bool cRecordControls::StopPrimary(bool DoIt) 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) { for (int i = 0; i < MAXRECORDCONTROLS; i++) { @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * 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 @@ -135,6 +135,7 @@ public: static void Stop(const char *InstantId); static void Stop(cDevice *Device); static bool StopPrimary(bool DoIt = false); + static bool PauseLiveVideo(void); static const char *GetInstantId(const char *LastInstantId); static cRecordControl *GetRecordControl(const char *FileName); static void Process(time_t t); @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * 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 @@ -30,6 +30,7 @@ enum eOSState { osUnknown, osPlugin, osSetup, osCommands, + osPause, osRecord, osReplay, osStopRecord, @@ -22,7 +22,7 @@ * * 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> @@ -553,6 +553,26 @@ int main(int argc, char *argv[]) cDisplayVolume::Process(key); key = kNone; // nobody else needs to see these keys 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: case kPower: isyslog("Power button pressed"); DELETENULL(Menu); @@ -577,6 +597,12 @@ int main(int argc, char *argv[]) if (state == osUnknown && ISMODELESSKEY(key) && cControl::Control() && Interact != cControl::Control()) state = cControl::Control()->ProcessKey(key); 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); Temp = NULL; if (cRecordControls::Start()) @@ -652,13 +678,6 @@ int main(int argc, char *argv[]) break; // Viewing Control: 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: case kRed: case kGreen: |