diff options
-rw-r--r-- | CONTRIBUTORS | 37 | ||||
-rw-r--r-- | HISTORY | 38 | ||||
-rw-r--r-- | INSTALL | 16 | ||||
-rw-r--r-- | Make.config.template | 7 | ||||
-rw-r--r-- | Makefile | 10 | ||||
-rw-r--r-- | PLUGINS/src/sky/channels.conf.sky | 8 | ||||
-rw-r--r-- | channels.c | 53 | ||||
-rw-r--r-- | channels.conf | 43 | ||||
-rw-r--r-- | channels.h | 3 | ||||
-rw-r--r-- | config.c | 3 | ||||
-rw-r--r-- | config.h | 6 | ||||
-rw-r--r-- | device.h | 5 | ||||
-rw-r--r-- | dvbplayer.c | 29 | ||||
-rw-r--r-- | dvbspu.c | 4 | ||||
-rw-r--r-- | eit.c | 18 | ||||
-rw-r--r-- | eitscan.c | 9 | ||||
-rw-r--r-- | epg.c | 4 | ||||
-rw-r--r-- | i18n.c | 30 | ||||
-rw-r--r-- | lirc.c | 4 | ||||
-rw-r--r-- | lirc.h | 4 | ||||
-rw-r--r-- | pat.c | 8 | ||||
-rw-r--r-- | rcu.c | 4 | ||||
-rw-r--r-- | rcu.h | 4 | ||||
-rw-r--r-- | recording.c | 6 | ||||
-rw-r--r-- | remux.c | 241 | ||||
-rw-r--r-- | remux.h | 8 | ||||
-rw-r--r-- | svdrp.c | 177 | ||||
-rw-r--r-- | timers.c | 4 | ||||
-rw-r--r-- | tools.c | 8 | ||||
-rw-r--r-- | tools.h | 4 | ||||
-rw-r--r-- | vdr.1 | 15 | ||||
-rw-r--r-- | vdr.c | 47 | ||||
-rw-r--r-- | videodir.c | 4 |
33 files changed, 589 insertions, 272 deletions
diff --git a/CONTRIBUTORS b/CONTRIBUTORS index cc43b02..770a080 100644 --- a/CONTRIBUTORS +++ b/CONTRIBUTORS @@ -199,6 +199,7 @@ Stefan Huelswitt <huels@iname.com> for fixing a memory leak in cDvbPlayer for pointing out that recordings with empty episode names were not listed correctly in the LSTR command + for fixing a memory leak in the SVDRP command LSTE Ulrich Röder <roeder@efr-net.de> for pointing out that there are channels that have a symbol rate higher than 27500 @@ -469,6 +470,7 @@ Oliver Lorei <oliverlorei@cityweb.de> Andreas Böttger <fboettger@t-online.de> for reporting a bug in skipping forward in time shift mode near the end of the recording + for fixing setting system time to avoid time jumps in case of faulty data Onno Kreuzinger <ok@solutas.net> for reporting leftover references to the file FORMATS in MANUAL and svdrp.c @@ -731,6 +733,7 @@ Marcel Wiesweg <marcel.wiesweg@gmx.de> for adding a few missing initializations for adding play mode pmVideoOnly for fixing a possible crash with inconsistent SI data + for pointing out a problem with the cChannel copy constructor Torsten Herz <torsten.herz@web.de> for fixing a possible deadlock when using the "Blue" button in the "Schedules" menu @@ -817,6 +820,8 @@ Andreas Brachold <vdr04@deltab.de> for generating file dependencies for suggesting that the 'plugins-clean' target of the Makefile should only delete the actual plugin library files from this version of VDR + for making files and directories created with rights according to the shell's + umask settings Manuel Hartl <icecep@gmx.net> for suggesting to extend the logging info when starting/stopping timers @@ -961,6 +966,9 @@ Reinhard Nissl <rnissl@gmx.de> for implementing cVideoRepacker in remux.c to make sure every PES packet contains only data from one frame for fixing the call to Channels.Unlock() in cEITScanner::Process() + for making cDvbPlayer::Goto() append a Sequence End Code to get the image shown + immediately with softdevices + for fixing cDvbSpuBitmap::putPixel() Richard Robson <richard_robson@beeb.net> for reporting freezing replay if a timer starts while in Transfer Mode from the @@ -1243,6 +1251,8 @@ Udo Richter <udo_richter@gmx.de> for reporting a problem in handling page up/down in menu lists in case there are several non selectable items in a row for fixing handling 'page down' after it was broken in version 1.3.26 + for suggesting a fix for an out-of-bounds memory access with audio language ids + for reporting a problem with cRemux in a single thread Sven Kreiensen <svenk@kammer.uni-hannover.de> for his help in keeping 'channels.conf.terr' up to date @@ -1269,12 +1279,14 @@ Joachim Wilke <vdr@joachim-wilke.de> for reporting missing calls to cStatus::MsgOsdClear() in cSkins::Message() Sascha Klek <sklek@gmx.de> - for reporting a problem with the '0' key in the "Day" item of the "Timers" menu + for reporting a problem with the '0' key in the "Day" item of the "Timers" menu Andreas Brugger <brougs78@gmx.net> - for reporting a possible crash when pausing live video and the recording was - unable to start, maybe because there was no lock on the device - for reporting the missing Euro sign in iso8859-1 + for reporting a possible crash when pausing live video and the recording was + unable to start, maybe because there was no lock on the device + for reporting the missing Euro sign in iso8859-1 + for reporting a problem with making changes to timers through SVDRP while they + are being edited via the menu Dino Ravnic <dino.ravnic@fer.hr> for fixing some characters in the iso8859-2 font file @@ -1285,10 +1297,13 @@ Olaf Titz <olaf@bigred.inka.de> for fixing some typos in the Makefile's 'font' target for reporting a problem and some advice in fixing a possible freeze in pause mode in case a device's PlayPesPacket() function permanently returns 0 + for reporting excess memory consumption due to duplicate components in EPG events Darren Salt <linux@youmustbejoking.demon.co.uk> for pointing out that the '-' and 'ö' characters need to be escaped in the man pages + for a patch that was used to add the command line options '--lirc', '--rcu' and + '--no-kbd' Sean Carlos <seanc@libero.it> for translating OSD texts to the Italian language @@ -1388,3 +1403,17 @@ Georg Acher <acher@baycom.de> Henrik Niehaus <henrik.niehaus@gmx.de> for reporting a problem with timers with a day given as MTWTF--@6, i.e. a repeating timer with first day not as full date, but just day of month + +Martin Wache <M.Wache@gmx.net> + for adding a sleep in cDvbPlayer::Action() in case there is no data to send to the + device, which avoids a busy loop on very fast machines + +Matthias Lenk <matthias.lenk@amd.com> + for reporting an out-of-bounds memory access with audio language ids + +Frank Krömmelbein <kroemmelbein@gmx.de> + for adding missing storing of the MenuScrollPage parameter + +Bernhard Stegmaier <bernhard.stegmaier@in.tum.de> + for reporting a problem in cEITScanner::Process() with forced EPG scans if EPG + scan timeout is set to 0 @@ -3633,3 +3633,41 @@ Video Disk Recorder Revision History - When drawing a bitmap to the OSD, the existing palette of the target can now be replaced with the new one instead of adding the new entries (thanks to Andreas Regel). + +2005-08-07: Version 1.3.28 + +- Added a sleep in cDvbPlayer::Action() in case there is no data to send to the + device, which avoids a busy loop on very fast machines (thanks to Martin Wache). +- Modified the description of cDevice::Poll() to avoid misunderstandings. +- Updated Croatian language texts (thanks to Drazen Dupor). +- cDvbPlayer::Goto() now appends a Sequence End Code to get the image shown + immediately with softdevices (thanks to Reinhard Nissl). +- Reactivated cVideoRepacker in remux.c after some fixes (thanks to Reinhard Nissl). +- Removed the fix for handling VPS timers, so that they only record if the event + they are assigned to actually has the given VPS time. This has caused repeating + VPS timers to stop recording prematurely. +- Avoiding duplicate components in EPG events when reading epg.data or in the + PUTE SVDRP command (thanks to Olaf Titz for reporting this one). +- Added the command line options '--lirc', '--rcu' and '--no-kbd' to allow setting + the remote control at runtime (based on a patch by Darren Salt). +- Now checking whether timers or channels are currently being edited via the menu + before making changes through SVDRP (thanks to Andreas Brugger for reporting a + problem with this). +- Files and directories are now created with rights according to the shell's + umask settings (thanks to Andreas Brachold). +- Fixed the cChannel copy constructor (thanks to Marcel Wiesweg for pointing out + a problem with it). +- Fixed an out-of-bounds memory access with audio language ids (thanks to + Matthias Lenk for reporting, and Udo Richter for suggesting a fix). +- Updated the Finnish OSD texts (thanks to Rolf Ahrenberg). +- Added missing storing of the MenuScrollPage parameter (thanks to Frank Krömmelbein). +- Added cRemux::SetTimeouts() for better use of cRemux in a single thread (thanks + to Udo Richter for reporting a problem with this). +- Modified cEITScanner::Process() so that it uses the primary device if it is + replaying and is the only device that provides the given transponder, and that + a forced EPG scan works even if EPG scan timeout is set to 0 (thanks to + Bernhard Stegmaier for reporting a problem with this). +- Fixed cDvbSpuBitmap::putPixel() (thanks to Reinhard Nissl). +- Fixed setting system time to avoid time jumps in case of faulty data (thanks + to Andreas Böttger). +- Fixed a memory leak in the SVDRP command LSTE (thanks to Stefan Huelswitt). @@ -45,17 +45,23 @@ installed. IMPORTANT: See "Configuration files" below for information on how ========= to set up the configuration files at the proper location! -By default the 'vdr' program can be controlled via the PC keyboard. If you have -an infrared remote control unit you can define the REMOTE macro to one of the -following values in the 'make' call to activate the respective control mode: +By default the 'vdr' program can be controlled via the PC keyboard. +If you want to disable control via the keyboard, you can add NO_KBD=1 +to the 'make' call, or use the '--no-kbd' option at runtime. + +If you have an infrared remote control unit you can define the REMOTE macro +to one of the following values in the 'make' call to make the respective control +the default: REMOTE=RCU control via the "Remote Control Unit" receiver (see http://www.cadsoft.de/vdr/remote.htm) REMOTE=LIRC control via the "Linux Infrared Remote Control" (see http://www.lirc.org) -If you want to disable control via the PC keyboard, you can add NO_KBD=1 -to the 'make' call. +Alternatively you can use the '--rcu' or '--lirc' options at runtime. +These options accept an optional path to the remote control device, +which's defaults can be set via the RCU_DEVICE and LIRC_DEVICE macros, +respectively. If your video directory will be on a VFAT partition, add the compile time switch diff --git a/Make.config.template b/Make.config.template index 3c429e7..149ce98 100644 --- a/Make.config.template +++ b/Make.config.template @@ -6,7 +6,7 @@ # See the main source file 'vdr.c' for copyright information and # how to reach the author. # -# $Id: Make.config.template 1.4 2005/05/14 10:32:33 kls Exp $ +# $Id: Make.config.template 1.5 2005/07/31 11:35:28 kls Exp $ ### The C compiler and options: @@ -25,3 +25,8 @@ BINDIR = /usr/local/bin PLUGINDIR= ./PLUGINS PLUGINLIBDIR= $(PLUGINDIR)/lib VIDEODIR = /video + +### The remote control: + +LIRC_DEVICE = /dev/lircd +RCU_DEVICE = /dev/ttyS1 @@ -4,7 +4,7 @@ # See the main source file 'vdr.c' for copyright information and # how to reach the author. # -# $Id: Makefile 1.75 2005/05/14 10:32:13 kls Exp $ +# $Id: Makefile 1.76 2005/07/31 11:20:20 kls Exp $ .DELETE_ON_ERROR: @@ -65,8 +65,14 @@ SMLFONT_ISO8859_15 = -adobe-helvetica-medium-r-normal--18-*-100-100-p-*-iso8859- ifndef NO_KBD DEFINES += -DREMOTE_KBD endif - +ifdef REMOTE DEFINES += -DREMOTE_$(REMOTE) +endif + +LIRC_DEVICE ?= /dev/lircd +RCU_DEVICE ?= /dev/ttyS1 + +DEFINES += -DLIRC_DEVICE=\"$(LIRC_DEVICE)\" -DRCU_DEVICE=\"$(RCU_DEVICE)\" DEFINES += -D_GNU_SOURCE diff --git a/PLUGINS/src/sky/channels.conf.sky b/PLUGINS/src/sky/channels.conf.sky index d40837f..52d1a87 100644 --- a/PLUGINS/src/sky/channels.conf.sky +++ b/PLUGINS/src/sky/channels.conf.sky @@ -18,17 +18,17 @@ # S28.2E-2-2027-4705:106:sky_one S28.2E-2-2027-5104:107:sky_one_mix -S28.2E-2-2054-10240:118:itv2 +S28.2E-2-2044-10070:118:itv2 S28.2E-2-2023-4905:130:scifi S28.2E-2-2025-5904:127:paramount S28.2E-2-2009-6201:551:discovery -S28.2E-2-2020-4809:310:sky_cinema +S28.2E-2-2030-4809:310:sky_cinema S28.2E-2-2007-4303:301:sky_movies1 S28.2E-2-2007-4302:302:sky_movies2 S28.2E-2-2007-4403:303:sky_movies3 S28.2E-2-2011-4402:304:sky_movies4 S28.2E-2-2011-4503:305:sky_movies5 S28.2E-2-2011-4502:306:sky_movies6 -S28.2E-2-2020-4603:307:sky_movies7 +S28.2E-2-2030-4603:307:sky_movies7 S28.2E-2-2007-5502:308:sky_movies8 -S28.2E-2-2020-4602:309:x +S28.2E-2-2030-4602:309:sky_movies9 @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: channels.c 1.42 2005/05/29 10:32:38 kls Exp $ + * $Id: channels.c 1.44 2005/08/06 12:22:41 kls Exp $ */ #include "channels.h" @@ -179,27 +179,13 @@ cChannel::cChannel(void) cChannel::cChannel(const cChannel &Channel) { - name = strdup(""); - shortName = strdup(""); - provider = strdup(""); - portalName = strdup(""); - *this = Channel; - vpid = 0; - ppid = 0; - apids[0] = 0; - dpids[0] = 0; - spids[0] = 0; - tpid = 0; - caids[0] = 0; - nid = 0; - tid = 0; - sid = 0; - rid = 0; - number = 0; - groupSep = false; - modification = CHANNELMOD_NONE; + name = NULL; + shortName = NULL; + provider = NULL; + portalName = NULL; linkChannels = NULL; refChannel = NULL; + *this = Channel; } cChannel::~cChannel() @@ -265,6 +251,24 @@ int cChannel::Modification(int Mask) return Result; } +void cChannel::CopyTransponderData(const cChannel *Channel) +{ + if (Channel) { + frequency = Channel->frequency; + source = Channel->source; + srate = Channel->srate; + polarization = Channel->polarization; + inversion = Channel->inversion; + bandwidth = Channel->bandwidth; + coderateH = Channel->coderateH; + coderateL = Channel->coderateL; + modulation = Channel->modulation; + transmission = Channel->transmission; + guard = Channel->guard; + hierarchy = Channel->hierarchy; + } +} + bool cChannel::SetSatTransponderData(int Source, int Frequency, char Polarization, int Srate, int CoderateH) { // Workarounds for broadcaster stupidity: @@ -442,14 +446,16 @@ void cChannel::SetPids(int Vpid, int Ppid, int *Apids, char ALangs[][4], int *Dp dsyslog("changing pids of channel %d from %d+%d:%s:%d to %d+%d:%s:%d", Number(), vpid, ppid, OldApidsBuf, tpid, Vpid, Ppid, NewApidsBuf, Tpid); vpid = Vpid; ppid = Ppid; - for (int i = 0; i <= MAXAPIDS; i++) { // <= to copy the terminating 0 + for (int i = 0; i < MAXAPIDS; i++) { apids[i] = Apids[i]; strn0cpy(alangs[i], ALangs[i], 4); } - for (int i = 0; i <= MAXDPIDS; i++) { // <= to copy the terminating 0 + apids[MAXAPIDS] = 0; + for (int i = 0; i < MAXDPIDS; i++) { dpids[i] = Dpids[i]; strn0cpy(dlangs[i], DLangs[i], 4); } + dpids[MAXDPIDS] = 0; tpid = Tpid; modification |= mod; Channels.SetModified(); @@ -977,7 +983,8 @@ cChannel *cChannels::NewChannel(const cChannel *Transponder, const char *Name, c { if (Transponder) { dsyslog("creating new channel '%s,%s;%s' on %s transponder %d with id %d-%d-%d-%d", Name, ShortName, Provider, *cSource::ToString(Transponder->Source()), Transponder->Transponder(), Nid, Tid, Sid, Rid); - cChannel *NewChannel = new cChannel(*Transponder); + cChannel *NewChannel = new cChannel; + NewChannel->CopyTransponderData(Transponder); NewChannel->SetId(Nid, Tid, Sid, Rid); NewChannel->SetName(Name, ShortName, Provider); Add(NewChannel); diff --git a/channels.conf b/channels.conf index 7243e9c..c48bd94 100644 --- a/channels.conf +++ b/channels.conf @@ -6,10 +6,10 @@ Das Erste;ARD:11836:hC34:S19.2E:27500:101:102=deu:104:0:28106:1:1101:0 Bayerisches FS;ARD:11836:hC34:S19.2E:27500:201:202=deu:204:0:28107:1:1101:0 hr-fernsehen;ARD:11836:hC34:S19.2E:27500:301:302=deu:304:0:28108:1:1101:0 NDR FS MV;ARD:12109:hC34:S19.2E:27500:2401:2402=deu:2404:0:28224:1:1073:0 -SR Fernsehen Südwest;ARD:11836:hC34:S19.2E:27500:501:502=deu:504:0:28110:1:1101:0 +SR SÜDWEST Ferns.;ARD:11836:hC34:S19.2E:27500:501:502=deu:504:0:28110:1:1101:0 WDR Köln;ARD:11836:hC34:S19.2E:27500:601:602=deu:604:0:28111:1:1101:0 -BR-alpha;ARD:11836:hC34:S19.2E:27500:701:702=deu:704:0:28112:1:1101:0 -SÜDWEST BW;ARD:11836:hC34:S19.2E:27500:801:802=deu:804:0:28113:1:1101:0 +BR-alpha;ARD:11836:hC34:S19.2E:27500:701:702=deu;703:704:0:28112:1:1101:0 +SÜDWEST Ferns. BW;ARD:11836:hC34:S19.2E:27500:801:802=deu:804:0:28113:1:1101:0 Phoenix;ARD:11836:hC34:S19.2E:27500:901:902=deu:904:0:28114:1:1101:0 ZDF;ZDFvision:11953:hC34:S19.2E:27500:110:120=deu,121=2ch;125=dd:130:0:28006:1:1079:0 3sat;ZDFvision:11953:hC34:S19.2E:27500:210:220=deu,221=2ch:230:0:28007:1:1079:0 @@ -23,14 +23,14 @@ Super RTL,S RTL;RTL World:12187:hC34:S19.2E:27500:165:120=deu:65:0:12040:1:1089: VOX;RTL World:12187:hC34:S19.2E:27500:167:136=deu:71:0:12060:1:1089:0 KABEL1;ProSiebenSat.1:12480:vC34:S19.2E:27500:511:512=deu:33:0:899:133:33:0 NEUN LIVE Television,NEUN LIVE;BetaDigital:12480:vC34:S19.2E:27500:767:768=deu:35:0:897:133:33:0 -DSF;BetaDigital:12480:vC34:S19.2E:27500:1023:1024=deu:0:0:900:133:33:0 +DSF;BetaDigital:12480:vC34:S19.2E:27500:1023:1024=deu:39:0:900:133:33:0 HSE24,HSE24;BetaDigital:12480:vC34:S19.2E:27500:1279:1280=deu:37:0:40:133:33:0 Bloomberg TV Germany;Bloomberg:12551:vC56:S19.2E:22000:162:99=deu:0:0:12160:1:1108:0 -EURONEWS;CSAT: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 +EURONEWS;CSAT:11817:vC34:S19.2E:27500:163:92=fra,91=rus,93=eng,94=ita,95=esl,98=por,99=deu:0:0:8004:1:1070:0 rbb Brandenburg;ARD:12109:hC34:S19.2E:27500:601:602=deu:604:0:28205:1:1073:0 Sky News;BSkyB:11597:vC56:S19.2E:22000:305+131:306=eng:0:0:28707:1:1026:0 -Veronica/JETIX;CANAL+:12574:hC56:S19.2E:22000:518+8190:92=dut:38:622,100:5020:53:1109:0 -BVN;CANAL+:12574:hC56:S19.2E:22000:515+8190:96=dut:36:0:5025:53:1109:0 +Veronica/JETIX;CANALDIGITAAL:12574:hC56:S19.2E:22000:518+8190:92=dut:38:622,100:5020:53:1109:0 +BVN;CANALDIGITAAL:12574:hC56:S19.2E:22000:515+8190:96=dut:36:0:5025:53:1109:0 n-tv;RTL World:12187:hC34:S19.2E:27500:169:73=deu:80:0:12090:1:1089:0 Al Jazeera;CANALSATELLITE:11567:vC56:S19.2E:22000:55:56=ara:0:0:9021:1:1024:0 TW1;ORF:12662:hC56:S19.2E:22000:1010:1011=deu:1013:0:13101:1:1115:0 @@ -44,13 +44,13 @@ MDR FERNSEHEN;ARD:12109:hC34:S19.2E:27500:401:402=deu:404:0:28204:1:1073:0 rbb Berlin;ARD:12109:hC34:S19.2E:27500:601:602=deu:604:0:28206:1:1073:0 :Premiere World PREMIERE START,START;PREMIERE:11797:hC34:S19.2E:27500:255:256=deu:32:1702,1801,1722:8:133:2:0 -PREMIERE 1,PREM 1;PREMIERE:11797:hC34:S19.2E:27500:511:512=deu,513=deu;515=deu:32:1722,1801,1702:10:133:2:0 -PREMIERE 2,PREM 2;PREMIERE:11797:hC34:S19.2E:27500:1791:1792=deu,1793=deu;1795=deu:32:1722,1801,1702:11:133:2:0 +PREMIERE 1,PREM 1;PREMIERE:11797:hC34:S19.2E:27500:511:512=deu;515=deu:32:1722,1702,1801:10:133:2:0 +PREMIERE 2,PREM 2;PREMIERE:11797:hC34:S19.2E:27500:1791:1792=deu;1795=deu:32:1801,1722,1702:11:133:2:0 PREMIERE 3,PREM 3;PREMIERE:11797:hC34:S19.2E:27500:2303:2304=deu,2305=deu:32:1722,1801,1702:43:133:2:0 PREMIERE 4,PREM 4;PREMIERE:11797:hC34:S19.2E:27500:767:768=deu,769=deu:32:1801,1722,1702:9:133:2:0 -PREMIERE 5,PREM 5;PREMIERE:11797:hC34:S19.2E:27500:1279:1280=deu,1281=deu:32:1801,1722,1702:29:133:2:0 -PREMIERE 6,PREM 6;PREMIERE:11797:hC34:S19.2E:27500:1535:1536=deu:32:1702,1722,1801:41:133:2:0 -PREMIERE 7,PREM 7;PREMIERE:11797:hC34:S19.2E:27500:1023:1024=deu:32:1722,1702,1801:20:133:2:0 +PREMIERE 5,PREM 5;PREMIERE:11797:hC34:S19.2E:27500:1279:1280=deu,1281=deu:32:1722,1801,1702:29:133:2:0 +PREMIERE 6,PREM 6;PREMIERE:11797:hC34:S19.2E:27500:1535:1536=deu:32:1702,1801,1722:41:133:2:0 +PREMIERE 7,PREM 7;PREMIERE:11797:hC34:S19.2E:27500:1023:1024=deu:32:1801,1722,1702:20:133:2:0 DISNEY CHANNEL,DISNEY;PREMIERE:11758:hC34:S19.2E:27500:2559:2560=deu:32:1722,1801,1702:34:133:17:0 :Premiere Direkt PREMIERE DIREKT,DIREKT;PREMIERE:12031:hC34:S19.2E:27500:2815:2816=deu,2817=deu;2819=deu:0:0:18:133:4:0 @@ -59,12 +59,12 @@ BEATE-UHSE.TV,B-UHSE;PREMIERE:11758:hC34:S19.2E:27500:1791:1792=deu:32:1801,1722 DIREKT EROTIK,EROTIK;PREMIERE:12031:hC34:S19.2E:27500:1279:0:0:1722,1801,1702:513:133:4:0 :Sportsworld PREMIERE SPORT PORTAL,SPORT PORTAL;PREMIERE:11719:hC34:S19.2E:27500:255:256=deu,257=deu:32:1702,1801,1722:17:133:3:0 -.,.;PREMIERE:12031:hC34:S19.2E:27500:3839:3840=deu:32:1722,1702,1801:27:133:4:0 +PREMIERE WIN,WIN;PREMIERE:12031:hC34:S19.2E:27500:3839:3840=deu:32:1722,1801,1702:27:133:4:0 :Beta Digital N24;ProSiebenSat.1:12480:vC34:S19.2E:27500:2047:2048=deu:36:0:47:133:33:0 LibertyTV FR;LibertyTV.com:12610:vC56:S19.2E:22000:941:943=deu:0:0:12199:1:1112:0 :- -ProSieben Austria;ProSiebenSat.1:12051:vC34:S19.2E:27500:161:84=deu:36:0:20002:1:1082:0 +ProSieben Austria;ProSiebenSat.1:12051:vC34:S19.2E:27500:161:84=deu;85=deu:36:0:20002:1:1082:0 Kabel 1 Schweiz;ProSiebenSat.1:12051:vC34:S19.2E:27500:162:163=deu:165:0:20003:1:1082:0 Kabel 1 Austria;ProSiebenSat.1:12051:vC34:S19.2E:27500:166:167=deu:169:0:20004:1:1082:0 ProSieben Schweiz;ProSiebenSat.1:12051:vC34:S19.2E:27500:289:290=deu:33:0:20001:1:1082:0 @@ -79,7 +79,7 @@ ASTRA-Mosaic 4;SES ASTRA:12551:vC56:S19.2E:22000:185:170=fra:0:0:3985:1:1108:0 ASTRA-Mosaic 5;SES ASTRA:12551:vC56:S19.2E:22000:163:164:0:0:3984:1:1108:0 Chamber TV;Chambre des Députées:12551:vC56:S19.2E:22000:55:56=ltz:0:0:12180:1:1108:0 RTL TELE Letzebuerg:12551:vC56:S19.2E:22000:168:144=eng,146=fra,151=ltz:74:0:3994:1:1108:0 -Yorin;CANAL+:12574:hC56:S19.2E:22000:512+8190:84=dut:33:622,100:5010:53:1109:0 +Yorin;CANALDIGITAAL:12574:hC56:S19.2E:22000:512+8190:84=dut:33:622,100:5010:53:1109:0 MTV2 Pop Channel;MTV Networks:12226:hC34:S19.2E:27500:513+8190:661=deu:577:0:28640:1:1091:0 MTV Central;MTV Networks:11739:vC34:S19.2E:27500:3031:3032:3034:0:28653:1:1066:0 VIVA;VIVA Fernsehen GmbH & Co. KG:12669:vC56:S19.2E:22000:309:310=deu:311:0:12732:1:1116:0 @@ -89,7 +89,7 @@ TELE 5;BetaDigital:12480:vC34:S19.2E:27500:1535:1536=deu:38:0:51:133:33:0 :@201 Sky Sky One;BSkyB:12226:hC23:S28.2E:27500:515+8190:643=eng:579:960,961:4705:2:2027:0 Sky Mix;BSkyB:12226:hC23:S28.2E:27500:514+8190:642=eng,662=NAR:578:960,961:5104:2:2027:0 -ITV2;BSkyB:10906:vC56:S28.2E:22000:2350:2351=eng:2353:960,961:10240:2:2054:0 +ITV2;BSkyB:10758:vC56:S28.2E:22000:2314:2315=eng:2317:960,961:10070:2:2044:0 Sci-Fi;BSkyB:12148:hC23:S28.2E:27500:512+8190:640=eng:576:960,961:4905:2:2023:0 Paramount;BSkyB:12187:hC23:S28.2E:27500:2313+2304:2317=eng,2318=NAR:2315:960,961:5904:2:2025:0 Discovery;BSkyB:11875:hC23:S28.2E:27500:2304:2306=eng,2307=NAR:2305:960,961:6201:2:2009:0 @@ -99,19 +99,18 @@ Sky Movies 3;BSkyB:11836:hC23:S28.2E:27500:520+8190:648=eng,654=NAR;688=eng:584: Sky Movies 4;BSkyB:11914:hC23:S28.2E:27500:512+8190:640=eng,660=NAR:576:960,961:4402:2:2011:0 Sky Movies 5;BSkyB:11914:hC23:S28.2E:27500:515+8190:643=eng,663=NAR:579:960,961:4503:2:2011:0 Sky Movies 6;BSkyB:11914:hC23:S28.2E:27500:513+8190:641=eng,661=NAR:577:960,961:4502:2:2011:0 -Sky Movies 7;BSkyB:12090:vC23:S28.2E:27500:2312+2304:2313=eng,2314=NAR:2315:960,961:4603:2:2020:0 +Sky Movies 7;BSkyB:12285:vC23:S28.2E:27500:515+8190:643=eng,663=NAR:579:960,961:4603:2:2030:0 Sky Movies 8;BSkyB:11836:hC23:S28.2E:27500:515+8190:643=eng,663=NAR:579:960,961:5502:2:2007:0 -Sky Movies 9;BSkyB:12090:vC23:S28.2E:27500:2308+2304:2309=eng,2310=NAR:2311:960,961:4602:2:2020:0 -Sky Cinema 1;BSkyB:12090:vC23:S28.2E:27500:2305+2304:2306=eng:2307:960,961:4809:2:2020:0 -Sky Cinema 2;BSkyB:12090:vC23:S28.2E:27500:2316+2304:2317=eng:2318:960,961:4802:2:2020:0 +Sky Movies 9;BSkyB:12285:vC23:S28.2E:27500:518+8190:646=eng,666=NAR:582:960,961:4602:2:2030:0 +Sky Cinema 1;BSkyB:12285:vC23:S28.2E:27500:519+8190:647=eng,667=NAR:583:960,961:4809:2:2030:0 +Sky Cinema 2;BSkyB:12285:vC23:S28.2E:27500:517+8190:645=eng,665=NAR:581:960,961:4802:2:2030:0 :@900 Some 'seed' channels Chelsea TV;BskyB:11778:vC23:S28.2E:27500:2308+2304:2309=eng:0:960,961:9307:2:2004:0 WDR Münster;ARD:12421:hC34:S19.2E:27500:101:102=deu:104:0:28310:1:1201:0 -Going Places:10920:hC56:S28.2E:22000:2310+2304:2311=eng:2312:0:5008:2:2055:0 Animal Plnt+;BSkyB:12070:hC23:S28.2E:27500:2314+2307:2315=eng:0:960,961:50002:2:2019:0 S1T;BSkyB:12285:vC23:S28.2E:27500:513+8190:641=eng,661=NAR:577:960,961:4409:2:2030:0 CNN;BSkyB:12051:vC23:S28.2E:27500:2313:2315=eng:2314:0:7140:2:2018:0 -BBC PARL'MNT:12129:vC23:S28.2E:27500:2304:2306=eng,2307=eng:2305:0:7300:2:2022:0 +BBC PARL'MNT;BSkyB:10847:vC56:S28.2E:22000:2327:2328=eng:2331:0:6902:2:2050:0 Bethel TV;T-Systems/MTI:11200:vC56:S13.0E:27500:413:414:0:0:4733:318:13400:0 Euro1080;EURO1080:12168:vC34:S19.2E:27500:308:256:0:FF:21100:1:1088:0 Astra HD:12441:vC34:S19.2E:27500:133+80:134=eng:0:FF:29700:0:0:0 @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: channels.h 1.32 2005/05/28 13:57:08 kls Exp $ + * $Id: channels.h 1.33 2005/08/06 11:23:32 kls Exp $ */ #ifndef __CHANNELS_H @@ -181,6 +181,7 @@ public: bool IsTerr(void) const { return cSource::IsTerr(source); } tChannelID GetChannelID(void) const { return tChannelID(source, nid, (nid || tid) ? tid : Transponder(), sid, rid); } int Modification(int Mask = CHANNELMOD_ALL); + void CopyTransponderData(const cChannel *Channel); bool SetSatTransponderData(int Source, int Frequency, char Polarization, int Srate, int CoderateH); bool SetCableTransponderData(int Source, int Frequency, int Modulation, int Srate, int CoderateH); bool SetTerrTransponderData(int Source, int Frequency, int Bandwidth, int Modulation, int Hierarchy, int CodeRateH, int CodeRateL, int Guard, int Transmission); @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: config.c 1.134 2005/06/18 10:30:02 kls Exp $ + * $Id: config.c 1.135 2005/08/07 09:03:00 kls Exp $ */ #include "config.h" @@ -472,6 +472,7 @@ bool cSetup::Save(void) Store("OSDTheme", OSDTheme); Store("PrimaryDVB", PrimaryDVB); Store("ShowInfoOnChSwitch", ShowInfoOnChSwitch); + Store("MenuScrollPage", MenuScrollPage); Store("MenuScrollWrap", MenuScrollWrap); Store("MarkInstantRecord", MarkInstantRecord); Store("NameInstantRecord", NameInstantRecord); @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: config.h 1.221 2005/06/18 10:29:25 kls Exp $ + * $Id: config.h 1.222 2005/07/30 09:19:25 kls Exp $ */ #ifndef __CONFIG_H @@ -20,8 +20,8 @@ #include "i18n.h" #include "tools.h" -#define VDRVERSION "1.3.27" -#define VDRVERSNUM 10327 // Version * 10000 + Major * 100 + Minor +#define VDRVERSION "1.3.28" +#define VDRVERSNUM 10328 // 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.59 2005/06/12 13:35:47 kls Exp $ + * $Id: device.h 1.60 2005/07/30 09:31:53 kls Exp $ */ #ifndef __DEVICE_H @@ -444,8 +444,7 @@ public: ///< Returns true if the device itself or any of the file handles in ///< Poller is ready for further action. ///< If TimeoutMs is not zero, the device will wait up to the given number - ///< of milleseconds before returning in case there is no immediate - ///< need for data. + ///< of milleseconds before returning in case it can't accept any data. virtual bool Flush(int TimeoutMs = 0); ///< Returns true if the device's output buffers are empty, i. e. any ///< data which was bufferd so far has been processed. diff --git a/dvbplayer.c b/dvbplayer.c index 2d4e1e4..cd002a7 100644 --- a/dvbplayer.c +++ b/dvbplayer.c @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: dvbplayer.c 1.34 2005/05/22 11:26:51 kls Exp $ + * $Id: dvbplayer.c 1.36 2005/07/30 10:00:24 kls Exp $ */ #include "dvbplayer.h" @@ -497,6 +497,8 @@ void cDvbPlayer::Action(void) p = NULL; } } + else + Sleep = true; } } active = running = false; @@ -666,11 +668,34 @@ void cDvbPlayer::Goto(int Index, bool Still) int FileOffset, Length; Index = index->GetNextIFrame(Index, false, &FileNumber, &FileOffset, &Length); if (Index >= 0 && NextFile(FileNumber, FileOffset) && Still) { - uchar b[MAXFRAMESIZE]; + uchar b[MAXFRAMESIZE + 4 + 5 + 4]; int r = ReadFrame(replayFile, b, Length, sizeof(b)); if (r > 0) { if (playMode == pmPause) DevicePlay(); + // append sequence end code to get the image shown immediately with softdevices + if (r > 6) { // should be always true + b[r++] = 0x00; + b[r++] = 0x00; + b[r++] = 0x01; + b[r++] = b[3]; + if (b[6] & 0x80) { // MPEG 2 + b[r++] = 0x00; + b[r++] = 0x07; + b[r++] = 0x80; + b[r++] = 0x00; + b[r++] = 0x00; + } + else { // MPEG 1 + b[r++] = 0x00; + b[r++] = 0x05; + b[r++] = 0x0F; + } + b[r++] = 0x00; + b[r++] = 0x00; + b[r++] = 0x01; + b[r++] = 0xB7; + } DeviceStillPicture(b, r); } playMode = pmStill; @@ -8,7 +8,7 @@ * * parts of this file are derived from the OMS program. * - * $Id: dvbspu.c 1.14 2005/05/07 11:13:48 kls Exp $ + * $Id: dvbspu.c 1.15 2005/08/07 12:06:32 kls Exp $ */ #include <assert.h> @@ -155,7 +155,7 @@ void cDvbSpuBitmap::putPixel(int xp, int yp, int len, uint8_t colorid) setMin(minsize[colorid].x1, xp); setMin(minsize[colorid].y1, yp); setMax(minsize[colorid].x2, xp + len - 1); - setMax(minsize[colorid].y2, yp + len - 1); + setMax(minsize[colorid].y2, yp); } static uint8_t getBits(uint8_t * &data, uint8_t & bitf) @@ -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.108 2005/06/11 15:31:21 kls Exp $ + * $Id: eit.c 1.109 2005/08/07 13:52:29 kls Exp $ */ #include "eit.h" @@ -252,11 +252,13 @@ cEIT::cEIT(cSchedules *Schedules, int Source, u_char Tid, const u_char *Data) class cTDT : public SI::TDT { private: static cMutex mutex; + static int lastDiff; public: cTDT(const u_char *Data); }; cMutex cTDT::mutex; +int cTDT::lastDiff = 0; cTDT::cTDT(const u_char *Data) :SI::TDT(Data, false) @@ -266,12 +268,16 @@ cTDT::cTDT(const u_char *Data) time_t sattim = getTime(); time_t loctim = time(NULL); - if (abs(sattim - loctim) > 2) { + int diff = abs(sattim - loctim); + if (diff > 2) { mutex.Lock(); - isyslog("System Time = %s (%ld)\n", *TimeToString(loctim), loctim); - isyslog("Local Time = %s (%ld)\n", *TimeToString(sattim), sattim); - if (stime(&sattim) < 0) - esyslog("ERROR while setting system time: %m"); + if (abs(diff - lastDiff) < 3) { + isyslog("System Time = %s (%ld)\n", *TimeToString(loctim), loctim); + isyslog("Local Time = %s (%ld)\n", *TimeToString(sattim), sattim); + if (stime(&sattim) < 0) + esyslog("ERROR while setting system time: %m"); + } + lastDiff = diff; mutex.Unlock(); } } @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: eitscan.c 1.26 2005/06/12 14:09:45 kls Exp $ + * $Id: eitscan.c 1.27 2005/08/07 11:29:54 kls Exp $ */ #include "eitscan.h" @@ -127,7 +127,7 @@ void cEITScanner::Activity(void) void cEITScanner::Process(void) { - if (Setup.EPGScanTimeout && Channels.MaxNumber() > 1) { + if ((Setup.EPGScanTimeout || !lastActivity) && Channels.MaxNumber() > 1) { // !lastActivity means a scan was forced time_t now = time(NULL); if (now - lastScan > ScanTimeout && now - lastActivity > ActivityTimeout) { if (Channels.Lock(false, 10)) { @@ -150,8 +150,9 @@ void cEITScanner::Process(void) if (!Channel->Ca() || Channel->Ca() == Device->DeviceNumber() + 1 || Channel->Ca() >= 0x0100) { if (Device->ProvidesTransponder(Channel)) { if (!Device->Receiving()) { - if (Device != cDevice::ActualDevice() || (Device->ProvidesTransponderExclusively(Channel) && Setup.EPGScanTimeout && now - lastActivity > Setup.EPGScanTimeout * 3600)) { - if (Device == cDevice::ActualDevice() && !currentChannel) { + bool IsPrimaryDeviceReplaying = Device == cDevice::PrimaryDevice() && Device->Replaying(); + if (Device != cDevice::ActualDevice() || (Device->ProvidesTransponderExclusively(Channel) && (IsPrimaryDeviceReplaying || now - lastActivity > Setup.EPGScanTimeout * 3600))) { + if (!IsPrimaryDeviceReplaying && Device == cDevice::ActualDevice() && !currentChannel) { if (cTransferControl::ReceiverDevice()) cDevice::PrimaryDevice()->StopReplay(); // stop transfer mode currentChannel = Device->CurrentChannel(); @@ -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.35 2005/06/05 12:17:15 kls Exp $ + * $Id: epg.c 1.36 2005/07/30 14:44:54 kls Exp $ */ #include "epg.h" @@ -298,6 +298,8 @@ bool cEvent::Read(FILE *f, cSchedule *Schedule) if (n == 3 || n == 4) { Event = (cEvent *)Schedule->GetEvent(EventID, StartTime); cEvent *newEvent = NULL; + if (Event) + DELETENULL(Event->components); if (!Event) Event = newEvent = new cEvent(EventID); if (Event) { @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: i18n.c 1.195 2005/06/18 10:42:31 kls Exp $ + * $Id: i18n.c 1.197 2005/08/06 16:09:44 kls Exp $ * * Translations provided by: * @@ -416,7 +416,7 @@ const tI18nPhrase Phrases[] = { "",//TODO "",//TODO "",//TODO - "",//TODO + "Info", "Info", "",//TODO }, @@ -2332,7 +2332,7 @@ const tI18nPhrase Phrases[] = { "",//TODO "",//TODO "¾âáãâáâÒãÕâ ×ÒãÚ!", - "",//TODO + "Audio nedostupan", "Audio kättesaamatu!", "Ingen lyd tilgængelig!", }, @@ -2859,7 +2859,7 @@ const tI18nPhrase Phrases[] = { "",// TODO "",// TODO "¿ÞÚÐ× ØÝäÞàÜÐæØØ Þ ÚÐÝÐÛÕ (áÕÚ)", - "",// TODO + "Vrijeme prikaza informacije o programu (s)", "Kanaliteate esitusaeg (s)", "Tid kanalinfo skal vises (s)", }, @@ -2892,7 +2892,7 @@ const tI18nPhrase Phrases[] = { "Scroll da página no menu", "Scrolling par pages", "Rask rulling i menyer", - "Valikkosivujen pikaselaus", + "Valikoiden vieritys sivuttain", "Przesuwac stronami", "Desplazar página entera", "Êßëéóç óåëßäáò", @@ -2913,6 +2913,7 @@ const tI18nPhrase Phrases[] = { "",// TODO "",// TODO "",// TODO + "Valikoiden vieritys ympäri", "",// TODO "",// TODO "",// TODO @@ -2921,8 +2922,7 @@ const tI18nPhrase Phrases[] = { "",// TODO "",// TODO "",// TODO - "",// TODO - "",// TODO + "S kraja skoèi na poèetak", "",// TODO "",// TODO }, @@ -3153,7 +3153,7 @@ const tI18nPhrase Phrases[] = { "",//TODO "",//TODO "ÈØàÞÚÞíÚàÐÝÝÞÕ Ø×ÞÑàÐÖÕÝØÕ", - "",//TODO + "Format video prikaza", "Video kuvamise formaat", "Video display format", }, @@ -3258,7 +3258,7 @@ const tI18nPhrase Phrases[] = { "",//TODO "",//TODO "²ÚÛîçØâì Dolby Digital", - "",//TODO + "Koristi Dolby Digital", "Dolby Digital kasutamine", "Anvend Dolby Digital", }, @@ -3384,7 +3384,7 @@ const tI18nPhrase Phrases[] = { "",//TODO "",//TODO "¿àÕÔßÞçØâÐÕÜëÕ ï×ëÚØ (×ÒãÚ)", - "",//TODO + "Audio jezici", "Audio keeled", "Audio sprog (ant.)", }, @@ -3405,7 +3405,7 @@ const tI18nPhrase Phrases[] = { "",//TODO "",//TODO "²ëÑàÐÝ", - "",//TODO + "Audio jezik", "Audio keel", "Audio sprog", }, @@ -3909,7 +3909,7 @@ const tI18nPhrase Phrases[] = { "Min. esemény szünet (min)", "Temps mínim en pausa (min)", "¼ØÝ. ÒàÕÜï ÞÖØÔÐÝØï áÞÑëâØï (ÜØÝ)", - "Najmanje vrijeme pauze", + "Minimalno vrijeme pauze", "Min. sündmuse kestus (min)", "Mindste hændelsespause (min)", }, @@ -3930,7 +3930,7 @@ const tI18nPhrase Phrases[] = { "Min. kezelési aktivitás (min)", "Temps mínim d'inactivitat (min)", "¼ØÝ. ÒàÕÜï ÞÖØÔÐÝØï ÒÒÞÔÐ (ÜØÝ)", - "Najmanje vrijeme neaktivnosti (min)", + "Minimalno vrijeme neaktivnosti (min)", "Min. kasutaja tegevusetus (min)", "Min. bruger inaktivitet (min)", }, @@ -5300,7 +5300,7 @@ const tI18nPhrase Phrases[] = { "",// TODO "",// TODO "",// TODO - "",// TODO + "Poèinjem EPG-scan", "EPG skaneerimine käivitatud", "Starter EPG skanning", }, @@ -5384,7 +5384,7 @@ const tI18nPhrase Phrases[] = { "",// TODO "",// TODO "",// TODO - "",// TODO + "Bez titla", "",// TODO "",// TODO }, @@ -6,7 +6,7 @@ * * LIRC support added by Carsten Koch <Carsten.Koch@icem.de> 2000-06-16. * - * $Id: lirc.c 1.10 2005/01/14 14:18:42 kls Exp $ + * $Id: lirc.c 1.11 2005/07/31 10:18:09 kls Exp $ */ #include "lirc.h" @@ -18,7 +18,7 @@ #define REPEATDELAY 350 // ms #define KEYPRESSDELAY 150 // ms -cLircRemote::cLircRemote(char *DeviceName) +cLircRemote::cLircRemote(const char *DeviceName) :cRemote("LIRC") ,cThread("LIRC remote control") { @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: lirc.h 1.2 2003/04/12 14:15:20 kls Exp $ + * $Id: lirc.h 1.3 2005/07/31 10:18:15 kls Exp $ */ #ifndef __LIRC_H @@ -19,7 +19,7 @@ private: int f; virtual void Action(void); public: - cLircRemote(char *DeviceName); + cLircRemote(const char *DeviceName); virtual ~cLircRemote(); virtual bool Ready(void); }; @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: pat.c 1.12 2005/01/25 21:02:11 kls Exp $ + * $Id: pat.c 1.13 2005/08/06 12:23:51 kls Exp $ */ #include "pat.h" @@ -324,10 +324,10 @@ void cPatFilter::Process(u_short Pid, u_char Tid, const u_char *Data, int Length SI::PMT::Stream stream; int Vpid = 0; int Ppid = pmt.getPCRPid(); - int Apids[MAXAPIDS + 1] = { 0 }; + int Apids[MAXAPIDS + 1] = { 0 }; // these lists are zero-terminated int Dpids[MAXDPIDS + 1] = { 0 }; - char ALangs[MAXAPIDS + 1][4] = { "" }; - char DLangs[MAXDPIDS + 1][4] = { "" }; + char ALangs[MAXAPIDS][4] = { "" }; + char DLangs[MAXDPIDS][4] = { "" }; int Tpid = 0; int NumApids = 0; int NumDpids = 0; @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: rcu.c 1.8 2004/12/19 18:06:00 kls Exp $ + * $Id: rcu.c 1.9 2005/07/31 10:17:45 kls Exp $ */ #include "rcu.h" @@ -16,7 +16,7 @@ #define REPEATLIMIT 20 // ms #define REPEATDELAY 350 // ms -cRcuRemote::cRcuRemote(char *DeviceName) +cRcuRemote::cRcuRemote(const char *DeviceName) :cRemote("RCU") ,cThread("RCU remote control") { @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: rcu.h 1.3 2003/04/12 14:36:09 kls Exp $ + * $Id: rcu.h 1.4 2005/07/31 10:18:00 kls Exp $ */ #ifndef __RCU_H @@ -37,7 +37,7 @@ private: virtual void ChannelSwitch(const cDevice *Device, int ChannelNumber); virtual void Recording(const cDevice *Device, const char *Name); public: - cRcuRemote(char *DeviceName); + cRcuRemote(const char *DeviceName); virtual ~cRcuRemote(); virtual bool Ready(void); virtual bool Initialize(void); diff --git a/recording.c b/recording.c index 462b160..081f9e6 100644 --- a/recording.c +++ b/recording.c @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: recording.c 1.109 2005/06/05 14:11:45 kls Exp $ + * $Id: recording.c 1.110 2005/08/06 09:53:21 kls Exp $ */ #include "recording.h" @@ -199,7 +199,7 @@ int cResumeFile::Read(void) bool cResumeFile::Save(int Index) { if (fileName) { - int f = open(fileName, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); + int f = open(fileName, O_WRONLY | O_CREAT | O_TRUNC, DEFFILEMODE); if (f >= 0) { if (safe_write(f, &Index, sizeof(Index)) < 0) LOG_ERROR_STR(fileName); @@ -974,7 +974,7 @@ cIndexFile::cIndexFile(const char *FileName, bool Record) else if (!Record) isyslog("missing index file %s", fileName); if (Record) { - if ((f = open(fileName, O_WRONLY | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)) >= 0) { + if ((f = open(fileName, O_WRONLY | O_CREAT | O_APPEND, DEFFILEMODE)) >= 0) { if (delta) { esyslog("ERROR: padding index file with %d '0' bytes", delta); while (delta--) @@ -11,7 +11,7 @@ * The cDolbyRepacker code was originally written by Reinhard Nissl <rnissl@gmx.de>, * and adapted to the VDR coding style by Klaus.Schmidinger@cadsoft.de. * - * $Id: remux.c 1.35 2005/06/19 10:17:00 kls Exp $ + * $Id: remux.c 1.36 2005/07/30 10:23:00 kls Exp $ */ #include "remux.h" @@ -26,17 +26,92 @@ class cRepacker { protected: int maxPacketSize; uint8_t subStreamId; + static void DroppedData(const char *Reason, int Count) { esyslog("%s (dropped %d bytes)", Reason, Count); } + static int Put(cRingBufferLinear *ResultBuffer, const uchar *Data, int Count) + { + int n = ResultBuffer->Put(Data, Count); + if (n != Count) + esyslog("ERROR: result buffer overflow, dropped %d out of %d byte", Count - n, Count); + return n; + } + static int AnalyzePesHeader(const uchar *Data, int Count, int &PesPayloadOffset, bool *ContinuationHeader = 0); public: cRepacker(void) { maxPacketSize = 6 + 65535; subStreamId = 0; } virtual ~cRepacker() {} virtual void Reset(void) {} - virtual int Put(cRingBufferLinear *ResultBuffer, const uchar *Data, int Count) = 0; + virtual void Repack(cRingBufferLinear *ResultBuffer, const uchar *Data, int Count) = 0; virtual int BreakAt(const uchar *Data, int Count) = 0; virtual int QuerySnoopSize(void) { return 0; } void SetMaxPacketSize(int MaxPacketSize) { maxPacketSize = MaxPacketSize; } void SetSubStreamId(uint8_t SubStreamId) { subStreamId = SubStreamId; } }; +int cRepacker::AnalyzePesHeader(const uchar *Data, int Count, int &PesPayloadOffset, bool *ContinuationHeader) +{ + if (Count < 7) + return -1; // too short + + if ((Data[6] & 0xC0) == 0x80) { // MPEG 2 + if (Count < 9) + return -1; // too short + + PesPayloadOffset = 6 + 3 + Data[8]; + if (Count < PesPayloadOffset) + return -1; // too short + + if (ContinuationHeader) + *ContinuationHeader = ((Data[6] == 0x80) && !Data[7] && !Data[8]); + + return 2; // MPEG 2 + } + + // check for MPEG 1 ... + PesPayloadOffset = 6; + + // skip up to 16 stuffing bytes + for (int i = 0; i < 16; i++) { + if (Data[PesPayloadOffset] != 0xFF) + break; + + if (Count <= ++PesPayloadOffset) + return -1; // too short + } + + // skip STD_buffer_scale/size + if ((Data[PesPayloadOffset] & 0xC0) == 0x40) { + PesPayloadOffset += 2; + + if (Count <= PesPayloadOffset) + return -1; // too short + } + + if (ContinuationHeader) + *ContinuationHeader = false; + + if ((Data[PesPayloadOffset] & 0xF0) == 0x20) { + // skip PTS only + PesPayloadOffset += 5; + } + else if ((Data[PesPayloadOffset] & 0xF0) == 0x30) { + // skip PTS and DTS + PesPayloadOffset += 10; + } + else if (Data[PesPayloadOffset] == 0x0F) { + // continuation header + PesPayloadOffset++; + + if (ContinuationHeader) + *ContinuationHeader = true; + } + else + return 0; // unknown + + if (Count < PesPayloadOffset) + return -1; // too short + + return 1; // MPEG 1 +} + // --- cVideoRepacker -------------------------------------------------------- class cVideoRepacker : public cRepacker { @@ -61,7 +136,7 @@ private: public: cVideoRepacker(void); virtual void Reset(void); - virtual int Put(cRingBufferLinear *ResultBuffer, const uchar *Data, int Count); + virtual void Repack(cRingBufferLinear *ResultBuffer, const uchar *Data, int Count); virtual int BreakAt(const uchar *Data, int Count); virtual int QuerySnoopSize() { return 4; } }; @@ -95,7 +170,7 @@ bool cVideoRepacker::PushOutPacket(cRingBufferLinear *ResultBuffer, const uchar // to strip off any partially contained start code. int Bite = fragmentLen + (Count >= 0 ? 0 : Count); // put data into result buffer - int n = ResultBuffer->Put(fragmentData, Bite); + int n = Put(ResultBuffer, fragmentData, Bite); if (n != Bite) { Reset(); return false; @@ -110,7 +185,7 @@ bool cVideoRepacker::PushOutPacket(cRingBufferLinear *ResultBuffer, const uchar // to strip off any partially contained start code. int Bite = pesHeaderLen + (Count >= 0 ? 0 : Count); // put data into result buffer - int n = ResultBuffer->Put(pesHeader, Bite); + int n = Put(ResultBuffer, pesHeader, Bite); if (n != Bite) { Reset(); return false; @@ -122,7 +197,7 @@ bool cVideoRepacker::PushOutPacket(cRingBufferLinear *ResultBuffer, const uchar // amount of data to put into result buffer int Bite = Count; // put data into result buffer - int n = ResultBuffer->Put(Data, Bite); + int n = Put(ResultBuffer, Data, Bite); if (n != Bite) { Reset(); return false; @@ -132,23 +207,29 @@ bool cVideoRepacker::PushOutPacket(cRingBufferLinear *ResultBuffer, const uchar return true; } -int cVideoRepacker::Put(cRingBufferLinear *ResultBuffer, const uchar *Data, int Count) +void cVideoRepacker::Repack(cRingBufferLinear *ResultBuffer, const uchar *Data, int Count) { + // synchronisation is detected some bytes after frame start. + const int SkippedBytesLimit = 4; + // reset local scanner localStart = -1; - - // check for MPEG 2 - if ((Data[6] & 0xC0) != 0x80) - return 0; - // backup PES header - if (Data[6] != 0x80 || Data[7] != 0x00 || Data[8] != 0x00) { - pesHeaderBackupLen = 6 + 3 + Data[8]; - memcpy(pesHeaderBackup, Data, pesHeaderBackupLen); + int pesPayloadOffset = 0; + bool continuationHeader = false; + int mpegLevel = AnalyzePesHeader(Data, Count, pesPayloadOffset, &continuationHeader); + if (mpegLevel <= 0) { + DroppedData("cVideoRepacker: no valid PES packet header found", Count); + return; } + if (!continuationHeader) { + // backup PES header + pesHeaderBackupLen = pesPayloadOffset; + memcpy(pesHeaderBackup, Data, pesHeaderBackupLen); + } // skip PES header - int done = 6 + 3 + Data[8]; + int done = pesPayloadOffset; int todo = Count - done; const uchar *data = Data + done; // remember start of the data @@ -191,15 +272,17 @@ int cVideoRepacker::Put(cRingBufferLinear *ResultBuffer, const uchar *Data, int // the byte count get's negative then the current buffer ends in a // partitial start code that must be stripped off, as it shall be put // in the next packet. - if (!PushOutPacket(ResultBuffer, payload, data - 3 - payload)) - return done - 3; + if (!PushOutPacket(ResultBuffer, payload, data - 3 - payload)) { + DroppedData("cVideoRepacker: result buffer overflow", Count - (done - 3)); + return; + } // go on with syncing to the next picture state = syncing; } if (state == syncing) { // report that syncing dropped some bytes - if (skippedBytes > 4) - esyslog("cVideoRepacker: skipped %d bytes to sync on next picture", skippedBytes - 4); + if (skippedBytes > SkippedBytesLimit) + esyslog("cVideoRepacker: skipped %d bytes to sync on next picture", skippedBytes - SkippedBytesLimit); skippedBytes = 0; // if there is a PES header available, then use it ... if (pesHeaderBackupLen > 0) { @@ -222,9 +305,14 @@ int cVideoRepacker::Put(cRingBufferLinear *ResultBuffer, const uchar *Data, int pesHeader[pesHeaderLen++] = Data[3]; // video stream ID pesHeader[pesHeaderLen++] = 0x00; // length still unknown pesHeader[pesHeaderLen++] = 0x00; // length still unknown - pesHeader[pesHeaderLen++] = 0x80; - pesHeader[pesHeaderLen++] = 0x00; - pesHeader[pesHeaderLen++] = 0x00; + + if (mpegLevel == 2) { + pesHeader[pesHeaderLen++] = 0x80; + pesHeader[pesHeaderLen++] = 0x00; + pesHeader[pesHeaderLen++] = 0x00; + } + else + pesHeader[pesHeaderLen++] = 0x0F; } // append the first three bytes of the start code pesHeader[pesHeaderLen++] = 0x00; @@ -299,8 +387,10 @@ int cVideoRepacker::Put(cRingBufferLinear *ResultBuffer, const uchar *Data, int const uchar *excessData = fragmentData + fragmentLen + bite; // a negative byte count means to drop some bytes from the current // fragment's tail, to not exceed the maximum packet size. - if (!PushOutPacket(ResultBuffer, payload, bite)) - return done; + if (!PushOutPacket(ResultBuffer, payload, bite)) { + DroppedData("cVideoRepacker: result buffer overflow", Count - done); + return; + } // create a continuation PES header pesHeaderLen = 0; pesHeader[pesHeaderLen++] = 0x00; @@ -309,9 +399,15 @@ int cVideoRepacker::Put(cRingBufferLinear *ResultBuffer, const uchar *Data, int pesHeader[pesHeaderLen++] = Data[3]; // video stream ID pesHeader[pesHeaderLen++] = 0x00; // length still unknown pesHeader[pesHeaderLen++] = 0x00; // length still unknown - pesHeader[pesHeaderLen++] = 0x80; - pesHeader[pesHeaderLen++] = 0x00; - pesHeader[pesHeaderLen++] = 0x00; + + if (mpegLevel == 2) { + pesHeader[pesHeaderLen++] = 0x80; + pesHeader[pesHeaderLen++] = 0x00; + pesHeader[pesHeaderLen++] = 0x00; + } + else + pesHeader[pesHeaderLen++] = 0x0F; + // copy any excess data while (bite++ < 0) { // append the excess data here @@ -344,22 +440,20 @@ int cVideoRepacker::Put(cRingBufferLinear *ResultBuffer, const uchar *Data, int fragmentLen += bite; } } - // we've eaten the whole packet ;-) - return Count; + // report that syncing dropped some bytes + if (skippedBytes > SkippedBytesLimit) { + esyslog("cVideoRepacker: skipped %d bytes while syncing on next picture", skippedBytes - SkippedBytesLimit); + skippedBytes = SkippedBytesLimit; + } } int cVideoRepacker::BreakAt(const uchar *Data, int Count) { - // enough data for test? - if (Count < 6 + 3) - return -1; - // check for MPEG 2 - if ((Data[6] & 0xC0) != 0x80) - return -1; - int headerLen = Data[8] + 6 + 3; - // enough data for test? - if (Count < headerLen) - return -1; + int PesPayloadOffset = 0; + + if (AnalyzePesHeader(Data, Count, PesPayloadOffset) <= 0) + return -1; // not enough data for test + // just detect end of picture if (state == scanPicture) { // setup local scanner @@ -368,7 +462,7 @@ int cVideoRepacker::BreakAt(const uchar *Data, int Count) localStart = 0; } // start where we've stopped at the last run - const uchar *data = Data + headerLen + localStart; + const uchar *data = Data + PesPayloadOffset + localStart; const uchar *limit = Data + Count; // scan data while (data < limit) { @@ -386,7 +480,7 @@ int cVideoRepacker::BreakAt(const uchar *Data, int Count) } } // just fill up packet and append next start code - return headerLen + packetTodo + 4; + return PesPayloadOffset + packetTodo + 4; } // --- cDolbyRepacker -------------------------------------------------------- @@ -412,6 +506,7 @@ private: get_length, output_packet } state; + int skippedBytes; void ResetPesHeader(bool ContinuationFrame = false); void AppendSubStreamID(bool ContinuationFrame = false); bool FinishRemainder(cRingBufferLinear *ResultBuffer, const uchar *const Data, const int Todo, int &Done, int &Bite); @@ -419,7 +514,7 @@ private: public: cDolbyRepacker(void); virtual void Reset(void); - virtual int Put(cRingBufferLinear *ResultBuffer, const uchar *Data, int Count); + virtual void Repack(cRingBufferLinear *ResultBuffer, const uchar *Data, int Count); virtual int BreakAt(const uchar *Data, int Count); }; @@ -490,6 +585,7 @@ void cDolbyRepacker::Reset(void) fragmentLen = 0; fragmentTodo = 0; pesHeaderBackupLen = 0; + skippedBytes = 0; } bool cDolbyRepacker::FinishRemainder(cRingBufferLinear *ResultBuffer, const uchar *const Data, const int Todo, int &Done, int &Bite) @@ -499,7 +595,7 @@ bool cDolbyRepacker::FinishRemainder(cRingBufferLinear *ResultBuffer, const ucha // output a previous fragment first if (fragmentLen > 0) { Bite = fragmentLen; - int n = ResultBuffer->Put(fragmentData, Bite); + int n = Put(ResultBuffer, fragmentData, Bite); if (Bite != n) { Reset(); return false; @@ -507,7 +603,7 @@ bool cDolbyRepacker::FinishRemainder(cRingBufferLinear *ResultBuffer, const ucha fragmentLen = 0; } Bite = fragmentTodo; - int n = ResultBuffer->Put(Data, Bite); + int n = Put(ResultBuffer, Data, Bite); if (Bite != n) { Reset(); Done += n; @@ -543,13 +639,13 @@ bool cDolbyRepacker::StartNewPacket(cRingBufferLinear *ResultBuffer, const uchar Bite = pesHeaderLen; // enough data available to put PES packet into buffer? if (packetLen - pesHeaderLen <= Todo) { - int n = ResultBuffer->Put(pesHeader, Bite); + int n = Put(ResultBuffer, pesHeader, Bite); if (Bite != n) { Reset(); return false; } Bite = packetLen - pesHeaderLen; - n = ResultBuffer->Put(Data, Bite); + n = Put(ResultBuffer, Data, Bite); if (Bite != n) { Reset(); Done += n; @@ -582,11 +678,16 @@ bool cDolbyRepacker::StartNewPacket(cRingBufferLinear *ResultBuffer, const uchar return true; } -int cDolbyRepacker::Put(cRingBufferLinear *ResultBuffer, const uchar *Data, int Count) +void cDolbyRepacker::Repack(cRingBufferLinear *ResultBuffer, const uchar *Data, int Count) { + // synchronisation is detected some bytes after frame start. + const int SkippedBytesLimit = 4; + // check for MPEG 2 - if ((Data[6] & 0xC0) != 0x80) - return 0; + if ((Data[6] & 0xC0) != 0x80) { + DroppedData("cDolbyRepacker: MPEG 2 PES header expected", Count); + return; + } // backup PES header if (Data[6] != 0x80 || Data[7] != 0x00 || Data[8] != 0x00) { @@ -616,6 +717,7 @@ int cDolbyRepacker::Put(cRingBufferLinear *ResultBuffer, const uchar *Data, int data++; done++; todo--; + skippedBytes++; // collect number of skipped bytes while syncing continue; case find_77: if (*data != 0x77) { @@ -625,18 +727,21 @@ int cDolbyRepacker::Put(cRingBufferLinear *ResultBuffer, const uchar *Data, int data++; done++; todo--; + skippedBytes++; // collect number of skipped bytes while syncing ++(int &)state; continue; case store_chk1: chk1 = *data++; done++; todo--; + skippedBytes++; // collect number of skipped bytes while syncing ++(int &)state; continue; case store_chk2: chk2 = *data++; done++; todo--; + skippedBytes++; // collect number of skipped bytes while syncing ++(int &)state; continue; case get_length: @@ -664,6 +769,10 @@ int cDolbyRepacker::Put(cRingBufferLinear *ResultBuffer, const uchar *Data, int state = find_0b; continue; } + // report that syncing dropped some bytes + if (skippedBytes > SkippedBytesLimit) + esyslog("cDolbyRepacker: skipped %d bytes to sync on next AC3 frame", skippedBytes - SkippedBytesLimit); + skippedBytes = 0; // append read data to header for common output processing pesHeader[pesHeaderLen++] = 0x0B; pesHeader[pesHeaderLen++] = 0x77; @@ -676,13 +785,17 @@ int cDolbyRepacker::Put(cRingBufferLinear *ResultBuffer, const uchar *Data, int int bite = 0; // finish remainder of ac3 frame? if (fragmentTodo > 0) { - if (!FinishRemainder(ResultBuffer, data, todo, done, bite)) - return done; + if (!FinishRemainder(ResultBuffer, data, todo, done, bite)) { + DroppedData("cDolbyRepacker: result buffer overflow", Count - done); + return; + } } else { // start a new packet - if (!StartNewPacket(ResultBuffer, data, todo, done, bite)) - return done; + if (!StartNewPacket(ResultBuffer, data, todo, done, bite)) { + DroppedData("cDolbyRepacker: result buffer overflow", Count - done); + return; + } // prepare for next (continuation) packet ResetPesHeader(state == output_packet); } @@ -693,7 +806,11 @@ int cDolbyRepacker::Put(cRingBufferLinear *ResultBuffer, const uchar *Data, int } } } - return Count; + // report that syncing dropped some bytes + if (skippedBytes > SkippedBytesLimit) { + esyslog("cDolbyRepacker: skipped %d bytes while syncing on next AC3 frame", skippedBytes - 4); + skippedBytes = SkippedBytesLimit; + } } int cDolbyRepacker::BreakAt(const uchar *Data, int Count) @@ -845,9 +962,13 @@ void cTS2PES::Clear(void) void cTS2PES::store(uint8_t *Data, int Count) { - int n = repacker ? repacker->Put(resultBuffer, Data, Count) : resultBuffer->Put(Data, Count); - if (n != Count) - esyslog("ERROR: result buffer overflow, dropped %d out of %d byte", Count - n, Count); + if (repacker) + repacker->Repack(resultBuffer, Data, Count); + else { + int n = resultBuffer->Put(Data, Count); + if (n != Count) + esyslog("ERROR: result buffer overflow, dropped %d out of %d byte", Count - n, Count); + } } void cTS2PES::reset_ipack(void) @@ -867,7 +988,7 @@ void cTS2PES::reset_ipack(void) void cTS2PES::send_ipack(void) { - if (count < 10) + if (count <= ((mpeg == 2) ? 9 : 7)) // skip empty packets return; buf[3] = (AUDIO_STREAM_S <= cid && cid <= AUDIO_STREAM_E && audioCid) ? audioCid : cid; buf[4] = (uint8_t)(((count - 6) & 0xFF00) >> 8); @@ -1155,7 +1276,7 @@ cRemux::cRemux(int VPid, const int *APids, const int *DPids, const int *SPids, b resultBuffer = new cRingBufferLinear(RESULTBUFFERSIZE, IPACKS, false, "Result"); resultBuffer->SetTimeouts(0, 100); if (VPid) -//#define TEST_cVideoRepacker +#define TEST_cVideoRepacker #ifdef TEST_cVideoRepacker ts2pes[numTracks++] = new cTS2PES(VPid, resultBuffer, IPACKS, 0x00, 0x00, new cVideoRepacker); #else @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: remux.h 1.13 2005/01/16 13:15:17 kls Exp $ + * $Id: remux.h 1.14 2005/08/07 10:28:07 kls Exp $ */ #ifndef __REMUX_H @@ -47,6 +47,12 @@ public: ///< PID). If ExitOnFailure is true, the remuxer will initiate an "emergency ///< exit" in case of problems with the data stream. ~cRemux(); + void SetTimeouts(int PutTimeout, int GetTimeout) { resultBuffer->SetTimeouts(PutTimeout, GetTimeout); } + ///< By default cRemux assumes that Put() and Get() are called from different + ///< threads, and uses a timeout in the Get() function in case there is no + ///< data available. SetTimeouts() can be used to modify these timeouts. + ///< Especially if Put() and Get() are called from the same thread, setting + ///< both timeouts to 0 is recommended. int Put(const uchar *Data, int Count); ///< Puts at most Count bytes of Data into the remuxer. ///< \return Returns the number of bytes actually consumed from Data. @@ -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.72 2005/05/26 09:59:09 kls Exp $ + * $Id: svdrp.c 1.74 2005/08/07 14:20:41 kls Exp $ */ #include "svdrp.h" @@ -209,7 +209,7 @@ const char *HelpPages[] = { " containing the given string as part of their name are listed.", "LSTE [ <channel> ] [ now | next | at <time> ]\n" " List EPG data. Without any parameters all data of all channels is\n" - " listed. If a channel is given (either by number of by channel ID),\n" + " listed. If a channel is given (either by number or by channel ID),\n" " only data for that channel is listed. 'now', 'next', or 'at <time>'\n" " restricts the returned data to present events, following events, or\n" " events at the given time (which must be in time_t form).", @@ -476,22 +476,26 @@ void cSVDRP::CmdDELC(const char *Option) { if (*Option) { if (isnumber(Option)) { - cChannel *channel = Channels.GetByNumber(strtol(Option, NULL, 10)); - if (channel) { - for (cTimer *timer = Timers.First(); timer; timer = Timers.Next(timer)) { - if (timer->Channel() == channel) { - Reply(550, "Channel \"%s\" is in use by timer %d", Option, timer->Index() + 1); - return; + if (!Channels.BeingEdited()) { + cChannel *channel = Channels.GetByNumber(strtol(Option, NULL, 10)); + if (channel) { + for (cTimer *timer = Timers.First(); timer; timer = Timers.Next(timer)) { + if (timer->Channel() == channel) { + Reply(550, "Channel \"%s\" is in use by timer %d", Option, timer->Index() + 1); + return; + } } - } - Channels.Del(channel); - Channels.ReNumber(); - Channels.SetModified(true); - isyslog("channel %s deleted", Option); - Reply(250, "Channel \"%s\" deleted", Option); + Channels.Del(channel); + Channels.ReNumber(); + Channels.SetModified(true); + isyslog("channel %s deleted", Option); + Reply(250, "Channel \"%s\" deleted", Option); + } + else + Reply(501, "Channel \"%s\" not defined", Option); } else - Reply(501, "Channel \"%s\" not defined", Option); + Reply(550, "Channels are being edited - try again later"); } else Reply(501, "Error in channel number \"%s\"", Option); @@ -532,19 +536,23 @@ void cSVDRP::CmdDELT(const char *Option) { if (*Option) { if (isnumber(Option)) { - cTimer *timer = Timers.Get(strtol(Option, NULL, 10) - 1); - if (timer) { - if (!timer->Recording()) { - isyslog("deleting timer %s", *timer->ToDescr()); - Timers.Del(timer); - Timers.SetModified(); - Reply(250, "Timer \"%s\" deleted", Option); + if (!Timers.BeingEdited()) { + cTimer *timer = Timers.Get(strtol(Option, NULL, 10) - 1); + if (timer) { + if (!timer->Recording()) { + isyslog("deleting timer %s", *timer->ToDescr()); + Timers.Del(timer); + Timers.SetModified(); + Reply(250, "Timer \"%s\" deleted", Option); + } + else + Reply(550, "Timer \"%s\" is recording", Option); } else - Reply(550, "Timer \"%s\" is recording", Option); + Reply(501, "Timer \"%s\" not defined", Option); } else - Reply(501, "Timer \"%s\" not defined", Option); + Reply(550, "Timers are being edited - try again later"); } else Reply(501, "Error in timer number \"%s\"", Option); @@ -782,18 +790,25 @@ void cSVDRP::CmdLSTE(const char *Option) p = strtok_r(NULL, delim, &strtok_next); } } - FILE *f = fdopen(file, "w"); - if (f) { - if (Schedule) - Schedule->Dump(f, "215-", DumpMode, AtTime); - else - Schedules->Dump(f, "215-", DumpMode, AtTime); - fflush(f); - Reply(215, "End of EPG data"); - // don't 'fclose(f)' here! + int fd = dup(file); + if (fd) { + FILE *f = fdopen(fd, "w"); + if (f) { + if (Schedule) + Schedule->Dump(f, "215-", DumpMode, AtTime); + else + Schedules->Dump(f, "215-", DumpMode, AtTime); + fflush(f); + Reply(215, "End of EPG data"); + fclose(f); + } + else { + Reply(451, "Can't open file connection"); + close(fd); + } } else - Reply(451, "Can't open file connection"); + Reply(451, "Can't dup stream descriptor"); } else Reply(451, "Can't get EPG data"); @@ -880,25 +895,29 @@ void cSVDRP::CmdMODC(const char *Option) int n = strtol(Option, &tail, 10); if (tail && tail != Option) { tail = skipspace(tail); - cChannel *channel = Channels.GetByNumber(n); - if (channel) { - cChannel ch; - if (ch.Parse(tail)) { - if (Channels.HasUniqueChannelID(&ch, channel)) { - *channel = ch; - Channels.ReNumber(); - Channels.SetModified(true); - isyslog("modifed channel %d %s", channel->Number(), *channel->ToText()); - Reply(250, "%d %s", channel->Number(), *channel->ToText()); + if (!Channels.BeingEdited()) { + cChannel *channel = Channels.GetByNumber(n); + if (channel) { + cChannel ch; + if (ch.Parse(tail)) { + if (Channels.HasUniqueChannelID(&ch, channel)) { + *channel = ch; + Channels.ReNumber(); + Channels.SetModified(true); + isyslog("modifed channel %d %s", channel->Number(), *channel->ToText()); + Reply(250, "%d %s", channel->Number(), *channel->ToText()); + } + else + Reply(501, "Channel settings are not unique"); } else - Reply(501, "Channel settings are not unique"); + Reply(501, "Error in channel settings"); } else - Reply(501, "Error in channel settings"); + Reply(501, "Channel \"%d\" not defined", n); } else - Reply(501, "Channel \"%d\" not defined", n); + Reply(550, "Channels are being edited - try again later"); } else Reply(501, "Error in channel number"); @@ -914,24 +933,28 @@ void cSVDRP::CmdMODT(const char *Option) int n = strtol(Option, &tail, 10); if (tail && tail != Option) { tail = skipspace(tail); - cTimer *timer = Timers.Get(n - 1); - if (timer) { - cTimer t = *timer; - if (strcasecmp(tail, "ON") == 0) - t.SetFlags(tfActive); - else if (strcasecmp(tail, "OFF") == 0) - t.ClrFlags(tfActive); - else if (!t.Parse(tail)) { - Reply(501, "Error in timer settings"); - return; + if (!Timers.BeingEdited()) { + cTimer *timer = Timers.Get(n - 1); + if (timer) { + cTimer t = *timer; + if (strcasecmp(tail, "ON") == 0) + t.SetFlags(tfActive); + else if (strcasecmp(tail, "OFF") == 0) + t.ClrFlags(tfActive); + else if (!t.Parse(tail)) { + Reply(501, "Error in timer settings"); + return; + } + *timer = t; + Timers.SetModified(); + isyslog("timer %s modified (%s)", *timer->ToDescr(), timer->HasFlags(tfActive) ? "active" : "inactive"); + Reply(250, "%d %s", timer->Index() + 1, *timer->ToText()); } - *timer = t; - Timers.SetModified(); - isyslog("timer %s modified (%s)", *timer->ToDescr(), timer->HasFlags(tfActive) ? "active" : "inactive"); - Reply(250, "%d %s", timer->Index() + 1, *timer->ToText()); + else + Reply(501, "Timer \"%d\" not defined", n); } else - Reply(501, "Timer \"%d\" not defined", n); + Reply(550, "Timers are being edited - try again later"); } else Reply(501, "Error in timer number"); @@ -1054,20 +1077,24 @@ void cSVDRP::CmdUPDT(const char *Option) if (*Option) { cTimer *timer = new cTimer; if (timer->Parse(Option)) { - cTimer *t = Timers.GetTimer(timer); - if (t) { - t->Parse(Option); - delete timer; - timer = t; - isyslog("timer %s updated", *timer->ToDescr()); - } - else { - Timers.Add(timer); - isyslog("timer %s added", *timer->ToDescr()); + if (!Timers.BeingEdited()) { + cTimer *t = Timers.GetTimer(timer); + if (t) { + t->Parse(Option); + delete timer; + timer = t; + isyslog("timer %s updated", *timer->ToDescr()); + } + else { + Timers.Add(timer); + isyslog("timer %s added", *timer->ToDescr()); + } + Timers.SetModified(); + Reply(250, "%d %s", timer->Index() + 1, *timer->ToText()); + return; } - Timers.SetModified(); - Reply(250, "%d %s", timer->Index() + 1, *timer->ToText()); - return; + else + Reply(550, "Timers are being edited - try again later"); } else Reply(501, "Error in timer settings"); @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: timers.c 1.33 2005/06/18 12:49:55 kls Exp $ + * $Id: timers.c 1.34 2005/07/30 13:03:51 kls Exp $ */ #include "timers.h" @@ -363,8 +363,6 @@ bool cTimer::Matches(time_t t, bool Directly) const if (HasFlags(tfActive)) { if (HasFlags(tfVps) && !Directly && event && event->Vps() && schedule && schedule->PresentSeenWithin(30)) { - if (startTime != event->Vps()) - return false; startTime = event->StartTime(); stopTime = event->EndTime(); return event->IsRunning(true); @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: tools.c 1.95 2005/05/29 10:18:26 kls Exp $ + * $Id: tools.c 1.96 2005/08/06 09:53:21 kls Exp $ */ #include "tools.h" @@ -308,7 +308,7 @@ bool MakeDirs(const char *FileName, bool IsDirectory) struct stat fs; if (stat(s, &fs) != 0 || !S_ISDIR(fs.st_mode)) { dsyslog("creating directory %s", s); - if (mkdir(s, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) == -1) { + if (mkdir(s, ACCESSPERMS) == -1) { LOG_ERROR_STR(s); result = false; break; @@ -451,7 +451,7 @@ bool SpinUpDisk(const char *FileName) if (access(buf, F_OK) != 0) { // the file does not exist timeval tp1, tp2; gettimeofday(&tp1, NULL); - int f = open(buf, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); + int f = open(buf, O_WRONLY | O_CREAT, DEFFILEMODE); // O_SYNC doesn't work on all file systems if (f >= 0) { if (fdatasync(f) < 0) @@ -843,7 +843,7 @@ bool cLockFile::Lock(int WaitSeconds) if (f < 0 && fileName) { time_t Timeout = time(NULL) + WaitSeconds; do { - f = open(fileName, O_WRONLY | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); + f = open(fileName, O_WRONLY | O_CREAT | O_EXCL, DEFFILEMODE); if (f < 0) { if (errno == EEXIST) { struct stat fs; @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: tools.h 1.72 2005/05/29 10:24:54 kls Exp $ + * $Id: tools.h 1.73 2005/08/06 09:53:21 kls Exp $ */ #ifndef __TOOLS_H @@ -158,7 +158,7 @@ public: cFile(void); ~cFile(); operator int () { return f; } - bool Open(const char *FileName, int Flags, mode_t Mode = S_IRUSR | S_IWUSR | S_IRGRP); + bool Open(const char *FileName, int Flags, mode_t Mode = DEFFILEMODE); bool Open(int FileDes); void Close(void); bool IsOpen(void) { return f >= 0; } @@ -8,7 +8,7 @@ .\" License as specified in the file COPYING that comes with the .\" vdr distribution. .\" -.\" $Id: vdr.1 1.13 2004/12/19 09:36:25 kls Exp $ +.\" $Id: vdr.1 1.14 2005/07/31 10:49:35 kls Exp $ .\" .TH vdr 1 "19 Dec 2004" "1.3.18" "Video Disk Recorder" .SH NAME @@ -46,7 +46,7 @@ Read config files from directory \fIdir\fR (default is to read them from the video directory). .TP .B \-d, \-\-daemon -Run in daemon mode. +Run in daemon mode (implies \-\-no\-kbd). .TP .BI \-D\ num ,\ \-\-device= num Use only the given DVB device (\fInum\fR = 0, 1, 2...). @@ -75,9 +75,16 @@ Search for plugins in directory \fIdir\fR (default is ./PLUGINS/lib). There can be several \fB\-L\fR options with different \fIdir\fR values. Each of them will apply to the \fB\-P\fR options following it. .TP +.BI \-\-lirc[= path ] +Use a LIRC remote control device. +If \fIpath\fR is omitted, vdr uses \fI/dev/lircd\fR. +.TP .B \-m, \-\-mute Mute audio of the primary DVB device at startup. .TP +.B \-\-no\-kbd +Don't use the keyboard as an input device. +.TP .BI \-p\ port ,\ \-\-port= port Use \fIport\fR for SVDRP. A value of \fB0\fR turns off SVDRP. The default SVDRP port is \fB2001\fR. @@ -101,6 +108,10 @@ particular options) you can use (note the quotes around the asterisk to prevent wildcard expansion). .TP +.BI \-\-rcu[= path ] +Use a serial port remote control device. +If \fIpath\fR is omitted, vdr uses \fI/dev/ttyS1\fR. +.TP .BI \-r\ cmd ,\ \-\-record= cmd Call \fIcmd\fR before and after a recording. .TP @@ -22,7 +22,7 @@ * * The project's page is at http://www.cadsoft.de/vdr * - * $Id: vdr.c 1.208 2005/06/18 11:19:07 kls Exp $ + * $Id: vdr.c 1.209 2005/07/31 11:25:16 kls Exp $ */ #include <getopt.h> @@ -115,6 +115,19 @@ int main(int argc, char *argv[]) int WatchdogTimeout = DEFAULTWATCHDOG; const char *Terminal = NULL; const char *Shutdown = NULL; + + bool UseKbd = true; + const char *LircDevice = NULL; + const char *RcuDevice = NULL; +#if !defined(REMOTE_KBD) + UseKbd = false; +#endif +#if defined(REMOTE_LIRC) + LircDevice = LIRC_DEVICE; +#elif defined(REMOTE_RCU) + RcuDevice = RCU_DEVICE; +#endif + cPluginManager PluginManager(DEFAULTPLUGINDIR); int ExitCode = 0; @@ -126,10 +139,13 @@ int main(int argc, char *argv[]) { "epgfile", required_argument, NULL, 'E' }, { "help", no_argument, NULL, 'h' }, { "lib", required_argument, NULL, 'L' }, + { "lirc", optional_argument, NULL, 'l' | 0x100 }, { "log", required_argument, NULL, 'l' }, { "mute", no_argument, NULL, 'm' }, + { "no-kbd", no_argument, NULL, 'n' | 0x100 }, { "plugin", required_argument, NULL, 'P' }, { "port", required_argument, NULL, 'p' }, + { "rcu", optional_argument, NULL, 'r' | 0x100 }, { "record", required_argument, NULL, 'r' }, { "shutdown", required_argument, NULL, 's' }, { "terminal", required_argument, NULL, 't' }, @@ -194,8 +210,14 @@ int main(int argc, char *argv[]) return 2; } break; + case 'l' | 0x100: + LircDevice = optarg ? : LIRC_DEVICE; + break; case 'm': MuteAudio = true; break; + case 'n' | 0x100: + UseKbd = false; + break; case 'p': if (isnumber(optarg)) SVDRPport = atoi(optarg); else { @@ -205,6 +227,9 @@ int main(int argc, char *argv[]) break; case 'P': PluginManager.AddPlugin(optarg); break; + case 'r' | 0x100: + RcuDevice = optarg ? : RCU_DEVICE; + break; case 'r': cRecordingUserCommand::SetCommand(optarg); break; case 's': Shutdown = optarg; @@ -261,10 +286,15 @@ int main(int argc, char *argv[]) " if logging should be done to LOG_LOCALn instead of\n" " LOG_USER, add '.n' to LEVEL, as in 3.7 (n=0..7)\n" " -L DIR, --lib=DIR search for plugins in DIR (default is %s)\n" + " --lirc[=PATH] use a LIRC remote control device, attached to PATH\n" + " (default: %s)\n" " -m, --mute mute audio of the primary DVB device at startup\n" + " --no-kbd don't use the keyboard as an input device\n" " -p PORT, --port=PORT use PORT for SVDRP (default: %d)\n" " 0 turns off SVDRP\n" " -P OPT, --plugin=OPT load a plugin defined by the given options\n" + " --rcu[=PATH] use a remote control device, attached to PATH\n" + " (default: %s)\n" " -r CMD, --record=CMD call CMD before and after a recording\n" " -s CMD, --shutdown=CMD call CMD to shutdown the computer\n" " -t TTY, --terminal=TTY controlling tty\n" @@ -275,7 +305,9 @@ int main(int argc, char *argv[]) "\n", DEFAULTEPGDATAFILENAME, DEFAULTPLUGINDIR, + LIRC_DEVICE, DEFAULTSVDRPPORT, + RCU_DEVICE, VideoDirectory, DEFAULTWATCHDOG ); @@ -470,15 +502,12 @@ int main(int argc, char *argv[]) cThemes::Load(Skins.Current()->Name(), Setup.OSDTheme, Skins.Current()->Theme()); // Remote Controls: -#if defined(REMOTE_RCU) - new cRcuRemote("/dev/ttyS1"); -#elif defined(REMOTE_LIRC) - new cLircRemote("/dev/lircd"); -#endif -#if defined(REMOTE_KBD) - if (!DaemonMode && HasStdin) + if (RcuDevice) + new cRcuRemote(RcuDevice); + if (LircDevice) + new cLircRemote(LircDevice); + if (!DaemonMode && HasStdin && UseKbd) new cKbdRemote; -#endif Interface->LearnKeys(); // External audio: @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: videodir.c 1.11 2004/12/26 11:52:12 kls Exp $ + * $Id: videodir.c 1.12 2005/08/06 09:53:21 kls Exp $ */ #include "videodir.h" @@ -137,7 +137,7 @@ int OpenVideoFile(const char *FileName, int Flags) } } } - int Result = open(ActualFileName, Flags, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); + int Result = open(ActualFileName, Flags, DEFFILEMODE); if (ActualFileName != FileName) free((char *)ActualFileName); return Result; |