diff options
author | Klaus Schmidinger <kls (at) cadsoft (dot) de> | 2004-03-14 18:00:00 +0100 |
---|---|---|
committer | Klaus Schmidinger <kls (at) cadsoft (dot) de> | 2004-03-14 18:00:00 +0100 |
commit | 9384e56566f56e77d577319a42929e708936e7c7 (patch) | |
tree | 594b86bcda612612b342c667966c678394a322fc | |
parent | 5a4eb3f1041b8a53826cebe570f9d201f3d35826 (diff) | |
download | vdr-patch-lnbsharing-9384e56566f56e77d577319a42929e708936e7c7.tar.gz vdr-patch-lnbsharing-9384e56566f56e77d577319a42929e708936e7c7.tar.bz2 |
Version 1.3.6vdr-1.3.6
- Completed the Finnish OSD texts (thanks to Rolf Ahrenberg).
- Fixed some descriptor handling in 'libsi' (thanks to Stéphane Esté-Gracias).
- Fixed handling the current menu item (thanks to Marc Hoppe).
- Fixed assigning events to timers (they no longer get "stuck").
- Added log entries whenever the running status of an event changes (currently
only logging the first 30 channels).
- Fixed handling timers in VPS margin if the EPG scan is turned on (the EPG scan
switched the device away from the channel, so it wouldn't see the change of
the running status).
- Fixed handling "itemized" texts in EPG data (thanks to Stéphane Esté-Gracias
for pointing out this problem, and Marcel Wiesweg for improving 'libsi').
- Fixed handling VPS times at year boundaries.
- Avoiding too many consecutive "ring buffer overflow" messages (which only
slowed down performance even more).
- Taking the Sid into account when detecting version changes in processing the
PMT (thanks to Stéphane Esté-Gracias for pointing out this problem).
- Completed the Russian OSD texts (thanks to Vyacheslav Dikonov).
- Any newline characters in the 'description' of EPG events are now preserved
to allow texts to be displayed the way the tv stations have formatted them.
This was also necessary to better display itemized texts.
- Fixed detecting the running status in case an empty EPG event is broadcast (thanks
to Michael Pennewiß for pointing this out).
- Improved performance when paging through very long menu lists.
- Removed cSchedule::GetEventNumber() and cSchedule::NumEvents(). There is now
cSchedule::Events() that returns the list of events directly.
- Avoiding occasional bad responsiveness to user interaction caused by assigning
events to timers.
- Now explicitly turning on the LNB power at startup, because newer drivers don't
do this any more (thanks to Oliver Endriss for pointing this out).
-rw-r--r-- | CONTRIBUTORS | 12 | ||||
-rw-r--r-- | HISTORY | 32 | ||||
-rw-r--r-- | README.vps | 6 | ||||
-rw-r--r-- | channels.conf | 26 | ||||
-rw-r--r-- | config.c | 2 | ||||
-rw-r--r-- | config.h | 6 | ||||
-rw-r--r-- | device.h | 4 | ||||
-rw-r--r-- | dvbdevice.c | 3 | ||||
-rw-r--r-- | eit.c | 22 | ||||
-rw-r--r-- | eitscan.c | 2 | ||||
-rw-r--r-- | eitscan.h | 2 | ||||
-rw-r--r-- | epg.c | 52 | ||||
-rw-r--r-- | epg.h | 13 | ||||
-rw-r--r-- | i18n.c | 28 | ||||
-rw-r--r-- | libsi/descriptor.c | 156 | ||||
-rw-r--r-- | libsi/descriptor.h | 27 | ||||
-rw-r--r-- | libsi/si.c | 83 | ||||
-rw-r--r-- | libsi/si.h | 63 | ||||
-rw-r--r-- | menu.c | 32 | ||||
-rw-r--r-- | menu.h | 2 | ||||
-rw-r--r-- | menuitems.c | 2 | ||||
-rw-r--r-- | menuitems.h | 2 | ||||
-rw-r--r-- | osd.c | 36 | ||||
-rw-r--r-- | pat.c | 18 | ||||
-rw-r--r-- | pat.h | 7 | ||||
-rw-r--r-- | recorder.c | 4 | ||||
-rw-r--r-- | ringbuffer.c | 17 | ||||
-rw-r--r-- | ringbuffer.h | 6 | ||||
-rw-r--r-- | sdt.c | 27 | ||||
-rw-r--r-- | svdrp.c | 2 | ||||
-rw-r--r-- | timers.c | 42 | ||||
-rw-r--r-- | timers.h | 2 | ||||
-rw-r--r-- | transfer.c | 4 | ||||
-rw-r--r-- | vdr.5 | 2 | ||||
-rw-r--r-- | vdr.c | 16 |
35 files changed, 544 insertions, 216 deletions
diff --git a/CONTRIBUTORS b/CONTRIBUTORS index 438d827..1f72231 100644 --- a/CONTRIBUTORS +++ b/CONTRIBUTORS @@ -514,6 +514,8 @@ Oliver Endriss <o.endriss@gmx.de> for suggesting to add 'repeat' function keys '7' and '9' for fixing handling rc key learning in case cRemote::Initialize() returns 'false' for suggesting to change the default "Lifetime" to 99 + for pointing out that the LNB power needs to be explicitly turned on at startup, + because newer drivers don't do this any more Reinhard Walter Buchner <rw.buchner@freenet.de> for adding some satellites to 'sources.conf' @@ -943,3 +945,13 @@ Thomas Bergwinkl <Thomas.Bergwinkl@t-online.de> Stéphane Esté-Gracias <sestegra@free.fr> for fixing a typo in libsi/si.h + for fixing some descriptor handling in 'libsi' + for pointing out a problem with "itemized" texts in EPG data + for pointing out a problem with taking the Sid into account when detecting version + changes in processing the PMT + +Marc Hoppe <MarcHoppe@gmx.de> + for fixing handling the current menu item + +Michael Pennewiß <M.Pennewiss@ARD-Digital.de> + for pointing out that an empty EPG event means there is currently no running event @@ -2713,3 +2713,35 @@ Video Disk Recorder Revision History whether an event has a VPS time that's different than its start time, and whether an event is currently running (see MANUAL under "The "Schedule" Menu" for details). + +2004-03-14: Version 1.3.6 + +- Completed the Finnish OSD texts (thanks to Rolf Ahrenberg). +- Fixed some descriptor handling in 'libsi' (thanks to Stéphane Esté-Gracias). +- Fixed handling the current menu item (thanks to Marc Hoppe). +- Fixed assigning events to timers (they no longer get "stuck"). +- Added log entries whenever the running status of an event changes (currently + only logging the first 30 channels). +- Fixed handling timers in VPS margin if the EPG scan is turned on (the EPG scan + switched the device away from the channel, so it wouldn't see the change of + the running status). +- Fixed handling "itemized" texts in EPG data (thanks to Stéphane Esté-Gracias + for pointing out this problem, and Marcel Wiesweg for improving 'libsi'). +- Fixed handling VPS times at year boundaries. +- Avoiding too many consecutive "ring buffer overflow" messages (which only + slowed down performance even more). +- Taking the Sid into account when detecting version changes in processing the + PMT (thanks to Stéphane Esté-Gracias for pointing out this problem). +- Completed the Russian OSD texts (thanks to Vyacheslav Dikonov). +- Any newline characters in the 'description' of EPG events are now preserved + to allow texts to be displayed the way the tv stations have formatted them. + This was also necessary to better display itemized texts. +- Fixed detecting the running status in case an empty EPG event is broadcast (thanks + to Michael Pennewiß for pointing this out). +- Improved performance when paging through very long menu lists. +- Removed cSchedule::GetEventNumber() and cSchedule::NumEvents(). There is now + cSchedule::Events() that returns the list of events directly. +- Avoiding occasional bad responsiveness to user interaction caused by assigning + events to timers. +- Now explicitly turning on the LNB power at startup, because newer drivers don't + do this any more (thanks to Oliver Endriss for pointing this out). @@ -128,3 +128,9 @@ stations: information to control recording would not see the end of that programme. ... more following as it comes up... + +Contact: +-------- + +ARD Digital: http://www.ard-digital.de/home/index.php?id=16&languageid=1 +ZDF vision: http://www.zdf.de/ZDFde/inhalt/1/0,1872,1021601,00.html (select "zdfvision") diff --git a/channels.conf b/channels.conf index f36c5f3..ca0b6fc 100644 --- a/channels.conf +++ b/channels.conf @@ -24,9 +24,10 @@ VOX:12187:hC34:S19.2E:27500:167:136=deu:71:0:12060:1:1089:0 KABEL1:12480:vC34:S19.2E:27500:511:512:33:0:899:133:33:0 NEUN LIVE,NEUN LIVE Television:12480:vC34:S19.2E:27500:767:768:35:0:897:133:33:0 DSF:12480:vC34:S19.2E:27500:1023:1024=deu:0:0:900:133:33:0 -HSEurope,Home Shopping Europe:12480:vC34:S19.2E:27500:1279:1280:37:0:40:133:33:0 +HSE24:12480:vC34:S19.2E:27500:1279:1280:37:0:40:133:33:0 Bloomberg TV Germany:12551:vC56:S19.2E:22000:162:99=deu:0:0:12160:1:1108:0 EURONEWS:11817:vC34:S19.2E:27500:163:92=fra,93=eng,94=ita,95=esl,91=rus,98=por,99=deu:0:0:8004:1:1070:0 +rbb Brandenburg:12109:hC34:S19.2E:27500:501:502=deu:504:0:28205:1:1073:0 Sky News Intl:11597:vC56:S19.2E:22000:305+131:306=eng:0:0:28707:1:1026:0 Veronica/FoxKids:12574:hC56:S19.2E:22000:518+8190:92=dut:38:622,602,100:5020:53:1109:0 BVN:12574:hC56:S19.2E:22000:515+8190:96=dut:36:0:5025:53:1109:0 @@ -38,20 +39,19 @@ Eurosport:11953:hC34:S19.2E:27500:410:420=deu:430:0:28009:1:1079:0 EinsExtra:12109:hC34:S19.2E:27500:101:102=deu:0:0:28201:1:1073:0 EinsFestival:12109:hC34:S19.2E:27500:201:202=deu:0:0:28202:1:1073:0 EinsMuXx:12109:hC34:S19.2E:27500:301:302=deu:0:0:28203:1:1073:0 -ZDFtheaterkanal:11953:hC34:S19.2E:27500:1110:1120:130:0:28016:1:1079:0 +ZDFtheaterkanal:11953:hC34:S19.2E:27500:1110:1120=deu:130:0:28016:1:1079:0 ZDFdokukanal:11953:hC34:S19.2E:27500:660:670=deu:130:0:28014:1:1079:0 MDR FERNSEHEN:12109:hC34:S19.2E:27500:401:402=deu:404:0:28204:1:1073:0 -RBB Brandenburg:12109:hC34:S19.2E:27500:501:502=deu:504:0:28205:1:1073:0 -RBB Berlin:12109:hC34:S19.2E:27500:601:602=deu:604:0:28206:1:1073:0 +rbb Berlin:12109:hC34:S19.2E:27500:601:602=deu:604:0:28206:1:1073:0 :Premiere World -START,PREMIERE START:11797:hC34:S19.2E:27500:255:256=deu:32:1702,1722,1801:8:133:2:0 -PREM 1,PREMIERE 1:11797:hC34:S19.2E:27500:511:512=deu,513=deu;515=deu:0:1702,1722,1801:10:133:2:0 +START,PREMIERE START:11797:hC34:S19.2E:27500:255:256=deu:32:1722,1801,1702:8:133:2:0 +PREM 1,PREMIERE 1:11797:hC34:S19.2E:27500:511:512=deu;515=deu:0:1702,1801,1722:10:133:2:0 PREM 2,PREMIERE 2:11797:hC34:S19.2E:27500:1791:1792=deu,1793=deu;1795=deu:0:1702,1722,1801:11:133:2:0 -PREM 3,PREMIERE 3:11797:hC34:S19.2E:27500:2303:2304=deu:0:1702,1722,1801:43:133:2:0 -PREM 4,PREMIERE 4:11797:hC34:S19.2E:27500:767:768=deu:0:1702,1722,1801:9:133:2:0 -PREM 5,PREMIERE 5:11797:hC34:S19.2E:27500:1279:1280=deu,1281=deu:0:1702,1722,1801:29:133:2:0 -PREM 6,PREMIERE 6:11797:hC34:S19.2E:27500:1535:1536=deu:0:1702,1722,1801:41:133:2:0 -PREM 7,PREMIERE 7:11797:hC34:S19.2E:27500:1023:1024=deu:0:1702,1722,1801:20:133:2:0 +PREM 3,PREMIERE 3:11797:hC34:S19.2E:27500:2303:2304=deu:0:1722,1702,1801:43:133:2:0 +PREM 4,PREMIERE 4:11797:hC34:S19.2E:27500:767:768=deu:0:1801,1722,1702:9:133:2:0 +PREM 5,PREMIERE 5:11797:hC34:S19.2E:27500:1279:1280=deu:0:1801,1702,1722:29:133:2:0 +PREM 6,PREMIERE 6:11797:hC34:S19.2E:27500:1535:1536=deu:0:1722,1801,1702:41:133:2:0 +PREM 7,PREMIERE 7:11797:hC34:S19.2E:27500:1023:1024=deu:0:1722,1702,1801:20:133:2:0 DISNEY,DISNEY CHANNEL:11758:hC34:S19.2E:27500:2559:2560=deu:0:1702,1722,1801:34:133:17:0 :Premiere Direkt DIREKT,PREMIERE DIREKT:12031:hC34:S19.2E:27500:2815:2816=deu,2817=deu;2819=deu:0:0:18:133:4:0 @@ -59,7 +59,7 @@ DIREKT,PREMIERE DIREKT:12031:hC34:S19.2E:27500:2815:2816=deu,2817=deu;2819=deu:0 B-UHSE,BEATE-UHSE.TV:12070:hC34:S19.2E:27500:1023:1024=deu:0:1702,1722,1801:21:133:1:0 EROTIK,PREMIERE EROTIK:12031:hC34:S19.2E:27500:1279:0:0:1702,1722,1801:513:133:4:0 :Sportsworld -Konferenz:11719:hC34:S19.2E:27500:255:256=deu:0:1702,1722,1801:17:133:3:0 +SPORT 1,PREMIERE SPORT 1:11719:hC34:S19.2E:27500:255:256=deu,257=deu:0:1702,1722,1801:17:133:3:0 SPORT 2,PREMIERE SPORT 2:12031:hC34:S19.2E:27500:3839:3840=deu,3841=deu:0:1702,1722,1801:27:133:4:0 :Beta Digital N24:12480:vC34:S19.2E:27500:2047:2048:36:0:47:133:33:0 @@ -114,6 +114,6 @@ Animal Plnt+:12070:hC23:S28.2E:27500:2315+2307:2316=eng:0:960,961:50002:2:2019:0 S1T:12285:vC23:S28.2E:27500:2311+2304:2312=eng,2313=NAR:2307:960,961:4409:2:2030:0 CNN:12051:vC23:S28.2E:27500:2309:2311=eng:2310:0:7140:2:2018:0 BBC PARL'MNT:12129:vC23:S28.2E:27500:2306:2308=eng,2309=eng:2307:0:7300:2:2022:0 -AL HAYAT:11200:vC56:S13.0E:27500:413:414:0:0:4733:318:13400:0 +AL HAYAT:11200:vC56:S13.0E:27500:413:414=eng:0:0:4733:318:13400:0 EURO1080:12168:vC34:S19.2E:27500:308:256:0:FF:21100:1:1088:0 :@1000 New channels @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: config.c 1.124 2004/02/21 15:05:40 kls Exp kls $ + * $Id: config.c 1.125 2004/02/28 11:12:20 kls Exp $ */ #include "config.h" @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: config.h 1.188 2004/02/21 15:04:53 kls Exp kls $ + * $Id: config.h 1.190 2004/03/05 14:35:15 kls Exp $ */ #ifndef __CONFIG_H @@ -20,8 +20,8 @@ #include "i18n.h" #include "tools.h" -#define VDRVERSION "1.3.5" -#define VDRVERSNUM 10305 // Version * 10000 + Major * 100 + Minor +#define VDRVERSION "1.3.6" +#define VDRVERSNUM 10306 // Version * 10000 + Major * 100 + Minor #define MAXPRIORITY 99 #define MAXLIFETIME 99 @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: device.h 1.40 2004/02/14 11:29:57 kls Exp $ + * $Id: device.h 1.41 2004/03/14 10:47:01 kls Exp $ */ #ifndef __DEVICE_H @@ -382,7 +382,7 @@ public: virtual int PlayVideo(const uchar *Data, int Length); ///< Actually plays the given data block as video. The data must be ///< part of a PES (Packetized Elementary Stream) which can contain - ///< one video and one audio strem. + ///< one video and one audio stream. virtual void PlayAudio(const uchar *Data, int Length); ///< Plays additional audio streams, like Dolby Digital. ///< A derived class must call the base class function to make sure data diff --git a/dvbdevice.c b/dvbdevice.c index 8ed62e1..6e1d7f9 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.82 2004/02/24 10:12:13 kls Exp $ + * $Id: dvbdevice.c 1.83 2004/03/14 14:47:46 kls Exp $ */ #include "dvbdevice.h" @@ -101,6 +101,7 @@ cDvbTuner::cDvbTuner(int Fd_Frontend, int CardIndex, fe_type_t FrontendType, cCi useCa = false; tunerStatus = tsIdle; startTime = time(NULL); + CHECK(ioctl(fd_frontend, FE_SET_VOLTAGE, SEC_VOLTAGE_13)); // must explicitly turn on LNB power SetDescription("tuner on device %d", cardIndex + 1); Start(); } @@ -8,7 +8,7 @@ * Robert Schneider <Robert.Schneider@web.de> and Rolf Hakenes <hakenes@hippomi.de>. * Adapted to 'libsi' for VDR 1.3.0 by Marcel Wiesweg <marcel.wiesweg@gmx.de>. * - * $Id: eit.c 1.89 2004/02/22 13:17:52 kls Exp kls $ + * $Id: eit.c 1.93 2004/03/13 13:54:20 kls Exp $ */ #include "eit.h" @@ -43,10 +43,12 @@ cEIT::cEIT(cSchedules *Schedules, int Source, u_char Tid, const u_char *Data) Schedules->Add(pSchedule); } + bool Empty = true; bool Modified = false; SI::EIT::Event SiEitEvent; for (SI::Loop::Iterator it; eventLoop.hasNext(it); ) { + Empty = false; SiEitEvent = eventLoop.getNext(it); cEvent *pEvent = (cEvent *)pSchedule->GetEvent(SiEitEvent.getEventId(), SiEitEvent.getStartTime()); @@ -82,10 +84,6 @@ cEIT::cEIT(cSchedules *Schedules, int Source, u_char Tid, const u_char *Data) pEvent->SetVersion(getVersionNumber()); pEvent->SetStartTime(SiEitEvent.getStartTime()); pEvent->SetDuration(SiEitEvent.getDuration()); - if (isPresentFollowing()) { - if (SiEitEvent.getRunningStatus() > SI::RunningStatusNotRunning) - pSchedule->SetRunningStatus(pEvent, SiEitEvent.getRunningStatus()); - } int LanguagePreferenceShort = -1; int LanguagePreferenceExt = -1; @@ -130,11 +128,16 @@ cEIT::cEIT(cSchedules *Schedules, int Source, u_char Tid, const u_char *Data) struct tm tm_r; struct tm t = *localtime_r(&now, &tm_r); // this initializes the time zone in 't' t.tm_isdst = -1; // makes sure mktime() will determine the correct DST setting + int month = t.tm_mon; t.tm_mon = pd->getMonth() - 1; t.tm_mday = pd->getDay(); t.tm_hour = pd->getHour(); t.tm_min = pd->getMinute(); t.tm_sec = 0; + if (month == 11 && t.tm_mon == 0) // current month is dec, but event is in jan + t.tm_year++; + else if (month == 0 && t.tm_mon == 11) // current month is jan, but event is in dec + t.tm_year--; time_t vps = mktime(&t); pEvent->SetVps(vps); } @@ -195,7 +198,7 @@ cEIT::cEIT(cSchedules *Schedules, int Source, u_char Tid, const u_char *Data) } if (ExtendedEventDescriptors) { char buffer[ExtendedEventDescriptors->getMaximumTextLength()]; - pEvent->SetDescription(ExtendedEventDescriptors->getText(buffer)); + pEvent->SetDescription(ExtendedEventDescriptors->getText(buffer, ": ")); } } delete ExtendedEventDescriptors; @@ -205,8 +208,15 @@ cEIT::cEIT(cSchedules *Schedules, int Source, u_char Tid, const u_char *Data) if (LinkChannels) channel->SetLinkChannels(LinkChannels); + if (Tid == 0x4E) { // we trust only the present/following info on the actual TS + if (SiEitEvent.getRunningStatus() >= SI::RunningStatusNotRunning) + pSchedule->SetRunningStatus(pEvent, SiEitEvent.getRunningStatus(), channel); + } Modified = true; } + if (Empty && Tid == 0x4E && getSectionNumber() == 0) + // ETR 211: an empty entry in section 0 of table 0x4E means there is currently no event running + pSchedule->ClrRunningStatus(channel); if (Modified) pSchedule->Sort(); } @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: eitscan.c 1.21 2004/02/14 13:44:31 kls Exp kls $ + * $Id: eitscan.c 1.21 2004/02/14 13:44:31 kls Exp $ */ #include "eitscan.h" @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: eitscan.h 1.8 2004/01/17 15:36:24 kls Exp kls $ + * $Id: eitscan.h 1.8 2004/01/17 15:36:24 kls Exp $ */ #ifndef __EITSCAN_H @@ -7,7 +7,7 @@ * Original version (as used in VDR before 1.3.0) written by * Robert Schneider <Robert.Schneider@web.de> and Rolf Hakenes <hakenes@hippomi.de>. * - * $Id: epg.c 1.13 2004/02/22 14:41:37 kls Exp kls $ + * $Id: epg.c 1.18 2004/03/13 15:01:05 kls Exp $ */ #include "epg.h" @@ -61,8 +61,11 @@ void cEvent::SetVersion(uchar Version) version = Version; } -void cEvent::SetRunningStatus(int RunningStatus) +void cEvent::SetRunningStatus(int RunningStatus, cChannel *Channel) { + if (Channel && runningStatus != RunningStatus && (RunningStatus > SI::RunningStatusNotRunning || runningStatus > SI::RunningStatusUndefined)) + if (Channel->Number() <= 30)//XXX maybe log only those that have timers??? + isyslog("channel %d (%s) event %s '%s' status %d", Channel->Number(), Channel->Name(), GetTimeString(), Title(), RunningStatus); runningStatus = RunningStatus; } @@ -105,6 +108,11 @@ bool cEvent::HasTimer(void) const return false; } +bool cEvent::IsRunning(bool OrAboutToStart) const +{ + return runningStatus >= (OrAboutToStart ? SI::RunningStatusStartsInAFewSeconds : SI::RunningStatusPausing); +} + const char *cEvent::GetDateString(void) const { static char buf[25]; @@ -146,8 +154,11 @@ void cEvent::Dump(FILE *f, const char *Prefix) const fprintf(f, "%sT %s\n", Prefix, title); if (!isempty(shortText)) fprintf(f, "%sS %s\n", Prefix, shortText); - if (!isempty(description)) + if (!isempty(description)) { + strreplace(description, '\n', '|'); fprintf(f, "%sD %s\n", Prefix, description); + strreplace(description, '|', '\n'); + } if (vps) fprintf(f, "%sV %ld\n", Prefix, vps); fprintf(f, "%se\n", Prefix); @@ -186,8 +197,10 @@ bool cEvent::Read(FILE *f, cSchedule *Schedule) case 'S': if (Event) Event->SetShortText(t); break; - case 'D': if (Event) + case 'D': if (Event) { + strreplace(t, '|', '\n'); Event->SetDescription(t); + } break; case 'V': if (Event) Event->SetVps(atoi(t)); @@ -282,11 +295,10 @@ void ReportEpgBugFixStats(bool Reset) void cEvent::FixEpgBugs(void) { - // VDR can't usefully handle newline characters in the EPG data, so let's - // always convert them to blanks (independent of the setting of EPGBugfixLevel): + // VDR can't usefully handle newline characters in the title and shortText of EPG + // data, so let's always convert them to blanks (independent of the setting of EPGBugfixLevel): strreplace(title, '\n', ' '); strreplace(shortText, '\n', ' '); - strreplace(description, '\n', ' '); // Same for control characters: strreplace(title, '\x86', ' '); strreplace(title, '\x87', ' '); @@ -462,6 +474,7 @@ void cEvent::FixEpgBugs(void) cSchedule::cSchedule(tChannelID ChannelID) { channelID = ChannelID; + hasRunning = false;; } cEvent *cSchedule::AddEvent(cEvent *Event) @@ -475,7 +488,7 @@ const cEvent *cSchedule::GetPresentEvent(bool CheckRunningStatus) const const cEvent *pe = NULL; time_t now = time(NULL); for (cEvent *p = events.First(); p; p = events.Next(p)) { - if (p->StartTime() <= now && now < p->StartTime() + p->Duration()) { + if (p->StartTime() <= now && now < p->EndTime()) { pe = p; if (!CheckRunningStatus) break; @@ -514,7 +527,7 @@ const cEvent *cSchedule::GetEventAround(time_t Time) const time_t delta = INT_MAX; for (cEvent *p = events.First(); p; p = events.Next(p)) { time_t dt = Time - p->StartTime(); - if (dt >= 0 && dt < delta && p->StartTime() + p->Duration() >= Time) { + if (dt >= 0 && dt < delta && p->EndTime() >= Time) { delta = dt; pe = p; } @@ -522,14 +535,29 @@ const cEvent *cSchedule::GetEventAround(time_t Time) const return pe; } -void cSchedule::SetRunningStatus(cEvent *Event, int RunningStatus) +void cSchedule::SetRunningStatus(cEvent *Event, int RunningStatus, cChannel *Channel) { for (cEvent *p = events.First(); p; p = events.Next(p)) { if (p == Event) - p->SetRunningStatus(RunningStatus); + p->SetRunningStatus(RunningStatus, Channel); else if (RunningStatus >= SI::RunningStatusPausing && p->RunningStatus() > SI::RunningStatusNotRunning) p->SetRunningStatus(SI::RunningStatusNotRunning); } + if (RunningStatus >= SI::RunningStatusPausing) + hasRunning = true; +} + +void cSchedule::ClrRunningStatus(cChannel *Channel) +{ + if (hasRunning) { + for (cEvent *p = events.First(); p; p = events.Next(p)) { + if (p->RunningStatus() >= SI::RunningStatusPausing) { + p->SetRunningStatus(SI::RunningStatusNotRunning, Channel); + hasRunning = false; + break; + } + } + } } void cSchedule::ResetVersions(void) @@ -555,7 +583,7 @@ void cSchedule::Cleanup(time_t Time) Event = events.Get(a); if (!Event) break; - if (!Event->HasTimer() && Event->StartTime() + Event->Duration() + Setup.EPGLinger * 60 + 3600 < Time) { // adding one hour for safety + if (!Event->HasTimer() && Event->EndTime() + Setup.EPGLinger * 60 + 3600 < Time) { // adding one hour for safety events.Del(Event); a--; } @@ -7,7 +7,7 @@ * Original version (as used in VDR before 1.3.0) written by * Robert Schneider <Robert.Schneider@web.de> and Rolf Hakenes <hakenes@hippomi.de>. * - * $Id: epg.h 1.10 2004/02/22 14:34:04 kls Exp kls $ + * $Id: epg.h 1.15 2004/03/14 13:25:39 kls Exp $ */ #ifndef __EPG_H @@ -49,9 +49,11 @@ public: const char *ShortText(void) const { return shortText; } const char *Description(void) const { return description; } time_t StartTime(void) const { return startTime; } + time_t EndTime(void) const { return startTime + duration; } int Duration(void) const { return duration; } time_t Vps(void) const { return vps; } bool HasTimer(void) const; + bool IsRunning(bool OrAboutToStart = false) const; const char *GetDateString(void) const; const char *GetTimeString(void) const; const char *GetEndTimeString(void) const; @@ -59,7 +61,7 @@ public: void SetEventID(u_int16_t EventID); void SetTableID(uchar TableID); void SetVersion(uchar Version); - void SetRunningStatus(int RunningStatus); + void SetRunningStatus(int RunningStatus, cChannel *Channel = NULL); void SetTitle(const char *Title); void SetShortText(const char *ShortText); void SetDescription(const char *Description); @@ -77,21 +79,22 @@ class cSchedule : public cListObject { private: tChannelID channelID; cList<cEvent> events; + bool hasRunning; public: cSchedule(tChannelID ChannelID); tChannelID ChannelID(void) const { return channelID; } - void SetRunningStatus(cEvent *Event, int RunningStatus); + void SetRunningStatus(cEvent *Event, int RunningStatus, cChannel *Channel = NULL); + void ClrRunningStatus(cChannel *Channel = NULL); void ResetVersions(void); void Sort(void); void Cleanup(time_t Time); void Cleanup(void); cEvent *AddEvent(cEvent *Event); + const cList<cEvent> *Events(void) const { return &events; } const cEvent *GetPresentEvent(bool CheckRunningStatus = false) const; const cEvent *GetFollowingEvent(bool CheckRunningStatus = false) const; const cEvent *GetEvent(u_int16_t EventID, time_t StartTime = 0) const; const cEvent *GetEventAround(time_t Time) const; - const cEvent *GetEventNumber(int n) const { return events.Get(n); } - int NumEvents(void) const { return events.Count(); } void Dump(FILE *f, const char *Prefix = "", eDumpMode DumpMode = dmAll, time_t AtTime = 0) const; static bool Read(FILE *f, cSchedules *Schedules); }; @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: i18n.c 1.148 2004/02/21 15:14:36 kls Exp kls $ + * $Id: i18n.c 1.152 2004/03/13 10:59:23 kls Exp $ * * Translations provided by: * @@ -1550,6 +1550,7 @@ const tI18nPhrase Phrases[] = { "",// TODO "",// TODO "",// TODO + "VPS", "",// TODO "",// TODO "",// TODO @@ -1557,8 +1558,7 @@ const tI18nPhrase Phrases[] = { "",// TODO "",// TODO "",// TODO - "",// TODO - "",// TODO + "VPS ßÞßàÐÒÚÐ", }, { "Priority", "Priorität", @@ -1839,9 +1839,9 @@ const tI18nPhrase Phrases[] = { "",//TODO "Pas de marques d'édition définies!", "",//TODO - "",//TODO + "Muokkausmerkinnät puuttuvat!", "Brak znakow montazowych!", - "Muokkausmerkinnät puuttuvat", + "",//TODO "ÄÝí Ý÷ïõí ïñéóôåß óçìåßá åðåîåñãáóßáò", "Det finns inga redigeringsmärken",//TODO "",//TODO @@ -2389,7 +2389,7 @@ const tI18nPhrase Phrases[] = { "",// TODO "",// TODO "",// TODO - "",// TODO + "ÅàÐÝÕÝØÕ ãáâÐàÕÒèØå ÔÐÝÝëå (ÜØÝ)", }, { "Setup.EPG$Set system time", "Systemzeit stellen", @@ -2777,7 +2777,7 @@ const tI18nPhrase Phrases[] = { "",// TODO "Priorité des pauses", "",// TODO - "Keskeytyksen prioriteetti", + "Taukotallenteen prioriteetti", "Priorytet przerwy", "",// TODO "Ðñïôåñáéüôçôá äéáëåßììáôïò", @@ -2795,7 +2795,7 @@ const tI18nPhrase Phrases[] = { "",// TODO "Durée de vie des pauses (j)", "",// TODO - "Keskeytyksen elinikä (d)", + "Taukotallenteen elinikä (d)", "Okres trwania przerwy (d)", "",// TODO "ÄéÜñêåéá äéáëåßìáôïò", @@ -2831,6 +2831,7 @@ const tI18nPhrase Phrases[] = { "",// TODO "",// TODO "",// TODO + "Käytä VPS-toimintoa", "",// TODO "",// TODO "",// TODO @@ -2838,8 +2839,7 @@ const tI18nPhrase Phrases[] = { "",// TODO "",// TODO "",// TODO - "",// TODO - "",// TODO + "¸áßÞÛì×ÞÒÐâì áØÓÝÐÛë VPS", }, { "Setup.Recording$VPS margin (s)", "Zeitpuffer bei VPS (s)", @@ -2849,6 +2849,7 @@ const tI18nPhrase Phrases[] = { "",// TODO "",// TODO "",// TODO + "VPS-toiminnon aloitusmarginaali (s)", "",// TODO "",// TODO "",// TODO @@ -2856,8 +2857,7 @@ const tI18nPhrase Phrases[] = { "",// TODO "",// TODO "",// TODO - "",// TODO - "",// TODO + "±ãäÕàÝÞÕ ÒàÕÜï VPS (áÕÚ)", }, { "Setup.Recording$Mark instant recording", "Direktaufzeichnung markieren", @@ -3627,7 +3627,7 @@ const tI18nPhrase Phrases[] = { "",// TODO "Pause", "",// TODO - "Keskeytä", + "Tauko", "Przerwa", "Pausa", "ÄéÜëåéììá", @@ -4186,7 +4186,7 @@ const tI18nPhrase Phrases[] = { "",// TODO "Pause de l'émission en direct...", "",// TODO - "Keskeytetään lähetys...", + "Pysäytetään lähetys...", "Zatrzymany program biezacy...", "Emisión en directo parada...", "ÄéÜëåéììá æùíôáíïý óÞìáôïò", diff --git a/libsi/descriptor.c b/libsi/descriptor.c index 0b0019f..82e2a8f 100644 --- a/libsi/descriptor.c +++ b/libsi/descriptor.c @@ -6,7 +6,7 @@ * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * - * $Id: descriptor.c 1.6 2004/02/22 11:11:36 kls Exp $ + * $Id: descriptor.c 1.10 2004/03/13 15:08:12 kls Exp $ * * ***************************************************************************/ @@ -60,13 +60,13 @@ void ExtendedEventDescriptor::Item::Parse() { item.setData(data+offset, mid->item_length); } -int ExtendedEventDescriptors::getTextLength() { +/*int ExtendedEventDescriptors::getTextLength() { int ret=0; for (int i=0;i<length;i++) { ExtendedEventDescriptor *d=(ExtendedEventDescriptor *)array[i]; if (!d) continue; - ret+=d->text.getLength()+1; //plus a blank + ret+=d->text.getLength(); ExtendedEventDescriptor::Item item; for (Loop::Iterator it; d->itemLoop.hasNext(it); ) { item=d->itemLoop.getNext(it); @@ -76,28 +76,84 @@ int ExtendedEventDescriptors::getTextLength() { } } return ret; -} +}*/ -//is there a case where this function does not return the same as getTextLength? int ExtendedEventDescriptors::getMaximumTextLength() { + return getMaximumTextPlainLength()+getMaximumTextItemizedLength(); +} + +char *ExtendedEventDescriptors::getText(const char *separation1, const char *separation2) { + char *text=new char[getMaximumTextLength()+strlen(separation1)+strlen(separation2)]; + return getText(text, separation1, separation2); +} + +char *ExtendedEventDescriptors::getText(char *buffer, const char *separation1, const char *separation2) { + int index=0, len; + char tempbuf[256]; + for (int i=0;i<length;i++) { + ExtendedEventDescriptor *d=(ExtendedEventDescriptor *)array[i]; + if (!d) + continue; + d->text.getText(tempbuf); + len=strlen(tempbuf); + if (len) { + memcpy(buffer+index, tempbuf, len); + index+=len; + } + } + + for (int i=0;i<length;i++) { + ExtendedEventDescriptor *d=(ExtendedEventDescriptor *)array[i]; + if (!d) + continue; + + strcpy(buffer+index, separation2); // let's have a separator between the long text and the items + index += strlen(separation2); + ExtendedEventDescriptor::Item item; + for (Loop::Iterator it; d->itemLoop.hasNext(it); ) { + item=d->itemLoop.getNext(it); + + item.itemDescription.getText(tempbuf); + len=strlen(tempbuf); + if (len) { + memcpy(buffer+index, tempbuf, len); + index+=len; + } + strcpy(buffer+index, separation1); + index += strlen(separation1); + + item.item.getText(tempbuf); + len=strlen(tempbuf); + if (len) { + memcpy(buffer+index, tempbuf, len); + index+=len; + } + strcpy(buffer+index, separation2); + index += strlen(separation2); + } + } + + buffer[index]='\0'; + return buffer; +} + +int ExtendedEventDescriptors::getMaximumTextPlainLength() { int ret=0; for (int i=0;i<length;i++) { ExtendedEventDescriptor *d=(ExtendedEventDescriptor *)array[i]; if (!d) continue; - ret+=d->text.getLength()+1; //plus a blank - ret+=d->itemLoop.getLength(); + ret+=d->text.getLength(); } return ret; } -char *ExtendedEventDescriptors::getText() { - char *text=new char[getMaximumTextLength()]; - return getText(text); +char *ExtendedEventDescriptors::getTextPlain() { + char *text=new char[getMaximumTextPlainLength()]; + return getTextPlain(text); } -//appends the Strings of every Descriptor in the group -char *ExtendedEventDescriptors::getText(char *buffer) { +char *ExtendedEventDescriptors::getTextPlain(char *buffer) { int index=0, len; char tempbuf[256]; for (int i=0;i<length;i++) { @@ -110,30 +166,98 @@ char *ExtendedEventDescriptors::getText(char *buffer) { memcpy(buffer+index, tempbuf, len); index+=len; } + } + buffer[index]='\0'; + return buffer; +} + +int ExtendedEventDescriptors::getMaximumTextItemizedLength() { + int ret=0; + for (int i=0;i<length;i++) { + ExtendedEventDescriptor *d=(ExtendedEventDescriptor *)array[i]; + if (!d) + continue; + //the size for the two separating characters is included ;-) + ret+=d->itemLoop.getLength(); + } + return ret; +} + +char *ExtendedEventDescriptors::getTextItemized(const char *separation1, const char *separation2) { + char *text=new char[getMaximumTextItemizedLength()+strlen(separation1)+strlen(separation2)]; + return getTextItemized(text, separation1, separation2); +} + +char *ExtendedEventDescriptors::getTextItemized(char *buffer, const char *separation1, const char *separation2) { + int index=0, len; + char tempbuf[256]; + for (int i=0;i<length;i++) { + ExtendedEventDescriptor *d=(ExtendedEventDescriptor *)array[i]; + if (!d) + continue; ExtendedEventDescriptor::Item item; for (Loop::Iterator it; d->itemLoop.hasNext(it); ) { item=d->itemLoop.getNext(it); - item.item.getText(tempbuf); + item.itemDescription.getText(tempbuf); len=strlen(tempbuf); if (len) { memcpy(buffer+index, tempbuf, len); index+=len; } + strcpy(buffer+index, separation1); + index += strlen(separation1); - item.itemDescription.getText(tempbuf); + item.item.getText(tempbuf); len=strlen(tempbuf); if (len) { memcpy(buffer+index, tempbuf, len); index+=len; } + strcpy(buffer+index, separation2); + index += strlen(separation2); } } buffer[index]='\0'; return buffer; } +//returns the itemized text pair by pair. Maximum length for buffers is 256. +//Return value is false if and only if the end of the list is reached. +bool ExtendedEventDescriptors::getTextItemized(Loop::Iterator &it, bool &valid, char *itemDescription, char *itemText) { + //The iterator has to store two values: The descriptor index (4bit) + //and the item loop index (max overall length 256, min item length 16 => max number 128 => 7bit) + valid=false; + + int index=(it.i & 0x780) >> 7; // 0x780 == 1111 000 0000 + it.i &= 0x7F; //0x7F == 111 1111 + + for (;index<length;index++) { + ExtendedEventDescriptor *d=(ExtendedEventDescriptor *)array[index]; + if (!d) + continue; + + ExtendedEventDescriptor::Item item; + if (d->itemLoop.hasNext(it)) { + item=d->itemLoop.getNext(it); + + item.item.getText(itemDescription); + item.itemDescription.getText(itemText); + valid=true; + break; + } else { + it.reset(); + continue; + } + } + + it.i &= 0x7F; + it.i |= (index & 0xF) << 7; //0xF == 1111 + + return index<length; +} + int TimeShiftedEventDescriptor::getReferenceServiceId() const { return HILO(s->reference_service_id); } @@ -148,7 +272,7 @@ void TimeShiftedEventDescriptor::Parse() { void ContentDescriptor::Parse() { //this descriptor is only a header and a loop - nibbleLoop.setData(data+sizeof(SectionHeader), getLength()-sizeof(SectionHeader)); + nibbleLoop.setData(data+sizeof(descr_content), getLength()-sizeof(descr_content)); } int ContentDescriptor::Nibble::getContentNibbleLevel1() const { @@ -173,7 +297,7 @@ void ContentDescriptor::Nibble::Parse() { void ParentalRatingDescriptor::Parse() { //this descriptor is only a header and a loop - ratingLoop.setData(data+sizeof(SectionHeader), getLength()-sizeof(SectionHeader)); + ratingLoop.setData(data+sizeof(descr_parental_rating), getLength()-sizeof(descr_parental_rating)); } int ParentalRatingDescriptor::Rating::getRating() const { diff --git a/libsi/descriptor.h b/libsi/descriptor.h index 17c81eb..3368b0a 100644 --- a/libsi/descriptor.h +++ b/libsi/descriptor.h @@ -6,7 +6,7 @@ * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * - * $Id: descriptor.h 1.6 2004/02/22 10:16:47 kls Exp $ + * $Id: descriptor.h 1.7 2004/03/07 11:13:54 kls Exp $ * * ***************************************************************************/ @@ -50,14 +50,29 @@ private: class ExtendedEventDescriptors : public DescriptorGroup { public: - //don't use - int getTextLength(); - //really fast int getMaximumTextLength(); + //Returns a concatenated version of first the non-itemized and then the itemized text //same semantics as with SI::String - char *getText(); + char *getText(const char *separation1="\t", const char *separation2="\n"); //buffer must at least be getTextLength(), getMaximumTextLength() is a good choice - char *getText(char *buffer); + char *getText(char *buffer, const char *separation1="\t", const char *separation2="\n"); + + //these only return the non-itemized text fields in concatenated form + int getMaximumTextPlainLength(); + char *getTextPlain(); + char *getTextPlain(char *buffer); + + //these only return the itemized text fields in concatenated form. + //Between the description and the text the separation1 character is used, + //separation2 used between two pairs. Example: + //Director\tSteven Spielberg\nActor\tMichael Mendl\n + int getMaximumTextItemizedLength(); + char *getTextItemized(const char *separation1="\t", const char *separation2="\n"); + char *getTextItemized(char *buffer, const char *separation1="\t", const char *separation2="\n"); + //returns the itemized text pair by pair. Maximum length for buffers is 256. + //Return value is false if and only if the end of the list is reached. + //The argument valid indicates whether the buffers contain valid content. + bool getTextItemized(Loop::Iterator &it, bool &valid, char *itemDescription, char *itemText); }; class TimeShiftedEventDescriptor : public Descriptor { @@ -6,7 +6,7 @@ * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * - * $Id: si.c 1.8 2004/02/22 10:14:12 kls Exp $ + * $Id: si.c 1.9 2004/03/07 10:50:09 kls Exp $ * * ***************************************************************************/ @@ -103,7 +103,7 @@ DescriptorTag Descriptor::getDescriptorTag(const unsigned char *d) { Descriptor *DescriptorLoop::getNext(Iterator &it) { if (it.i<getLength()) { - return createDescriptor(it.i); + return createDescriptor(it.i, true); } return 0; } @@ -115,19 +115,18 @@ Descriptor *DescriptorLoop::getNext(Iterator &it, DescriptorTag tag, bool return const unsigned char *end=p+getLength(); while (p < end) { if (Descriptor::getDescriptorTag(p) == tag) { - d=createDescriptor(it.i); - break; + d=createDescriptor(it.i, returnUnimplemetedDescriptor); + if (d) + break; } it.i+=Descriptor::getLength(p); p+=Descriptor::getLength(p); } } - if (d && d->getDescriptorTag()==UnimplementedDescriptorTag) - return returnUnimplemetedDescriptor ? d : 0; return d; } -Descriptor *DescriptorLoop::getNext(Iterator &it, DescriptorTag *tags, int arrayLength, bool returnUnimplemetedDescriptor) { +Descriptor *DescriptorLoop::getNext(Iterator &it, DescriptorTag *tags, int arrayLength, bool returnUnimplementedDescriptor) { Descriptor *d=0; if (it.i<getLength()) { const unsigned char *p=data.getData(it.i); @@ -135,27 +134,38 @@ Descriptor *DescriptorLoop::getNext(Iterator &it, DescriptorTag *tags, int array while (p < end) { for (int u=0; u<arrayLength;u++) if (Descriptor::getDescriptorTag(p) == tags[u]) { - d=createDescriptor(it.i); + d=createDescriptor(it.i, returnUnimplementedDescriptor); break; } if (d) - break; + break; //length is added to it.i by createDescriptor, break here it.i+=Descriptor::getLength(p); p+=Descriptor::getLength(p); } } - if (d && d->getDescriptorTag()==UnimplementedDescriptorTag) - return returnUnimplemetedDescriptor ? d : 0; return d; } -Descriptor *DescriptorLoop::createDescriptor(int &i) { - Descriptor *d=Descriptor::getDescriptor(data+i, domain); +Descriptor *DescriptorLoop::createDescriptor(int &i, bool returnUnimplemetedDescriptor) { + Descriptor *d=Descriptor::getDescriptor(data+i, domain, returnUnimplemetedDescriptor); + if (!d) + return 0; i+=d->getLength(); d->CheckParse(); return d; } +int DescriptorLoop::getNumberOfDescriptors() { + const unsigned char *p=data.getData(); + const unsigned char *end=p+getLength(); + int count=0; + while (p < end) { + count++; + p+=Descriptor::getLength(p); + } + return count; +} + DescriptorGroup::DescriptorGroup(bool del) { array=0; length=0; @@ -211,6 +221,16 @@ char *String::getText(char *buffer) { return buffer; } +//taken from VDR, Copyright Klaus Schmidinger <kls@cadsoft.de> +char *String::getText(char *buffer, char *shortVersion) { + if (getLength() < 0 || getLength() >4095) { + strncpy(buffer, "text error", getLength()+1); + return buffer; + } + decodeText(buffer, shortVersion); + return buffer; +} + //taken from libdtv, Copyright Rolf Hakenes <hakenes@hippomi.de> void String::decodeText(char *buffer) { const unsigned char *from=data.getData(0); @@ -228,18 +248,47 @@ void String::decodeText(char *buffer) { if ( ((' ' <= *from) && (*from <= '~')) || (*from == '\n') || (0xA0 <= *from) + || (*from == 0x86 || *from == 0x87) ) *to++ = *from; else if (*from == 0x8A) *to++ = '\n'; - else if (*from == 0x86 || *from == 0x87) //&& !(GDT_NAME_DESCRIPTOR & type)) + from++; + } + *to = '\0'; +} + +void String::decodeText(char *buffer, char *shortVersion) { + const unsigned char *from=data.getData(0); + char *to=buffer; + char *toShort=shortVersion; + int IsShortName=0; + + for (int i = 0; i < getLength(); i++) { + if (*from == 0) + break; + if ( ((' ' <= *from) && (*from <= '~')) + || (*from == '\n') + || (0xA0 <= *from) + ) + { *to++ = *from; + if (IsShortName) + *toShort++ = *from; + } + else if (*from == 0x8A) + *to++ = '\n'; + else if (*from == 0x86) + IsShortName++; + else if (*from == 0x87) + IsShortName--; from++; } *to = '\0'; + *toShort = '\0'; } -Descriptor *Descriptor::getDescriptor(CharArray da, DescriptorTagDomain domain) { +Descriptor *Descriptor::getDescriptor(CharArray da, DescriptorTagDomain domain, bool returnUnimplemetedDescriptor) { Descriptor *d=0; switch (domain) { case SI: @@ -383,6 +432,8 @@ Descriptor *Descriptor::getDescriptor(CharArray da, DescriptorTagDomain domain) case AdaptationFieldDataDescriptorTag: case TransportStreamDescriptorTag: default: + if (!returnUnimplemetedDescriptor) + return 0; d=new UnimplementedDescriptor(); break; } @@ -417,6 +468,8 @@ Descriptor *Descriptor::getDescriptor(CharArray da, DescriptorTagDomain domain) case MHP_DelegatedApplicationDescriptorTag: case MHP_ApplicationStorageDescriptorTag: default: + if (!returnUnimplemetedDescriptor) + return 0; d=new UnimplementedDescriptor(); break; } @@ -6,7 +6,7 @@ * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * - * $Id: si.h 1.8 2004/02/23 17:02:33 kls Exp $ + * $Id: si.h 1.9 2004/03/07 10:09:49 kls Exp $ * * ***************************************************************************/ @@ -252,8 +252,11 @@ protected: //returns a subclass of descriptor according to the data given. //The object is allocated with new and must be delete'd. //setData() will have been called, CheckParse() not. - //Never returns null - maybe the UnimplementedDescriptor. - static Descriptor *getDescriptor(CharArray d, DescriptorTagDomain domain); + //if returnUnimplemetedDescriptor==true: + // Never returns null - maybe the UnimplementedDescriptor. + //if returnUnimplemetedDescriptor==false: + // Never returns the UnimplementedDescriptor - maybe null + static Descriptor *getDescriptor(CharArray d, DescriptorTagDomain domain, bool returnUnimplemetedDescriptor); }; class Loop : public VariableLengthPart { @@ -266,6 +269,7 @@ public: template <class T> friend class StructureLoop; friend class DescriptorLoop; template <class T> friend class TypeLoop; + friend class ExtendedEventDescriptors; int i; }; protected: @@ -311,14 +315,46 @@ public: //returns null if no more descriptors available Descriptor *getNext(Iterator &it); //return the next descriptor with given tag, or 0 if not available. - //if the descriptor found is not implemented, - // an UnimplementedDescriptor will be returned if returnUnimplemetedDescriptor==true, - // 0 will be returned if returnUnimplemetedDescriptor==false + //if returnUnimplemetedDescriptor==true: + // an UnimplementedDescriptor may be returned if the next matching descriptor is unimplemented, + // 0 will be returned if and only if no matching descriptor is found. + //if returnUnimplemetedDescriptor==false: + // if 0 is returned, either no descriptor with the given tag was found, + // or descriptors were found, but the descriptor type is not implemented + //In either case, a return value of 0 indicates that no further calls to this method + //with the iterator shall be made. Descriptor *getNext(Iterator &it, DescriptorTag tag, bool returnUnimplemetedDescriptor=false); //return the next descriptor with one of the given tags, or 0 if not available. + //if returnUnimplemetedDescriptor==true: + // returns 0 if and only if no descriptor with one of the given tags was found. + // The UnimplementedDescriptor may be returned. + //if returnUnimplemetedDescriptor==false: + // if 0 is returned, either no descriptor with one of the given tags was found, + // or descriptors were found, but none of them are implemented. + // The UnimplementedDescriptor will never be returned. + //In either case, a return value of 0 indicates that no further calls to this method + //with the iterator shall be made. Descriptor *getNext(Iterator &it, DescriptorTag *tags, int arrayLength, bool returnUnimplemetedDescriptor=false); + //returns the number of descriptors in this loop + int getNumberOfDescriptors(); + //writes the tags of the descriptors in this loop in the array, + // which must at least have the size getNumberOfDescriptors(). + //The number of descriptors, i.e. getNumberOfDescriptors(), is returned. + // You can specify the array type (Descriptor tags are 8 Bit, + // you might e.g. choose a char, short, int or DescriptorTag array) + template <typename T> int getDescriptorTags(T *tags) + { + const unsigned char *p=data.getData(); + const unsigned char *end=p+getLength(); + int count=0; + while (p < end) { + tags[count++]=(T)Descriptor::getDescriptorTag(p); + p+=Descriptor::getLength(p); + } + return count; + } protected: - Descriptor *createDescriptor(int &i); + Descriptor *createDescriptor(int &i, bool returnUnimplemetedDescriptor); DescriptorTagDomain domain; }; @@ -385,7 +421,7 @@ class String : public VariableLengthPart { public: //A note to the length: getLength() returns the length of the raw data. //The text may be shorter. Its length can be obtained with one of the - //above functions and strlen. + //getText functions and strlen. //returns text. Data is allocated with new and must be delete'd by the user. char *getText(); @@ -394,10 +430,19 @@ public: //In most descriptors the string length is an 8-bit field, //so the maximum there is 256. //returns the given buffer for convenience. - char * getText(char *buffer); + //The emphasis marks 0x86 and 0x87 are still available. + char *getText(char *buffer); + //The same semantics as for getText(char*) apply. + //The short version of the text according to ETSI TR 101 211 (chapter 4.6) + //will be written into the shortVersion buffer (which should, therefore, have the same + //length as buffer). If no shortVersion is available, shortVersion will contain + //an empty string. + //The emphasis marks 0x86 and 0x87 are still available in buffer, but not in shortVersion. + char *getText(char *buffer, char *shortVersion); protected: virtual void Parse() {} void decodeText(char *buffer); + void decodeText(char *buffer, char *shortVersion); }; } //end of namespace @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: menu.c 1.292 2004/02/22 14:14:55 kls Exp kls $ + * $Id: menu.c 1.297 2004/03/14 13:24:02 kls Exp $ */ #include "menu.h" @@ -18,7 +18,6 @@ #include "cutter.h" #include "eitscan.h" #include "i18n.h" -#include "libsi/si.h" #include "menuitems.h" #include "plugin.h" #include "recording.h" @@ -1009,13 +1008,8 @@ public: cMenuTimers::cMenuTimers(void) :cOsdMenu(tr("Timers"), 2, CHNUMWIDTH, 10, 6, 6) { - int i = 0; - cTimer *timer; - - while ((timer = Timers.Get(i)) != NULL) { - Add(new cMenuTimerItem(timer)); - i++; - } + for (cTimer *timer = Timers.First(); timer; timer = Timers.Next(timer)) + Add(new cMenuTimerItem(timer)); if (Setup.SortTimers) Sort(); SetHelp(tr("Edit"), tr("New"), tr("Delete"), Setup.SortTimers ? tr("On/Off") : tr("Mark")); @@ -1216,7 +1210,7 @@ cMenuWhatsOnItem::cMenuWhatsOnItem(const cEvent *Event, cChannel *Channel) int TimerMatch; char t = Timers.GetMatch(Event, &TimerMatch) ? (TimerMatch == tmFull) ? 'T' : 't' : ' '; char v = event->Vps() && (event->Vps() - event->StartTime()) ? 'V' : ' '; - char r = event->RunningStatus() > SI::RunningStatusNotRunning ? '*' : ' '; + char r = event->IsRunning() ? '*' : ' '; asprintf(&buffer, "%d\t%.*s\t%.*s\t%c%c%c\t%s", channel->Number(), 6, channel->Name(), 5, event->GetTimeString(), t, v, r, event->Title()); SetText(buffer, false); } @@ -1334,7 +1328,7 @@ cMenuScheduleItem::cMenuScheduleItem(const cEvent *Event) int TimerMatch; char t = Timers.GetMatch(Event, &TimerMatch) ? (TimerMatch == tmFull) ? 'T' : 't' : ' '; char v = event->Vps() && (event->Vps() - event->StartTime()) ? 'V' : ' '; - char r = event->RunningStatus() > SI::RunningStatusNotRunning ? '*' : ' '; + char r = event->IsRunning() ? '*' : ' '; asprintf(&buffer, "%.*s\t%.*s\t%c%c%c\t%s", 5, event->GetDateString(), 5, event->GetTimeString(), t, v, r, event->Title()); SetText(buffer, false); } @@ -1386,11 +1380,9 @@ void cMenuSchedule::PrepareSchedule(cChannel *Channel) const cSchedule *Schedule = schedules->GetSchedule(Channel->GetChannelID()); if (Schedule) { const cEvent *PresentEvent = Schedule->GetPresentEvent(Channel->Number() == cDevice::CurrentChannel()); - int num = Schedule->NumEvents(); time_t now = time(NULL) - Setup.EPGLinger * 60; - for (int a = 0; a < num; a++) { - const cEvent *Event = Schedule->GetEventNumber(a); - if (Event->StartTime() + Event->Duration() > now || Event == PresentEvent) + for (const cEvent *Event = Schedule->Events()->First(); Event; Event = Schedule->Events()->Next(Event)) { + if (Event->EndTime() > now || Event == PresentEvent) Add(new cMenuScheduleItem(Event), Event == PresentEvent); } } @@ -1494,13 +1486,8 @@ cMenuCommands::cMenuCommands(const char *Title, cCommands *Commands, const char SetHasHotkeys(); commands = Commands; parameters = Parameters ? strdup(Parameters) : NULL; - int i = 0; - cCommand *command; - - while ((command = commands->Get(i)) != NULL) { - Add(new cOsdItem(hk(command->Title()))); - i++; - } + for (cCommand *command = commands->First(); command; command = commands->Next(command)) + Add(new cOsdItem(hk(command->Title()))); } cMenuCommands::~cMenuCommands() @@ -3196,6 +3183,7 @@ bool cRecordControls::Start(cTimer *Timer, bool Pause) if (device == cTransferControl::ReceiverDevice()) cControl::Shutdown(); // in case this device was used for Transfer Mode } + dsyslog("switching device %d to channel %d", device->DeviceNumber() + 1, channel->Number()); if (!device->SwitchChannel(channel, false)) { cThread::EmergencyExit(true); return false; @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: menu.h 1.60 2004/02/15 14:11:28 kls Exp kls $ + * $Id: menu.h 1.60 2004/02/15 14:11:28 kls Exp $ */ #ifndef __MENU_H diff --git a/menuitems.c b/menuitems.c index e3c99a5..49874f1 100644 --- a/menuitems.c +++ b/menuitems.c @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: menuitems.c 1.14 2004/01/25 15:40:55 kls Exp kls $ + * $Id: menuitems.c 1.15 2004/02/24 12:38:43 kls Exp $ */ #include "menuitems.h" diff --git a/menuitems.h b/menuitems.h index 72a2418..7091740 100644 --- a/menuitems.h +++ b/menuitems.h @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: menuitems.h 1.5 2003/01/12 15:06:23 kls Exp kls $ + * $Id: menuitems.h 1.6 2004/02/24 11:55:14 kls Exp $ */ #ifndef __MENUITEMS_H @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: osd.c 1.43 2003/06/04 16:13:00 kls Exp $ + * $Id: osd.c 1.45 2004/03/14 10:33:20 kls Exp $ */ #include "osd.h" @@ -429,30 +429,27 @@ void cOsdMenu::Display(void) Interface->Help(helpRed, helpGreen, helpYellow, helpBlue); int count = Count(); if (count > 0) { - for (int i = 0; i < count; i++) { - cOsdItem *item = Get(i); - if (item) - cStatus::MsgOsdItem(item->Text(), i); - } + int ni = 0; + for (cOsdItem *item = First(); item; item = Next(item)) + cStatus::MsgOsdItem(item->Text(), ni++); if (current < 0) current = 0; // just for safety - there HAS to be a current item! - int n = 0; - if (current - first >= MAXOSDITEMS) { + if (current - first >= MAXOSDITEMS || current < first) { first = current - MAXOSDITEMS / 2; if (first + MAXOSDITEMS > count) first = count - MAXOSDITEMS; if (first < 0) first = 0; } - for (int i = first; i < count; i++) { - cOsdItem *item = Get(i); - if (item) { - item->Display(i - first, i == current ? clrBlack : clrWhite, i == current ? clrCyan : clrBackground); - if (i == current) - cStatus::MsgOsdCurrentItem(item->Text()); - } + int i = first; + int n = 0; + for (cOsdItem *item = Get(first); item; item = Next(item)) { + item->Display(i - first, i == current ? clrBlack : clrWhite, i == current ? clrCyan : clrBackground); + if (i == current) + cStatus::MsgOsdCurrentItem(item->Text()); if (++n == MAXOSDITEMS) //TODO get this from Interface!!! break; + i++; } } if (!isempty(status)) @@ -562,12 +559,13 @@ void cOsdMenu::PageDown(void) { current += MAXOSDITEMS; first += MAXOSDITEMS; - if (current > Count() - 1) { - current = Count() - 1; - first = max(0, Count() - MAXOSDITEMS); + int count = Count(); + if (current > count - 1) { + current = count - 1; + first = max(0, count - MAXOSDITEMS); } if (SpecialItem(current)) { - current += (current < Count() - 1) ? 1 : -1; + current += (current < count - 1) ? 1 : -1; first = max(first, current - MAXOSDITEMS); } Display(); @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: pat.c 1.7 2004/01/25 15:12:53 kls Exp $ + * $Id: pat.c 1.8 2004/03/07 16:59:00 kls Exp $ */ #include "pat.h" @@ -250,19 +250,21 @@ void cPatFilter::Trigger(void) numPmtEntries = 0; } -bool cPatFilter::PmtVersionChanged(int PmtPid, int Version) +bool cPatFilter::PmtVersionChanged(int PmtPid, int Sid, int Version) { - Version <<= 16; + uint64_t v = Version; + v <<= 32; + uint64_t id = (PmtPid | (Sid << 16)) & 0x00000000FFFFFFFFLL; for (int i = 0; i < numPmtEntries; i++) { - if ((pmtVersion[i] & 0x0000FFFF) == PmtPid) { - bool Changed = (pmtVersion[i] & 0x00FF0000) != Version; + if ((pmtVersion[i] & 0x00000000FFFFFFFFLL) == id) { + bool Changed = (pmtVersion[i] & 0x000000FF00000000LL) != v; if (Changed) - pmtVersion[i] = PmtPid | Version; + pmtVersion[i] = id | v; return Changed; } } if (numPmtEntries < MAXPMTENTRIES) - pmtVersion[numPmtEntries++] = PmtPid | Version; + pmtVersion[numPmtEntries++] = id | v; return true; } @@ -301,7 +303,7 @@ void cPatFilter::Process(u_short Pid, u_char Tid, const u_char *Data, int Length SI::PMT pmt(Data, false); if (!pmt.CheckCRCAndParse()) return; - if (!PmtVersionChanged(pmtPid, pmt.getVersionNumber())) { + if (!PmtVersionChanged(pmtPid, pmt.getTableIdExtension(), pmt.getVersionNumber())) { lastPmtScan = 0; // this triggers the next scan return; } @@ -4,13 +4,14 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: pat.h 1.3 2004/01/03 13:47:54 kls Exp $ + * $Id: pat.h 1.4 2004/03/07 16:22:01 kls Exp $ */ #ifndef __PAT_H #define __PAT_H #include "filter.h" +#include <stdint.h> #define MAXPMTENTRIES 64 @@ -19,9 +20,9 @@ private: time_t lastPmtScan; int pmtIndex; int pmtPid; - int pmtVersion[MAXPMTENTRIES]; + uint64_t pmtVersion[MAXPMTENTRIES]; int numPmtEntries; - bool PmtVersionChanged(int PmtPid, int Version); + bool PmtVersionChanged(int PmtPid, int Sid, int Version); protected: virtual void Process(u_short Pid, u_char Tid, const u_char *Data, int Length); public: @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: recorder.c 1.8 2003/10/18 11:35:02 kls Exp $ + * $Id: recorder.c 1.9 2004/03/07 14:39:25 kls Exp $ */ #include <stdarg.h> @@ -102,7 +102,7 @@ void cRecorder::Receive(uchar *Data, int Length) { int p = ringBuffer->Put(Data, Length); if (p != Length && active) - esyslog("ERROR: ring buffer overflow (%d bytes dropped)", Length - p); + ringBuffer->ReportOverflow(Length - p); } void cRecorder::Action(void) diff --git a/ringbuffer.c b/ringbuffer.c index c92b75f..6f26748 100644 --- a/ringbuffer.c +++ b/ringbuffer.c @@ -7,7 +7,7 @@ * Parts of this file were inspired by the 'ringbuffy.c' from the * LinuxDVB driver (see linuxtv.org). * - * $Id: ringbuffer.c 1.18 2003/10/12 14:25:09 kls Exp $ + * $Id: ringbuffer.c 1.19 2004/03/07 13:46:51 kls Exp $ */ #include "ringbuffer.h" @@ -17,6 +17,8 @@ // --- cRingBuffer ----------------------------------------------------------- +#define OVERFLOWREPORTDELTA 5 // seconds between reports + cRingBuffer::cRingBuffer(int Size, bool Statistics) { size = Size; @@ -24,6 +26,8 @@ cRingBuffer::cRingBuffer(int Size, bool Statistics) maxFill = 0; lastPercent = 0; putTimeout = getTimeout = 0; + lastOverflowReport = 0; + overflowCount = overflowBytes = 0; } cRingBuffer::~cRingBuffer() @@ -68,6 +72,17 @@ void cRingBuffer::SetTimeouts(int PutTimeout, int GetTimeout) getTimeout = GetTimeout; } +void cRingBuffer::ReportOverflow(int Bytes) +{ + overflowCount++; + overflowBytes += Bytes; + if (time(NULL) - lastOverflowReport > OVERFLOWREPORTDELTA) { + esyslog("ERROR: %d ring buffer overflow%s (%d bytes dropped)", overflowCount, overflowCount > 1 ? "s" : "", overflowBytes); + overflowCount = overflowBytes = 0; + lastOverflowReport = time(NULL); + } +} + // --- cRingBufferLinear ----------------------------------------------------- cRingBufferLinear::cRingBufferLinear(int Size, int Margin, bool Statistics) diff --git a/ringbuffer.h b/ringbuffer.h index 0680df4..349096f 100644 --- a/ringbuffer.h +++ b/ringbuffer.h @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: ringbuffer.h 1.13 2003/10/12 13:57:56 kls Exp $ + * $Id: ringbuffer.h 1.14 2004/03/07 13:40:45 kls Exp $ */ #ifndef __RINGBUFFER_H @@ -21,6 +21,9 @@ private: int putTimeout; int getTimeout; int size; + time_t lastOverflowReport; + int overflowCount; + int overflowBytes; protected: int maxFill;//XXX int lastPercent; @@ -39,6 +42,7 @@ public: cRingBuffer(int Size, bool Statistics = false); virtual ~cRingBuffer(); void SetTimeouts(int PutTimeout, int GetTimeout); + void ReportOverflow(int Bytes); }; class cRingBufferLinear : public cRingBuffer { @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: sdt.c 1.7 2004/01/17 17:27:49 kls Exp $ + * $Id: sdt.c 1.8 2004/03/07 10:46:08 kls Exp $ */ #include "sdt.h" @@ -57,34 +57,17 @@ void cSdtFilter::Process(u_short Pid, u_char Tid, const u_char *Data, int Length //XXX TODO case 0x04: // NVOD reference service //XXX TODO case 0x05: // NVOD time-shifted service { - char buffer[1024]; - char *p = sd->serviceName.getText(buffer); char NameBuf[1024]; char ShortNameBuf[1024]; - char *pn = NameBuf; - char *ps = ShortNameBuf; - int IsShortName = 0; - while (*p) { - if ((uchar)*p == 0x86) - IsShortName++; - else if ((uchar)*p == 0x87) - IsShortName--; - else { - *pn++ = *p; - if (IsShortName) - *ps++ = *p; - } - p++; - } - *pn = *ps = 0; - pn = NameBuf; + sd->serviceName.getText(NameBuf, ShortNameBuf); + char *pn = compactspace(NameBuf); + char *ps = compactspace(ShortNameBuf); if (*NameBuf && *ShortNameBuf && strcmp(NameBuf, ShortNameBuf) != 0) { + ps = ShortNameBuf + strlen(ShortNameBuf); *ps++ = ','; strcpy(ps, NameBuf); pn = ShortNameBuf; } - pn = compactspace(pn); - ps = compactspace(ps); if (channel) { channel->SetId(sdt.getOriginalNetworkId(), sdt.getTransportStreamId(), SiSdtService.getServiceId()); if (Setup.UpdateChannels >= 1) @@ -10,7 +10,7 @@ * and interact with the Video Disk Recorder - or write a full featured * graphical interface that sits on top of an SVDRP connection. * - * $Id: svdrp.c 1.60 2004/02/22 15:31:23 kls Exp kls $ + * $Id: svdrp.c 1.61 2004/02/24 12:24:43 kls Exp $ */ #include "svdrp.h" @@ -4,14 +4,13 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: timers.c 1.9 2004/02/13 15:37:49 kls Exp kls $ + * $Id: timers.c 1.12 2004/03/14 13:27:57 kls Exp $ */ #include "timers.h" #include <ctype.h> #include "channels.h" #include "i18n.h" -#include "libsi/si.h" // IMPORTANT NOTE: in the 'sscanf()' calls there is a blank after the '%d' // format characters in order to allow any number of blanks after a numeric @@ -333,8 +332,8 @@ bool cTimer::Matches(time_t t, bool Directly) if (HasFlags(tfActive)) { if (HasFlags(tfVps) && !Directly && event && event->Vps()) { startTime = event->StartTime(); - stopTime = startTime + event->Duration(); - return event->RunningStatus() > SI::RunningStatusNotRunning; + stopTime = event->EndTime(); + return event->IsRunning(true); } return startTime <= t && t < stopTime; // must stop *before* stopTime to allow adjacent timers } @@ -350,9 +349,14 @@ int cTimer::Matches(const cEvent *Event) bool m1 = Matches(t1, true); bool m2 = UseVps ? m1 : Matches(t2, true); startTime = stopTime = 0; - if (m1 && m2) + if (m1 && m2) { + if (UseVps && Event->IsRunning(true)) + return tmFull; + if (time(NULL) > Event->EndTime()) + return tmNone; return tmFull; - if (m1 || m2) + } + if ((m1 || m2) && time(NULL) <= Event->EndTime()) return tmPartial; } return tmNone; @@ -381,6 +385,8 @@ void cTimer::SetEvent(const cEvent *Event) sprintf(vpsbuf, "(VPS: %s) ", Event->GetVpsString()); isyslog("timer %d (%d %04d-%04d '%s') set to event %s %s-%s %s'%s'", Index() + 1, Channel()->Number(), start, stop, file, Event->GetDateString(), Event->GetTimeString(), Event->GetEndTimeString(), vpsbuf, Event->Title()); } + else + isyslog("timer %d (%d %04d-%04d '%s') set to no event", Index() + 1, Channel()->Number(), start, stop, file); event = Event; } } @@ -500,7 +506,7 @@ cTimer *cTimers::GetNextActiveTimer(void) void cTimers::SetEvents(void) { - cSchedulesLock SchedulesLock; + cSchedulesLock SchedulesLock(false, 100); const cSchedules *Schedules = cSchedules::Schedules(SchedulesLock); if (Schedules) { for (cTimer *ti = First(); ti; ti = Next(ti)) { @@ -508,19 +514,17 @@ void cTimers::SetEvents(void) const cEvent *Event = NULL; if (Schedule) { //XXX what if the Schedule doesn't have any VPS??? - const cEvent *e; int Match = tmNone; - int i = 0; - while ((e = Schedule->GetEventNumber(i++)) != NULL) { - int m = ti->Matches(e); - if (m > Match) { - Match = m; - Event = e; - if (Match == tmFull) - break; - //XXX what if there's another event with the same VPS time??? - } - } + for (const cEvent *e = Schedule->Events()->First(); e; e = Schedule->Events()->Next(e)) { + int m = ti->Matches(e); + if (m > Match) { + Match = m; + Event = e; + if (Match == tmFull) + break; + //XXX what if there's another event with the same VPS time??? + } + } } ti->SetEvent(Event); } @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: timers.h 1.6 2003/12/13 13:04:21 kls Exp kls $ + * $Id: timers.h 1.7 2004/02/29 14:18:17 kls Exp $ */ #ifndef __TIMERS_H @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: transfer.c 1.15 2003/10/18 11:36:03 kls Exp $ + * $Id: transfer.c 1.16 2004/03/07 14:40:15 kls Exp $ */ #include "transfer.h" @@ -55,7 +55,7 @@ void cTransfer::Receive(uchar *Data, int Length) int i = 0; while (active && Length > 0) { if (i++ > 10) { - esyslog("ERROR: ring buffer overflow (%d bytes dropped)", Length); + ringBuffer->ReportOverflow(Length); break; } int p = ringBuffer->Put(Data, Length); @@ -8,7 +8,7 @@ .\" License as specified in the file COPYING that comes with the .\" vdr distribution. .\" -.\" $Id: vdr.5 1.25 2004/02/22 13:18:48 kls Exp kls $ +.\" $Id: vdr.5 1.26 2004/02/24 12:36:35 kls Exp $ .\" .TH vdr 5 "1 Jun 2003" "1.2.0" "Video Disk Recorder Files" .SH NAME @@ -22,7 +22,7 @@ * * The project's page is at http://www.cadsoft.de/vdr * - * $Id: vdr.c 1.177 2004/02/15 14:29:30 kls Exp kls $ + * $Id: vdr.c 1.180 2004/03/14 14:25:02 kls Exp $ */ #include <getopt.h> @@ -549,10 +549,13 @@ int main(int argc, char *argv[]) PreviousChannel[PreviousChannelIndex ^= 1] = LastChannel; // Timers and Recordings: if (!Timers.BeingEdited()) { - static time_t LastSetEvents = 0;//XXX trigger by actual EPG data modification??? - if (!Menu && time(NULL) - LastSetEvents > 5) { - Timers.SetEvents(); - LastSetEvents = time(NULL); + // Assign events to timers: + if (time(NULL) - LastActivity > 10) { + static time_t LastSetEvents = 0;//XXX trigger by actual EPG data modification??? + if (time(NULL) - LastSetEvents > 5) { + Timers.SetEvents(); + LastSetEvents = time(NULL); + } } time_t Now = time(NULL); // must do all following calls with the exact same time! // Process ongoing recordings: @@ -571,7 +574,6 @@ int main(int argc, char *argv[]) if (Timer->HasFlags(tfActive | tfVps) && !Timer->Recording() && !Timer->Pending() && Timer->Matches(Now + Setup.VpsMargin, true)) { if (!Timer->InVpsMargin()) { Timer->SetInVpsMargin(true); - TimerInVpsMargin = true; //XXX if not primary device has TP??? LastTimerChannel = Timer->Channel()->Number(); cRecordControls::Start(Timer); // will only switch the device @@ -579,6 +581,8 @@ int main(int argc, char *argv[]) } else Timer->SetInVpsMargin(false); + if (Timer->InVpsMargin()) + TimerInVpsMargin = true; } } // CAM control: |