summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKlaus Schmidinger <kls (at) cadsoft (dot) de>2005-03-20 18:00:00 +0100
committerKlaus Schmidinger <kls (at) cadsoft (dot) de>2005-03-20 18:00:00 +0100
commit782b517c51eaa6d2641fe9b6801afdad50be8586 (patch)
tree0d7b59865417ded6a8dfcb22b97ad2e32260982a
parent05402c740765e6e0ca2aaf1760c77d9e3d3ed5a5 (diff)
downloadvdr-patch-lnbsharing-782b517c51eaa6d2641fe9b6801afdad50be8586.tar.gz
vdr-patch-lnbsharing-782b517c51eaa6d2641fe9b6801afdad50be8586.tar.bz2
Version 1.3.23vdr-1.3.23
- The setup option "DVB/Video display format" is now only available if "Video format" is set to "4:3" (suggested by Mikko Salo). - Updated the Russian OSD texts (thanks to Vyacheslav Dikonov). - Dropped CA support for the old '-icam' firmware. - Updated the Finnish OSD texts (thanks to Rolf Ahrenberg). - Updated the Swedish OSD texts (thanks to Tomas Prybil). - Fixed a few French OSD texts that were in the wrong place. - Improved matching timers to EPG events, especially in case there are several events with the same VPS time. - Fixed cDolbyRepacker to allow recording ProSieben HD broadcasts (thanks to Reinhard Nissl). - Fixed cDvbDevice::SetVideoDisplayFormat() in case of 16:9 (thanks to Marco Schlüßler). - The running status of a VPS event is now only taken seriously if that event has been seen within the last 30 seconds - otherwise recording is done as if no VPS was available. - The day of a timer is now stored as a full date in ISO notation ("YYYY-MM-DD") in 'timers.conf' and for the result of the SVDRP command LSTT (based in parts on a patch by Roman Krenický). - Some fixes to avoid compiler warnings in gcc 4.0 (thanks to Ville Skyttä for reporting these). - Single shot timers are now reliably deleted when they have expired. - Fixed setting the colored button help after deleting a recording in case the next menu entry is a directory (thanks to Steffen Beyer). - Improved falling back to normal recording if the VPS data hasn't been seen for more than 30 seconds. - Added a missing cMutexLock to cRemote::HasKeys() (thanks to Wolfgang Rohdewald). - All log entries regarding timers now contain a short description of the timer.
-rw-r--r--CONTRIBUTORS15
-rw-r--r--HISTORY30
-rw-r--r--MANUAL18
-rw-r--r--channels.c11
-rw-r--r--channels.conf8
-rw-r--r--config.h6
-rw-r--r--dvbdevice.c21
-rw-r--r--eit.c4
-rw-r--r--epg.c5
-rw-r--r--epg.h7
-rw-r--r--font.h3
-rw-r--r--i18n.c90
-rw-r--r--menu.c75
-rw-r--r--menu.h5
-rw-r--r--menuitems.c202
-rw-r--r--menuitems.h20
-rw-r--r--remote.c3
-rw-r--r--remux.c46
-rw-r--r--svdrp.c15
-rw-r--r--timers.c309
-rw-r--r--timers.h50
-rw-r--r--tools.c4
-rw-r--r--tools.h4
-rw-r--r--vdr.514
-rw-r--r--vdr.c4
25 files changed, 555 insertions, 414 deletions
diff --git a/CONTRIBUTORS b/CONTRIBUTORS
index 52d5224..26d52c4 100644
--- a/CONTRIBUTORS
+++ b/CONTRIBUTORS
@@ -1281,6 +1281,7 @@ Wolfgang Rohdewald <wolfgang@rohdewald.de>
in cDevice::Shutdown()
for removing some unneeded code and fixing access to unallocated memory in
cEvent::FixEpgBugs()
+ for adding a missing cMutexLock to cRemote::HasKeys()
Chad Flynt <hoochster@sofnet.com>
for suggestions and experiments regarding the buffer reserve in cTransfer
@@ -1292,3 +1293,17 @@ Chris Warren <dvb@ixalon.net>
Luca Olivetti <luca@ventoso.org>
for making cDevice::AttachPlayer() keep the track language codes and descriptions
in Transfer Mode
+
+Mikko Salo <mikko.salo@ppe.inet.fi>
+ for suggesting to make the setup option "DVB/Video display format" available only
+ if "Video format" is set to "4:3"
+
+Roman Krenický <free-rtk@gmx.de>
+ for a patch that was used a a basis for changing a timer's day handling to full date
+
+Ville Skyttä <ville.skytta@iki.fi>
+ for reporting several compiler warnings in gcc 4.0
+
+Steffen Beyer <cpunk@reactor.de>
+ for fixing setting the colored button help after deleting a recording in case the next
+ menu entry is a directory
diff --git a/HISTORY b/HISTORY
index a8099c4..a5e8247 100644
--- a/HISTORY
+++ b/HISTORY
@@ -3443,3 +3443,33 @@ Video Disk Recorder Revision History
Luca Olivetti).
- Fixed handling repeated kAudio keys.
- Improved displaying the the current audio track in the ST:TNG channel display.
+
+2005-03-20: Version 1.3.23
+
+- The setup option "DVB/Video display format" is now only available if "Video format"
+ is set to "4:3" (suggested by Mikko Salo).
+- Updated the Russian OSD texts (thanks to Vyacheslav Dikonov).
+- Dropped CA support for the old '-icam' firmware.
+- Updated the Finnish OSD texts (thanks to Rolf Ahrenberg).
+- Updated the Swedish OSD texts (thanks to Tomas Prybil).
+- Fixed a few French OSD texts that were in the wrong place.
+- Improved matching timers to EPG events, especially in case there are several events
+ with the same VPS time.
+- Fixed cDolbyRepacker to allow recording ProSieben HD broadcasts (thanks to Reinhard
+ Nissl).
+- Fixed cDvbDevice::SetVideoDisplayFormat() in case of 16:9 (thanks to Marco Schlüßler).
+- The running status of a VPS event is now only taken seriously if that event has been
+ seen within the last 30 seconds - otherwise recording is done as if no VPS was
+ available.
+- The day of a timer is now stored as a full date in ISO notation ("YYYY-MM-DD") in
+ 'timers.conf' and for the result of the SVDRP command LSTT (based in parts on a
+ patch by Roman Krenický).
+- Some fixes to avoid compiler warnings in gcc 4.0 (thanks to Ville Skyttä for reporting
+ these).
+- Single shot timers are now reliably deleted when they have expired.
+- Fixed setting the colored button help after deleting a recording in case the next
+ menu entry is a directory (thanks to Steffen Beyer).
+- Improved falling back to normal recording if the VPS data hasn't been seen for more
+ than 30 seconds.
+- Added a missing cMutexLock to cRemote::HasKeys() (thanks to Wolfgang Rohdewald).
+- All log entries regarding timers now contain a short description of the timer.
diff --git a/MANUAL b/MANUAL
index e95b94f..ebf8ce0 100644
--- a/MANUAL
+++ b/MANUAL
@@ -381,10 +381,9 @@ Version 1.2
Any changes made in the "Channels" list (like renaming or
reordering channels) will be automatically reflected in the
timers settings.
- Day: The day on which this timer shall start. This can be either a
- "day of month" (1..31), which allows programming a "single shot"
- timer that hits once and is deleted after it ends. Single shot
- timers can be programmed up to one month into the future.
+ Day: The day on which this timer shall start. This can be a
+ date (like 2005-03-19), which allows programming a "single shot"
+ timer that hits once and is deleted after it ends.
Another option here are "repeating timers" which are defined
by listing the days of the week on which they shall record.
For example, a timer that shall record every monday and wednesday
@@ -392,6 +391,9 @@ Version 1.2
The '0' key toggles between a single shot and a repeating timer.
If "Day" indicates a repeating timer, the keys '1'...'7' can be
used to toggle the individual days ('1' is monday).
+ You can also switch to a set of predefined repeating timer settings
+ by pressing the "Left" key when the day is the present day. To return
+ to the single shot mode just press "Right" until a date is displayed.
Start: The start time of the timer in hh:mm as 24 hour ("military") time.
Stop: The stop time of the timer.
VPS: Defines whether the timer shall use VPS (if available). If this
@@ -588,12 +590,14 @@ Version 1.2
from the primary DVB interface, so that the viewer will
be disturbed as little as possible.
+ Video format = 4:3 The video format (or aspect ratio) of the tv set in use
+ (4:3 or 16:9).
+
Video display format = letterbox
The display format to use for playing wide screen video on
a 4:3 tv set ("pan & scan", "letterbox" or "center cut out").
-
- Video format = 4:3 The video format (or aspect ratio) of the tv set in use
- (4:3 or 16:9).
+ This option is only available if "Video format" is set to
+ 4:3.
Use Dolby Digital = yes
Turns recording of the Dolby Digital audio channels on
diff --git a/channels.c b/channels.c
index dd230da..3392d9a 100644
--- a/channels.c
+++ b/channels.c
@@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
- * $Id: channels.c 1.35 2005/02/06 09:44:53 kls Exp $
+ * $Id: channels.c 1.36 2005/03/19 15:56:38 kls Exp $
*/
#include "channels.h"
@@ -694,9 +694,12 @@ bool cChannel::Parse(const char *s, bool AllowNonUniqueID)
char *p = strchr(vpidbuf, '+');
if (p)
*p++ = 0;
- sscanf(vpidbuf, "%d", &vpid);
- if (p)
- sscanf(p, "%d", &ppid);
+ if (sscanf(vpidbuf, "%d", &vpid) != 1)
+ return false;
+ if (p) {
+ if (sscanf(p, "%d", &ppid) != 1)
+ return false;
+ }
else
ppid = vpid;
diff --git a/channels.conf b/channels.conf
index e0fc70f..21763de 100644
--- a/channels.conf
+++ b/channels.conf
@@ -48,7 +48,7 @@ PREMIERE 1,PREM 1;PREMIERE:11797:hC34:S19.2E:27500:511:512=deu,513=deu;515=deu:3
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 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:32:1801,1722,1702:29: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
DISNEY CHANNEL,DISNEY;PREMIERE:11758:hC34:S19.2E:27500:2559:2560=deu:0:1722,1801,1702:34:133:17:0
@@ -90,9 +90,9 @@ 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:2305+2304:2306=eng:2307:960,961:4705:2:2027:0
Sky Mix;BSkyB:12226:hC23:S28.2E:27500:2314+2304:2315=eng,2316=NAR:2317:960,961:5104:2:2027:0
-ITV2;BSkyB:10906:vC56:S28.2E:22000:2350:2351=eng,2352=eng:2353:960,961:10240:2:2054:0
-Sci-Fi;BSkyB:12148:hC23:S28.2E:27500:2314+2304:2315=eng:2316:960,961:4905:2:2023:0
-Paramount;BSkyB:12187:hC23:S28.2E:27500:2313+2304:2314=eng:2315:960,961:5904:2:2025:0
+ITV2;BSkyB:10906:vC56:S28.2E:22000:2350:2351=eng:2353:960,961:10240:2:2054:0
+Sci-Fi;BSkyB:12148:hC23:S28.2E:27500:2320+2304:2321=eng:2322: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
Sky Movies 1;BSkyB:11836:hC23:S28.2E:27500:518+8190:646=eng,653=NAR;686=eng:582:960,961:4303:2:2007:0
Sky Movies 2;BSkyB:11836:hC23:S28.2E:27500:519+8190:647=eng,667=NAR;687=eng:583:960,961:4302:2:2007:0
diff --git a/config.h b/config.h
index a94f906..833022e 100644
--- a/config.h
+++ b/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.215 2005/02/20 12:50:37 kls Exp $
+ * $Id: config.h 1.216 2005/03/05 15:44:35 kls Exp $
*/
#ifndef __CONFIG_H
@@ -20,8 +20,8 @@
#include "i18n.h"
#include "tools.h"
-#define VDRVERSION "1.3.22"
-#define VDRVERSNUM 10322 // Version * 10000 + Major * 100 + Minor
+#define VDRVERSION "1.3.23"
+#define VDRVERSNUM 10323 // Version * 10000 + Major * 100 + Minor
#define MAXPRIORITY 99
#define MAXLIFETIME 99
diff --git a/dvbdevice.c b/dvbdevice.c
index c231122..9c8a0ac 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.124 2005/02/20 13:35:28 kls Exp $
+ * $Id: dvbdevice.c 1.127 2005/03/20 10:10:38 kls Exp $
*/
#include "dvbdevice.h"
@@ -577,7 +577,7 @@ bool cDvbDevice::GrabImage(const char *FileName, bool Jpeg, int Quality, int Siz
else {
// write PNM file:
if (fprintf(f, "P6\n%d\n%d\n255\n", vm.width, vm.height) < 0 ||
- fwrite(mem, vm.width * vm.height * 3, 1, f) < 0) {
+ fwrite(mem, vm.width * vm.height * 3, 1, f) != 1) {
LOG_ERROR_STR(FileName);
result |= 1;
}
@@ -604,7 +604,7 @@ void cDvbDevice::SetVideoDisplayFormat(eVideoDisplayFormat VideoDisplayFormat)
cDevice::SetVideoDisplayFormat(VideoDisplayFormat);
if (HasDecoder()) {
if (Setup.VideoFormat) {
- CHECK(ioctl(fd_video, VIDEO_SET_DISPLAY_FORMAT, VIDEO_CENTER_CUT_OUT));
+ CHECK(ioctl(fd_video, VIDEO_SET_DISPLAY_FORMAT, VIDEO_LETTER_BOX));
}
else {
switch (VideoDisplayFormat) {
@@ -757,8 +757,7 @@ bool cDvbDevice::ProvidesChannel(const cChannel *Channel, int Priority, bool *Ne
if (Channel->Vpid() && !HasPid(Channel->Vpid()) || Channel->Apid(0) && !HasPid(Channel->Apid(0))) {
#ifdef DO_MULTIPLE_RECORDINGS
if (Ca() > CACONFBASE || Channel->Ca() > CACONFBASE)
- needsDetachReceivers = !ciHandler // only LL-firmware can do non-live CA channels
- || Ca() != Channel->Ca();
+ needsDetachReceivers = Ca() != Channel->Ca();
else if (!IsPrimaryDevice())
result = true;
#ifdef DO_REC_AND_PLAY_ON_PRIMARY_DEVICE
@@ -781,27 +780,21 @@ bool cDvbDevice::ProvidesChannel(const cChannel *Channel, int Priority, bool *Ne
bool cDvbDevice::SetChannelDevice(const cChannel *Channel, bool LiveView)
{
- bool IsEncrypted = Channel->Ca() > CACONFBASE && !ciHandler; // only LL-firmware can do non-live CA channels
-
bool DoTune = !dvbTuner->IsTunedTo(Channel);
bool TurnOffLivePIDs = HasDecoder()
&& (DoTune
- || IsEncrypted && pidHandles[ptVideo].pid != Channel->Vpid() // CA channels can only be decrypted in "live" mode
|| !IsPrimaryDevice()
|| LiveView // for a new live view the old PIDs need to be turned off
|| pidHandles[ptVideo].pid == Channel->Vpid() // for recording the PIDs must be shifted from DMX_PES_AUDIO/VIDEO to DMX_PES_OTHER
);
- bool StartTransferMode = IsPrimaryDevice() && !IsEncrypted && !DoTune
+ bool StartTransferMode = IsPrimaryDevice() && !DoTune
&& (LiveView && HasPid(Channel->Vpid() ? Channel->Vpid() : Channel->Apid(0)) && (pidHandles[ptVideo].pid != Channel->Vpid() || pidHandles[ptAudio].pid != Channel->Apid(0))// the PID is already set as DMX_PES_OTHER
|| !LiveView && (pidHandles[ptVideo].pid == Channel->Vpid() || pidHandles[ptAudio].pid == Channel->Apid(0)) // a recording is going to shift the PIDs from DMX_PES_AUDIO/VIDEO to DMX_PES_OTHER
);
- bool TurnOnLivePIDs = HasDecoder() && !StartTransferMode
- && (IsEncrypted // CA channels can only be decrypted in "live" mode
- || LiveView
- );
+ bool TurnOnLivePIDs = HasDecoder() && !StartTransferMode && LiveView;
#ifndef DO_MULTIPLE_RECORDINGS
TurnOffLivePIDs = TurnOnLivePIDs = true;
@@ -919,7 +912,7 @@ bool cDvbDevice::CanReplay(void) const
if (Receiving())
return false;
#endif
- return cDevice::CanReplay() && (Ca() <= MAXDEVICES || ciHandler); // with non-LL-firmware we can only replay if there is no CA recording going on
+ return cDevice::CanReplay();
}
bool cDvbDevice::SetPlayMode(ePlayMode PlayMode)
diff --git a/eit.c b/eit.c
index a7d60c4..6c6381b 100644
--- a/eit.c
+++ b/eit.c
@@ -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.102 2005/01/02 11:52:12 kls Exp $
+ * $Id: eit.c 1.103 2005/03/20 12:33:51 kls Exp $
*/
#include "eit.h"
@@ -246,6 +246,8 @@ cEIT::cEIT(cSchedules *Schedules, int Source, u_char Tid, const u_char *Data)
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 (Tid == 0x4E)
+ pSchedule->SetPresentSeen();
if (Modified) {
pSchedule->Sort();
Schedules->SetModified(pSchedule);
diff --git a/epg.c b/epg.c
index df267f6..7b0fcd9 100644
--- a/epg.c
+++ b/epg.c
@@ -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.25 2005/02/19 11:35:00 kls Exp $
+ * $Id: epg.c 1.27 2005/03/20 12:34:19 kls Exp $
*/
#include "epg.h"
@@ -645,6 +645,7 @@ cSchedule::cSchedule(tChannelID ChannelID)
channelID = ChannelID;
hasRunning = false;;
modified = 0;
+ presentSeen = 0;
}
cEvent *cSchedule::AddEvent(cEvent *Event)
@@ -663,7 +664,7 @@ const cEvent *cSchedule::GetPresentEvent(bool CheckRunningStatus) const
if (!CheckRunningStatus)
break;
}
- if (CheckRunningStatus && time(NULL) - p->Seen() < 30 && p->RunningStatus() >= SI::RunningStatusPausing)
+ if (CheckRunningStatus && p->SeenWithin(30) && p->RunningStatus() >= SI::RunningStatusPausing)
return p;
}
return pe;
diff --git a/epg.h b/epg.h
index 88e6602..6668a61 100644
--- a/epg.h
+++ b/epg.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.h 1.19 2005/01/02 10:44:41 kls Exp $
+ * $Id: epg.h 1.21 2005/03/20 12:32:36 kls Exp $
*/
#ifndef __EPG_H
@@ -79,6 +79,7 @@ public:
int Duration(void) const { return duration; }
time_t Vps(void) const { return vps; }
time_t Seen(void) const { return seen; }
+ bool SeenWithin(int Seconds) const { return time(NULL) - seen < Seconds; }
bool HasTimer(void) const;
bool IsRunning(bool OrAboutToStart = false) const;
cString GetDateString(void) const;
@@ -110,11 +111,15 @@ private:
cList<cEvent> events;
bool hasRunning;
time_t modified;
+ time_t presentSeen;
public:
cSchedule(tChannelID ChannelID);
tChannelID ChannelID(void) const { return channelID; }
time_t Modified(void) const { return modified; }
+ time_t PresentSeen(void) const { return presentSeen; }
+ bool PresentSeenWithin(int Seconds) const { return time(NULL) - presentSeen < Seconds; }
void SetModified(void) { modified = time(NULL); }
+ void SetPresentSeen(void) { presentSeen = time(NULL); }
void SetRunningStatus(cEvent *Event, int RunningStatus, cChannel *Channel = NULL);
void ClrRunningStatus(cChannel *Channel = NULL);
void ResetVersions(void);
diff --git a/font.h b/font.h
index 012f6c5..b5a21a3 100644
--- a/font.h
+++ b/font.h
@@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
- * $Id: font.h 1.10 2005/01/14 13:25:35 kls Exp $
+ * $Id: font.h 1.11 2005/03/19 15:51:19 kls Exp $
*/
#ifndef __FONT_H
@@ -44,6 +44,7 @@ private:
int height;
public:
cFont(void *Data);
+ virtual ~cFont() {}
void SetData(void *Data);
virtual int Width(unsigned char c) const { return data[c]->width; }
///< Returns the width of the given character.
diff --git a/i18n.c b/i18n.c
index a265cd0..5721666 100644
--- a/i18n.c
+++ b/i18n.c
@@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
- * $Id: i18n.c 1.181 2005/02/27 09:45:57 kls Exp $
+ * $Id: i18n.c 1.185 2005/03/12 10:43:16 kls Exp $
*
* Translations provided by:
*
@@ -958,7 +958,7 @@ const tI18nPhrase Phrases[] = {
"",//TODO
"",//TODO
"",//TODO
- "",//TODO
+ "Skanna",
"Cãutare canale",
"",//TODO
"",//TODO
@@ -1801,7 +1801,7 @@ const tI18nPhrase Phrases[] = {
"",// TODO
"",// TODO
"",// TODO
- "",// TODO
+ "VPS",
"VPS",
"",// TODO
"",// TODO
@@ -2301,16 +2301,16 @@ const tI18nPhrase Phrases[] = {
"Geen audio beschikbaar!",
"",//TODO
"",//TODO
- "",//TODO
+ "Pas d'audio disponible!",
"Äänen kieli ei ole valittavissa!",
"",//TODO
"",//TODO
"",//TODO
- "Pas d'audio disponible!",
- "",//TODO
+ "Ljud saknas!"
"",//TODO
"",//TODO
"",//TODO
+ "¾âáãâáâÒãÕâ ×ÒãÚ!",
"",//TODO
"Audio kättesaamatu!",
"Ingen lyd tilgængelig!",
@@ -2581,7 +2581,7 @@ const tI18nPhrase Phrases[] = {
"",// TODO
"",// TODO
"",// TODO
- "",// TODO
+ "Skin",
"Skin",
"",// TODO
"",// TODO
@@ -2602,7 +2602,7 @@ const tI18nPhrase Phrases[] = {
"",// TODO
"",// TODO
"",// TODO
- "",// TODO
+ "Tema",
"Temã",
"",// TODO
"",// TODO
@@ -2623,7 +2623,7 @@ const tI18nPhrase Phrases[] = {
"",// TODO
"",// TODO
"",// TODO
- "",// TODO
+ "Vänster",
"Stânga",
"",// TODO
"",// TODO
@@ -2644,7 +2644,7 @@ const tI18nPhrase Phrases[] = {
"",// TODO
"",// TODO
"",// TODO
- "",// TODO
+ "Övre",
"Sus",
"",// TODO
"",// TODO
@@ -2728,7 +2728,7 @@ const tI18nPhrase Phrases[] = {
"",// TODO
"",// TODO
"",// TODO
- "",// TODO
+ "Använd liten font",
"Utilizare fonturi mici",
"",// TODO
"",// TODO
@@ -2749,7 +2749,7 @@ const tI18nPhrase Phrases[] = {
"",// TODO
"",// TODO
"",// TODO
- "",// TODO
+ "aldrig",
"niciodatã",
"",// TODO
"",// TODO
@@ -2770,7 +2770,7 @@ const tI18nPhrase Phrases[] = {
"",// TODO
"",// TODO
"",// TODO
- "",// TODO
+ "skin beroende",
"dep. de skin",
"",// TODO
"",// TODO
@@ -2791,7 +2791,7 @@ const tI18nPhrase Phrases[] = {
"",// TODO
"",// TODO
"",// TODO
- "",// TODO
+ "alltid",
"întotdeauna",
"",// TODO
"",// TODO
@@ -2833,11 +2833,11 @@ const tI18nPhrase Phrases[] = {
"",// TODO
"",// TODO
"",// TODO
+ "Kanal information (s)",
"",// TODO
"",// TODO
"",// TODO
- "",// TODO
- "",// TODO
+ "¿ÞÚÐ× ØÝäÞàÜÐæØØ Þ ÚÐÝÐÛÕ (áÕÚ)",
"",// TODO
"",// TODO
"Tid kanalinfo skal vises (s)",
@@ -3043,11 +3043,11 @@ const tI18nPhrase Phrases[] = {
"",// TODO
"",// TODO
"",// TODO
- "",// TODO
+ "Önskade språk",
"Limbi preferate",
"",// TODO
"",// TODO
- "¿àÕÔßÞçØâÐÕÜëÕ ï×ëÚØ",
+ "¿àÕÔßÞçØâÐÕÜëÕ ï×ëÚØ (âÕÛÕÓØÔ)",
"Preferirani jezici",
"Eelistatuid keeli",
"Foretrukne sprog",
@@ -3064,7 +3064,7 @@ const tI18nPhrase Phrases[] = {
"",// TODO
"",// TODO
"",// TODO
- "",// TODO
+ "Önskat språk",
"Limba preferatã",
"",// TODO
"",// TODO
@@ -3102,15 +3102,15 @@ const tI18nPhrase Phrases[] = {
"",//TODO
"",//TODO
"",//TODO
+ "Näyttömuoto",
"",//TODO
"",//TODO
"",//TODO
+ "Format för Video display",
"",//TODO
"",//TODO
"",//TODO
- "",//TODO
- "",//TODO
- "",//TODO
+ "ÈØàÞÚÞíÚàÐÝÝÞÕ Ø×ÞÑàÐÖÕÝØÕ",
"",//TODO
"",//TODO
"",//TODO
@@ -3131,7 +3131,7 @@ const tI18nPhrase Phrases[] = {
"pan&scan",
"pan&scan",
"pan&scan",
- "pan&scan",
+ "ßÐÝÞàÐÜØàÞÒÐâì",
"pan&scan",
"pan&scan",
"pan&scan",
@@ -3152,7 +3152,7 @@ const tI18nPhrase Phrases[] = {
"letterbox",
"letterbox",
"letterbox",
- "letterbox",
+ "ãÜÕÝìèÐâì",
"letterbox",
"letterbox",
"letterbox",
@@ -3173,7 +3173,7 @@ const tI18nPhrase Phrases[] = {
"center cut out",
"center cut out",
"center cut out",
- "center cut out",
+ "ÞÑàÕ×Ðâì áÑÞÚã",
"center cut out",
"center cut out",
"center cut out",
@@ -3205,17 +3205,17 @@ const tI18nPhrase Phrases[] = {
"",//TODO
"Dolby Digital gebruiken",
"",//TODO
- "",//TODO
+ "Utiliser le Dolby Digital",
"",//TODO
"Käytä Dolby Digital -ääntä",
"",//TODO
"",//TODO
"",//TODO
- "Utiliser le Dolby Digital",
- "",//TODO
+ "Använd Dolby Digital",
"",//TODO
"",//TODO
"",//TODO
+ "²ÚÛîçØâì Dolby Digital",
"",//TODO
"Dolby Digital kasutamine",
"Anvend Dolby Digital",
@@ -3232,7 +3232,7 @@ const tI18nPhrase Phrases[] = {
"",// TODO
"",// TODO
"",// TODO
- "",// TODO
+ "Uppdatera kanaler",
"Actualizare canale",
"",// TODO
"",// TODO
@@ -3253,7 +3253,7 @@ const tI18nPhrase Phrases[] = {
"",// TODO
"",// TODO
"",// TODO
- "",// TODO
+ "bara namn",
"doar numele",
"",// TODO
"",// TODO
@@ -3274,7 +3274,7 @@ const tI18nPhrase Phrases[] = {
"",// TODO
"",// TODO
"",// TODO
- "",// TODO
+ "namn och PIDdar",
"nume si PID-uri",
"",// TODO
"",// TODO
@@ -3295,7 +3295,7 @@ const tI18nPhrase Phrases[] = {
"",// TODO
"",// TODO
"",// TODO
- "",// TODO
+ "lägg till nya kanaler",
"adãugare canale noi",
"",// TODO
"",// TODO
@@ -3316,7 +3316,7 @@ const tI18nPhrase Phrases[] = {
"",// TODO
"",// TODO
"",// TODO
- "",// TODO
+ "lägg till nya transponders",
"adãugare transpondere noi",
"",// TODO
"",// TODO
@@ -3337,11 +3337,11 @@ const tI18nPhrase Phrases[] = {
"",//TODO
"",//TODO
"",//TODO
+ "Antal ljudspråk",
"",//TODO
"",//TODO
"",//TODO
- "",//TODO
- "",//TODO
+ "¿àÕÔßÞçØâÐÕÜëÕ ï×ëÚØ (×ÒãÚ)",
"",//TODO
"",//TODO
"Audio sprog (ant.)",
@@ -3358,11 +3358,11 @@ const tI18nPhrase Phrases[] = {
"",//TODO
"",//TODO
"",//TODO
+ "Ljudspråk",
"",//TODO
"",//TODO
"",//TODO
- "",//TODO
- "",//TODO
+ "²ëÑàÐÝ",
"",//TODO
"",//TODO
"Audio sprog",
@@ -3652,7 +3652,7 @@ const tI18nPhrase Phrases[] = {
"",// TODO
"",// TODO
"",// TODO
- "",// TODO
+ "Använd VPS",
"Utilizeazã VPS",
"",// TODO
"",// TODO
@@ -3673,7 +3673,7 @@ const tI18nPhrase Phrases[] = {
"",// TODO
"",// TODO
"",// TODO
- "",// TODO
+ "VPS marginal (s)",
"Marjã de timp la utilizare VPS (s)",
"",// TODO
"",// TODO
@@ -3925,7 +3925,7 @@ const tI18nPhrase Phrases[] = {
"",// TODO
"",// TODO
"ÆÜðéíãê äéáêïðÞ (ä)",
- "",// TODO
+ "Zap timeout(s)",
"Interval zapping (s)",
"",// TODO
"",// TODO
@@ -4784,17 +4784,17 @@ const tI18nPhrase Phrases[] = {
"",// TODO
"Audio",
"",// TODO
- "",// TODO
+ "Audio",
"",// TODO
"Ääni",
"",// TODO
"",// TODO
"",// TODO
- "Audio",
- "",// TODO
+ "Ljud",
"",// TODO
"",// TODO
"",// TODO
+ "Ï×ëÚ",
"",// TODO
"Audio",
"Audio",
@@ -5274,7 +5274,7 @@ const tI18nPhrase Phrases[] = {
"",// TODO
"",// TODO
"",// TODO
- "",// TODO
+ "Klassisk VDR",
"VDR clasic",
"",// TODO
"",// TODO
@@ -5295,7 +5295,7 @@ const tI18nPhrase Phrases[] = {
"",// TODO
"",// TODO
"",// TODO
- "",// TODO
+ "ST:TNG konsol",
"Cons. ST:TNG",
"",// TODO
"",// TODO
diff --git a/menu.c b/menu.c
index e316863..30183df 100644
--- a/menu.c
+++ b/menu.c
@@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
- * $Id: menu.c 1.342 2005/02/27 14:09:00 kls Exp $
+ * $Id: menu.c 1.348 2005/03/20 15:14:51 kls Exp $
*/
#include "menu.h"
@@ -632,7 +632,7 @@ cMenuEditTimer::cMenuEditTimer(cTimer *Timer, bool New)
channel = data.Channel()->Number();
Add(new cMenuEditBitItem( tr("Active"), &data.flags, tfActive));
Add(new cMenuEditChanItem(tr("Channel"), &channel));
- Add(new cMenuEditDayItem( tr("Day"), &data.day));
+ Add(new cMenuEditDateItem(tr("Day"), &data.day, &data.weekdays));
Add(new cMenuEditTimeItem(tr("Start"), &data.start));
Add(new cMenuEditTimeItem(tr("Stop"), &data.stop));
Add(new cMenuEditBitItem( tr("VPS"), &data.flags, tfVps));
@@ -654,13 +654,12 @@ cMenuEditTimer::~cMenuEditTimer()
void cMenuEditTimer::SetFirstDayItem(void)
{
if (!firstday && !data.IsSingleEvent()) {
- Add(firstday = new cMenuEditDateItem(tr("First day"), &data.firstday));
+ Add(firstday = new cMenuEditDateItem(tr("First day"), &data.day));
Display();
}
else if (firstday && data.IsSingleEvent()) {
Del(firstday->Index());
firstday = NULL;
- data.firstday = 0;
Display();
}
}
@@ -691,7 +690,7 @@ eOSState cMenuEditTimer::ProcessKey(eKeys Key)
Timers.Add(timer);
timer->Matches();
Timers.SetModified();
- isyslog("timer %d %s (%s)", timer->Index() + 1, addIfConfirmed ? "added" : "modified", timer->HasFlags(tfActive) ? "active" : "inactive");
+ isyslog("timer %s %s (%s)", *timer->ToDescr(), addIfConfirmed ? "added" : "modified", timer->HasFlags(tfActive) ? "active" : "inactive");
addIfConfirmed = false;
}
}
@@ -733,13 +732,28 @@ int cMenuTimerItem::Compare(const cListObject &ListObject) const
void cMenuTimerItem::Set(void)
{
+ cString day, name("");
+ if (timer->WeekDays())
+ day = timer->PrintDay(0, timer->WeekDays());
+ else if (timer->Day() - time(NULL) < 28 * SECSINDAY) {
+ day = itoa(timer->GetMDay(timer->Day()));
+ name = WeekDayName(timer->Day());
+ }
+ else {
+ struct tm tm_r;
+ time_t Day = timer->Day();
+ localtime_r(&Day, &tm_r);
+ char buffer[16];
+ strftime(buffer, sizeof(buffer), "%Y%m%d", &tm_r);
+ day = buffer;
+ }
char *buffer = NULL;
asprintf(&buffer, "%c\t%d\t%s%s%s\t%02d:%02d\t%02d:%02d\t%s",
!(timer->HasFlags(tfActive)) ? ' ' : timer->FirstDay() ? '!' : timer->Recording() ? '#' : '>',
timer->Channel()->Number(),
- timer->IsSingleEvent() ? *WeekDayName(timer->StartTime()) : "",
- timer->IsSingleEvent() ? " " : "",
- *timer->PrintDay(timer->Day()),
+ *name,
+ *name && **name ? " " : "",
+ *day,
timer->Start() / 100,
timer->Start() % 100,
timer->Stop() / 100,
@@ -795,9 +809,9 @@ eOSState cMenuTimers::OnOff(void)
RefreshCurrent();
DisplayCurrent(true);
if (timer->FirstDay())
- isyslog("timer %d first day set to %s", timer->Index() + 1, *timer->PrintFirstDay());
+ isyslog("timer %s first day set to %s", *timer->ToDescr(), *timer->PrintFirstDay());
else
- isyslog("timer %d %sactivated", timer->Index() + 1, timer->HasFlags(tfActive) ? "" : "de");
+ isyslog("timer %s %sactivated", *timer->ToDescr(), timer->HasFlags(tfActive) ? "" : "de");
Timers.SetModified();
}
return osContinue;
@@ -807,7 +821,7 @@ eOSState cMenuTimers::Edit(void)
{
if (HasSubMenu() || Count() == 0)
return osContinue;
- isyslog("editing timer %d", CurrentTimer()->Index() + 1);
+ isyslog("editing timer %s", *CurrentTimer()->ToDescr());
return AddSubMenu(new cMenuEditTimer(CurrentTimer()));
}
@@ -832,12 +846,11 @@ eOSState cMenuTimers::Delete(void)
else
return osContinue;
}
- int Index = ti->Index();
+ isyslog("deleting timer %s", *ti->ToDescr());
Timers.Del(ti);
cOsdMenu::Del(Current());
Timers.SetModified();
Display();
- isyslog("timer %d deleted", Index + 1);
}
}
return osContinue;
@@ -1603,9 +1616,8 @@ eOSState cMenuRecordings::Delete(void)
timer->Skip();
cRecordControls::Process(time(NULL));
if (timer->IsSingleEvent()) {
- int Index = timer->Index();
+ isyslog("deleting timer %s", *timer->ToDescr());
Timers.Del(timer);
- isyslog("timer %d deleted", Index + 1);
}
Timers.SetModified();
}
@@ -1619,6 +1631,7 @@ eOSState cMenuRecordings::Delete(void)
cReplayControl::ClearLastReplayed(ri->FileName());
cOsdMenu::Del(Current());
Recordings.Del(recording);
+ SetHelpKeys();
Display();
if (!Count())
return osBack;
@@ -1947,8 +1960,9 @@ void cMenuSetupDVB::Setup(void)
Clear();
Add(new cMenuEditIntItem( tr("Setup.DVB$Primary DVB interface"), &data.PrimaryDVB, 1, cDevice::NumDevices()));
- Add(new cMenuEditStraItem(tr("Setup.DVB$Video display format"), &data.VideoDisplayFormat, 3, videoDisplayFormatTexts));
Add(new cMenuEditBoolItem(tr("Setup.DVB$Video format"), &data.VideoFormat, "4:3", "16:9"));
+ if (data.VideoFormat == 0)
+ Add(new cMenuEditStraItem(tr("Setup.DVB$Video display format"), &data.VideoDisplayFormat, 3, videoDisplayFormatTexts));
Add(new cMenuEditBoolItem(tr("Setup.DVB$Use Dolby Digital"), &data.UseDolbyDigital));
Add(new cMenuEditStraItem(tr("Setup.DVB$Update channels"), &data.UpdateChannels, 5, updateChannelsTexts));
Add(new cMenuEditIntItem( tr("Setup.DVB$Audio languages"), &numAudioLanguages, 0, I18nNumLanguages));
@@ -1964,10 +1978,12 @@ eOSState cMenuSetupDVB::ProcessKey(eKeys Key)
int oldPrimaryDVB = ::Setup.PrimaryDVB;
int oldVideoDisplayFormat = ::Setup.VideoDisplayFormat;
bool oldVideoFormat = ::Setup.VideoFormat;
+ bool newVideoFormat = data.VideoFormat;
int oldnumAudioLanguages = numAudioLanguages;
eOSState state = cMenuSetupBase::ProcessKey(Key);
if (Key != kNone) {
+ bool DoSetup = data.VideoFormat != newVideoFormat;
if (numAudioLanguages != oldnumAudioLanguages) {
for (int i = oldnumAudioLanguages; i < numAudioLanguages; i++) {
data.AudioLanguages[i] = 0;
@@ -1984,8 +2000,10 @@ eOSState cMenuSetupDVB::ProcessKey(eKeys Key)
}
}
data.AudioLanguages[numAudioLanguages] = -1;
- Setup();
+ DoSetup = true;
}
+ if (DoSetup)
+ Setup();
}
if (state == osBack && Key == kOk) {
if (::Setup.PrimaryDVB != oldPrimaryDVB)
@@ -3048,7 +3066,7 @@ cRecordControl::cRecordControl(cDevice *Device, cTimer *Timer, bool Pause)
cRecordControl::~cRecordControl()
{
- Stop(true);
+ Stop();
free(instantId);
free(fileName);
}
@@ -3083,16 +3101,11 @@ bool cRecordControl::GetEvent(void)
return false;
}
-void cRecordControl::Stop(bool KeepInstant)
+void cRecordControl::Stop(void)
{
if (timer) {
DELETENULL(recorder);
timer->SetRecording(false);
- if ((IsInstant() && !KeepInstant) || (timer->IsSingleEvent() && timer->StopTime() <= time(NULL))) {
- isyslog("deleting timer %d", timer->Index() + 1);
- Timers.Del(timer);
- Timers.SetModified();
- }
timer = NULL;
cStatus::MsgRecording(device, NULL);
cRecordingUserCommand::InvokeCommand(RUC_AFTERRECORDING, fileName);
@@ -3153,8 +3166,16 @@ void cRecordControls::Stop(const char *InstantId)
for (int i = 0; i < MAXRECORDCONTROLS; i++) {
if (RecordControls[i]) {
const char *id = RecordControls[i]->InstantId();
- if (id && strcmp(id, InstantId) == 0)
+ if (id && strcmp(id, InstantId) == 0) {
+ cTimer *timer = RecordControls[i]->Timer();
RecordControls[i]->Stop();
+ if (timer) {
+ isyslog("deleting timer %s", *timer->ToDescr());
+ Timers.Del(timer);
+ Timers.SetModified();
+ }
+ break;
+ }
}
}
}
@@ -3165,7 +3186,7 @@ void cRecordControls::Stop(cDevice *Device)
if (RecordControls[i]) {
if (RecordControls[i]->Device() == Device) {
isyslog("stopping recording on DVB device %d due to higher priority", Device->CardIndex() + 1);
- RecordControls[i]->Stop(true);
+ RecordControls[i]->Stop();
}
}
}
@@ -3242,7 +3263,7 @@ void cRecordControls::ChannelDataModified(cChannel *Channel)
if (RecordControls[i]->Timer() && RecordControls[i]->Timer()->Channel() == Channel) {
if (RecordControls[i]->Device()->ProvidesTransponder(Channel)) { // avoids retune on devices that don't really access the transponder
isyslog("stopping recording due to modification of channel %d", Channel->Number());
- RecordControls[i]->Stop(true);
+ RecordControls[i]->Stop();
// This will restart the recording, maybe even from a different
// device in case conditional access has changed.
}
diff --git a/menu.h b/menu.h
index d63fdaf..d142bbc 100644
--- a/menu.h
+++ b/menu.h
@@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
- * $Id: menu.h 1.68 2005/01/08 15:48:57 kls Exp $
+ * $Id: menu.h 1.69 2005/03/20 10:57:29 kls Exp $
*/
#ifndef __MENU_H
@@ -155,8 +155,7 @@ public:
virtual ~cRecordControl();
bool Process(time_t t);
cDevice *Device(void) { return device; }
- void Stop(bool KeepInstant = false);
- bool IsInstant(void) { return instantId; }
+ void Stop(void);
const char *InstantId(void) { return instantId; }
const char *FileName(void) { return fileName; }
cTimer *Timer(void) { return timer; }
diff --git a/menuitems.c b/menuitems.c
index 9b86db4..18b001e 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.21 2004/11/21 13:24:10 kls Exp $
+ * $Id: menuitems.c 1.22 2005/03/19 15:33:34 kls Exp $
*/
#include "menuitems.h"
@@ -535,117 +535,35 @@ eOSState cMenuEditTranItem::ProcessKey(eKeys Key)
return state;
}
-// --- cMenuEditDayItem ------------------------------------------------------
-
-int cMenuEditDayItem::days[] ={ cTimer::ParseDay("M------"),
- cTimer::ParseDay("-T-----"),
- cTimer::ParseDay("--W----"),
- cTimer::ParseDay("---T---"),
- cTimer::ParseDay("----F--"),
- cTimer::ParseDay("-----S-"),
- cTimer::ParseDay("------S"),
- cTimer::ParseDay("MTWTF--"),
- cTimer::ParseDay("MTWTFS-"),
- cTimer::ParseDay("MTWTFSS"),
- cTimer::ParseDay("-----SS"),
- 0 };
-
-cMenuEditDayItem::cMenuEditDayItem(const char *Name, int *Value)
-:cMenuEditIntItem(Name, Value, -INT_MAX, 31)
-{
- d = -1;
- md = 0;
- if (*value < 0) {
- int n = 0;
- while (days[n]) {
- if (days[n] == *value) {
- d = n;
- break;
- }
- n++;
- }
- }
- Set();
-}
-
-void cMenuEditDayItem::Set(void)
-{
- SetValue(cTimer::PrintDay(*value));
-}
+// --- cMenuEditDateItem -----------------------------------------------------
-eOSState cMenuEditDayItem::ProcessKey(eKeys Key)
+static int ParseWeekDays(const char *s)
{
- switch (Key) {
- case kLeft|k_Repeat:
- case kLeft: if (d > 0)
- *value = days[--d];
- else if (d == 0) {
- *value = 31;
- d = -1;
- }
- else if (*value == 1) {
- d = sizeof(days) / sizeof(int) - 2;
- *value = days[d];
- }
- else
- return cMenuEditIntItem::ProcessKey(Key);
- Set();
- break;
- case kRight|k_Repeat:
- case kRight: if (d >= 0) {
- *value = days[++d];
- if (*value == 0) {
- *value = 1;
- d = -1;
- }
- }
- else if (*value == 31) {
- d = 0;
- *value = days[d];
- }
- else
- return cMenuEditIntItem::ProcessKey(Key);
- Set();
- break;
- default: {
- if (d >= 0) {
- if (k1 <= Key && Key <= k7) {
- int v = *value ^ (1 << (Key - k1));
- if ((v & 0xFF) != 0) {
- *value = v; // can't let this become all 0
- Set();
- }
- break;
- }
- }
- int v = *value;
- eOSState result = cMenuEditIntItem::ProcessKey(Key);
- if (result == osContinue && Key == k0) {
- if (d >= 0) {
- *value = md ? md : cTimer::GetMDay(time(NULL));
- md = 0;
- d = -1;
- Set();
- }
- else if (*value == 0 || *value == v) {
- md = v;
- d = cTimer::GetWDayFromMDay(v);
- *value = days[d];
- Set();
- }
- }
- return result;
- }
- }
- return osContinue;
+ time_t day;
+ int weekdays;
+ return cTimer::ParseDay(s, day, weekdays) ? weekdays : 0;
}
-// --- cMenuEditDateItem -----------------------------------------------------
+int cMenuEditDateItem::days[] = { ParseWeekDays("M------"),
+ ParseWeekDays("-T-----"),
+ ParseWeekDays("--W----"),
+ ParseWeekDays("---T---"),
+ ParseWeekDays("----F--"),
+ ParseWeekDays("-----S-"),
+ ParseWeekDays("------S"),
+ ParseWeekDays("MTWTF--"),
+ ParseWeekDays("MTWTFS-"),
+ ParseWeekDays("MTWTFSS"),
+ ParseWeekDays("-----SS"),
+ 0 };
-cMenuEditDateItem::cMenuEditDateItem(const char *Name, time_t *Value)
+cMenuEditDateItem::cMenuEditDateItem(const char *Name, time_t *Value, int *WeekDays)
:cMenuEditItem(Name)
{
value = Value;
+ weekdays = WeekDays;
+ oldvalue = 0;
+ dayindex = 0;
Set();
}
@@ -653,7 +571,11 @@ void cMenuEditDateItem::Set(void)
{
#define DATEBUFFERSIZE 32
char buf[DATEBUFFERSIZE];
- if (*value) {
+ if (weekdays && *weekdays) {
+ SetValue(cTimer::PrintDay(0, *weekdays));
+ return;
+ }
+ else if (*value) {
struct tm tm_r;
localtime_r(value, &tm_r);
strftime(buf, DATEBUFFERSIZE, "%Y-%m-%d ", &tm_r);
@@ -669,15 +591,73 @@ eOSState cMenuEditDateItem::ProcessKey(eKeys Key)
eOSState state = cMenuEditItem::ProcessKey(Key);
if (state == osUnknown) {
+ time_t now = time(NULL);
if (NORMALKEY(Key) == kLeft) { // TODO might want to increase the delta if repeated quickly?
- *value -= SECSINDAY;
- if (*value < time(NULL))
- *value = 0;
+ if (!weekdays || !*weekdays) {
+ // Decrement single day:
+ time_t v = *value;
+ v -= SECSINDAY;
+ if (v < now) {
+ if (now <= v + SECSINDAY) { // switched from tomorrow to today
+ if (!weekdays)
+ v = 0;
+ }
+ else if (weekdays) { // switched from today to yesterday, so enter weekdays mode
+ v = 0;
+ dayindex = sizeof(days) / sizeof(int) - 2;
+ *weekdays = days[dayindex];
+ }
+ else // don't go before today
+ v = *value;
+ }
+ *value = v;
+ }
+ else {
+ // Decrement weekday index:
+ if (dayindex > 0)
+ *weekdays = days[--dayindex];
+ }
}
else if (NORMALKEY(Key) == kRight) {
- if (!*value)
- *value = cTimer::SetTime(time(NULL), 0);
- *value += SECSINDAY;
+ if (!weekdays || !*weekdays) {
+ // Increment single day:
+ if (!*value)
+ *value = cTimer::SetTime(now, 0);
+ *value += SECSINDAY;
+ }
+ else {
+ // Increment weekday index:
+ *weekdays = days[++dayindex];
+ if (!*weekdays) { // was last weekday entry, so switch to today
+ *value = cTimer::SetTime(now, 0);
+ dayindex = 0;
+ }
+ }
+ }
+ else if (weekdays) {
+ if (Key == k0) {
+ // Toggle between weekdays and single day:
+ if (*weekdays) {
+ *value = cTimer::SetTime(oldvalue ? oldvalue : now, 0);
+ oldvalue = 0;
+ *weekdays = 0;
+ }
+ else {
+ *weekdays = days[cTimer::GetWDay(*value)];
+ oldvalue = *value;
+ *value = 0;
+ }
+ }
+ else if (k1 <= Key && Key <= k7) {
+ // Toggle individual weekdays:
+ if (*weekdays) {
+ int v = *weekdays ^ (1 << (Key - k1));
+ if (v != 0)
+ *weekdays = v; // can't let this become all 0
+ }
+ }
+ else
+ return state;
}
else
return state;
diff --git a/menuitems.h b/menuitems.h
index 2890401..b45fc96 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.10 2004/11/21 13:23:00 kls Exp $
+ * $Id: menuitems.h 1.11 2005/03/19 15:02:57 kls Exp $
*/
#ifndef __MENUITEMS_H
@@ -118,24 +118,16 @@ public:
virtual eOSState ProcessKey(eKeys Key);
};
-class cMenuEditDayItem : public cMenuEditIntItem {
+class cMenuEditDateItem : public cMenuEditItem {
private:
static int days[];
- int d;
- int md;
-protected:
- virtual void Set(void);
-public:
- cMenuEditDayItem(const char *Name, int *Value);
- virtual eOSState ProcessKey(eKeys Key);
- };
-
-class cMenuEditDateItem : public cMenuEditItem {
-protected:
time_t *value;
+ int *weekdays;
+ time_t oldvalue;
+ int dayindex;
virtual void Set(void);
public:
- cMenuEditDateItem(const char *Name, time_t *Value);
+ cMenuEditDateItem(const char *Name, time_t *Value, int *WeekDays = NULL);
virtual eOSState ProcessKey(eKeys Key);
};
diff --git a/remote.c b/remote.c
index 2d382e0..448d553 100644
--- a/remote.c
+++ b/remote.c
@@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
- * $Id: remote.c 1.41 2004/10/31 14:05:12 kls Exp $
+ * $Id: remote.c 1.42 2005/03/20 13:25:31 kls Exp $
*/
#include "remote.h"
@@ -145,6 +145,7 @@ bool cRemote::Put(const char *Code, bool Repeat, bool Release)
bool cRemote::HasKeys(void)
{
+ cMutexLock MutexLock(&mutex);
return in != out && !(keys[out] & k_Repeat);
}
diff --git a/remux.c b/remux.c
index ca65a61..135fa79 100644
--- a/remux.c
+++ b/remux.c
@@ -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.31 2005/02/13 14:36:23 kls Exp $
+ * $Id: remux.c 1.33 2005/03/20 13:18:15 kls Exp $
*/
#include "remux.h"
@@ -46,6 +46,8 @@ private:
int fragmentTodo;
uchar pesHeader[6 + 3 + 255 + 4 + 4];
int pesHeaderLen;
+ uchar pesHeaderBackup[6 + 3 + 255];
+ int pesHeaderBackupLen;
uchar chk1;
uchar chk2;
int ac3todo;
@@ -57,8 +59,8 @@ private:
get_length,
output_packet
} state;
- void ResetPesHeader(void);
- void AppendSubStreamID(void);
+ 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);
bool StartNewPacket(cRingBufferLinear *ResultBuffer, const uchar *const Data, const int Todo, int &Done, int &Bite);
public:
@@ -103,23 +105,26 @@ cDolbyRepacker::cDolbyRepacker(void)
Reset();
}
-void cDolbyRepacker::AppendSubStreamID(void)
+void cDolbyRepacker::AppendSubStreamID(bool ContinuationFrame)
{
if (subStreamId) {
pesHeader[pesHeaderLen++] = subStreamId;
+ // number of ac3 frames "starting" in this packet (1 by design).
+ pesHeader[pesHeaderLen++] = 0x01;
+ // offset to start of first ac3 frame (0 means "no ac3 frame starting"
+ // so 1 (by design) addresses the first byte after the next two bytes).
pesHeader[pesHeaderLen++] = 0x00;
- pesHeader[pesHeaderLen++] = 0x00;
- pesHeader[pesHeaderLen++] = 0x00;
+ pesHeader[pesHeaderLen++] = (ContinuationFrame ? 0x00 : 0x01);
}
}
-void cDolbyRepacker::ResetPesHeader(void)
+void cDolbyRepacker::ResetPesHeader(bool ContinuationFrame)
{
pesHeader[6] = 0x80;
pesHeader[7] = 0x00;
pesHeader[8] = 0x00;
pesHeaderLen = 9;
- AppendSubStreamID();
+ AppendSubStreamID(ContinuationFrame);
}
void cDolbyRepacker::Reset(void)
@@ -131,6 +136,7 @@ void cDolbyRepacker::Reset(void)
chk2 = 0;
fragmentLen = 0;
fragmentTodo = 0;
+ pesHeaderBackupLen = 0;
}
bool cDolbyRepacker::FinishRemainder(cRingBufferLinear *ResultBuffer, const uchar *const Data, const int Todo, int &Done, int &Bite)
@@ -229,12 +235,17 @@ int cDolbyRepacker::Put(cRingBufferLinear *ResultBuffer, const uchar *Data, int
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);
+ }
+
// skip PES header
int done = 6 + 3 + Data[8];
int todo = Count - done;
const uchar *data = Data + done;
- bool headerCopied = false;
-
+
// look for 0x0B 0x77 <chk1> <chk2> <frameSize>
while (todo > 0) {
switch (state) {
@@ -242,10 +253,10 @@ int cDolbyRepacker::Put(cRingBufferLinear *ResultBuffer, const uchar *Data, int
if (*data == 0x0B) {
++(int &)state;
// copy header information once for later use
- if (!headerCopied) {
- headerCopied = true;
- pesHeaderLen = 6 + 3 + Data[8];
- memcpy(pesHeader, Data, pesHeaderLen);
+ if (pesHeaderBackupLen > 0) {
+ pesHeaderLen = pesHeaderBackupLen;
+ pesHeaderBackupLen = 0;
+ memcpy(pesHeader, pesHeaderBackup, pesHeaderLen);
AppendSubStreamID();
}
}
@@ -279,9 +290,8 @@ int cDolbyRepacker::Put(cRingBufferLinear *ResultBuffer, const uchar *Data, int
ac3todo = 2 * frameSizes[*data];
// frameSizeCode was invalid => restart searching
if (ac3todo <= 0) {
- // reset PES header instead of using/copying a wrong one
+ // reset PES header instead of using a wrong one
ResetPesHeader();
- headerCopied = true;
if (chk1 == 0x0B) {
if (chk2 == 0x77) {
state = store_chk1;
@@ -320,8 +330,8 @@ int cDolbyRepacker::Put(cRingBufferLinear *ResultBuffer, const uchar *Data, int
// start a new packet
if (!StartNewPacket(ResultBuffer, data, todo, done, bite))
return done;
- // prepare for next packet
- ResetPesHeader();
+ // prepare for next (continuation) packet
+ ResetPesHeader(state == output_packet);
}
data += bite;
done += bite;
diff --git a/svdrp.c b/svdrp.c
index 1981f6e..7101502 100644
--- a/svdrp.c
+++ b/svdrp.c
@@ -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.67 2004/12/26 12:23:55 kls Exp $
+ * $Id: svdrp.c 1.69 2005/03/20 15:04:00 kls Exp $
*/
#include "svdrp.h"
@@ -111,7 +111,8 @@ int cSocket::Accept(void)
bool accepted = SVDRPhosts.Acceptable(clientname.sin_addr.s_addr);
if (!accepted) {
const char *s = "Access denied!\n";
- write(newsock, s, strlen(s));
+ if (write(newsock, s, strlen(s)) < 0)
+ LOG_ERROR;
close(newsock);
newsock = -1;
}
@@ -528,9 +529,9 @@ void cSVDRP::CmdDELT(const char *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();
- isyslog("timer %s deleted", Option);
Reply(250, "Timer \"%s\" deleted", Option);
}
else
@@ -918,7 +919,7 @@ void cSVDRP::CmdMODT(const char *Option)
}
*timer = t;
Timers.SetModified();
- isyslog("timer %d modified (%s)", timer->Index() + 1, timer->HasFlags(tfActive) ? "active" : "inactive");
+ isyslog("timer %s modified (%s)", *timer->ToDescr(), timer->HasFlags(tfActive) ? "active" : "inactive");
Reply(250, "%d %s", timer->Index() + 1, *timer->ToText());
}
else
@@ -976,7 +977,7 @@ void cSVDRP::CmdNEWT(const char *Option)
if (!t) {
Timers.Add(timer);
Timers.SetModified();
- isyslog("timer %d added", timer->Index() + 1);
+ isyslog("timer %s added", *timer->ToDescr());
Reply(250, "%d %s", timer->Index() + 1, *timer->ToText());
return;
}
@@ -1050,11 +1051,11 @@ void cSVDRP::CmdUPDT(const char *Option)
t->Parse(Option);
delete timer;
timer = t;
- isyslog("timer %d updated", timer->Index() + 1);
+ isyslog("timer %s updated", *timer->ToDescr());
}
else {
Timers.Add(timer);
- isyslog("timer %d added", timer->Index() + 1);
+ isyslog("timer %s added", *timer->ToDescr());
}
Timers.SetModified();
Reply(250, "%d %s", timer->Index() + 1, *timer->ToText());
diff --git a/timers.c b/timers.c
index 9edc6c3..2dded66 100644
--- a/timers.c
+++ b/timers.c
@@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
- * $Id: timers.c 1.22 2005/02/06 09:45:52 kls Exp $
+ * $Id: timers.c 1.30 2005/03/20 14:50:37 kls Exp $
*/
#include "timers.h"
@@ -30,7 +30,8 @@ cTimer::cTimer(bool Instant, bool Pause)
time_t t = time(NULL);
struct tm tm_r;
struct tm *now = localtime_r(&t, &tm_r);
- day = now->tm_mday;
+ day = SetTime(t, 0);
+ weekdays = 0;
start = now->tm_hour * 100 + now->tm_min;
stop = now->tm_hour * 60 + now->tm_min + Setup.InstantRecordTime;
stop = (stop / 60) * 100 + (stop % 60);
@@ -39,7 +40,6 @@ cTimer::cTimer(bool Instant, bool Pause)
priority = Pause ? Setup.PausePriority : Setup.DefaultPriority;
lifetime = Pause ? Setup.PauseLifetime : Setup.DefaultLifetime;
*file = 0;
- firstday = 0;
summary = NULL;
event = NULL;
if (Instant && channel)
@@ -62,7 +62,8 @@ cTimer::cTimer(const cEvent *Event)
}
struct tm tm_r;
struct tm *time = localtime_r(&tstart, &tm_r);
- day = time->tm_mday;
+ day = SetTime(tstart, 0);
+ weekdays = 0;
start = time->tm_hour * 100 + time->tm_min;
time = localtime_r(&tstop, &tm_r);
stop = time->tm_hour * 100 + time->tm_min;
@@ -74,7 +75,6 @@ cTimer::cTimer(const cEvent *Event)
const char *Title = Event->Title();
if (!isempty(Title))
strn0cpy(file, Event->Title(), sizeof(file));
- firstday = 0;
summary = NULL;
event = Event;
}
@@ -109,85 +109,111 @@ cString cTimer::ToText(bool UseChannelID)
char *buffer;
strreplace(file, ':', '|');
strreplace(summary, '\n', '|');
- asprintf(&buffer, "%d:%s:%s:%04d:%04d:%d:%d:%s:%s\n", flags, UseChannelID ? *Channel()->GetChannelID().ToString() : *itoa(Channel()->Number()), *PrintDay(day, firstday), start, stop, priority, lifetime, file, summary ? summary : "");
+ asprintf(&buffer, "%d:%s:%s:%04d:%04d:%d:%d:%s:%s\n", flags, UseChannelID ? *Channel()->GetChannelID().ToString() : *itoa(Channel()->Number()), *PrintDay(day, weekdays), start, stop, priority, lifetime, file, summary ? summary : "");
strreplace(summary, '|', '\n');
strreplace(file, '|', ':');
return cString(buffer, true);
}
+cString cTimer::ToDescr(void) const
+{
+ char *buffer;
+ asprintf(&buffer, "%d (%d %04d-%04d '%s')", Index() + 1, Channel()->Number(), start, stop, file);
+ return cString(buffer, true);
+}
+
int cTimer::TimeToInt(int t)
{
return (t / 100 * 60 + t % 100) * 60;
}
-int cTimer::ParseDay(const char *s, time_t *FirstDay)
-{
- char *tail;
- int d = strtol(s, &tail, 10);
- if (FirstDay)
- *FirstDay = 0;
- if (tail && *tail) {
- d = 0;
- if (tail == s) {
- const char *first = strchr(s, '@');
- int l = first ? first - s : strlen(s);
- if (l == 7) {
- for (const char *p = s + 6; p >= s; p--) {
- d <<= 1;
- d |= (*p != '-');
- }
- d |= 0x80000000;
- }
- if (FirstDay && first) {
- ++first;
- if (strlen(first) == 10) {
- struct tm tm_r;
- if (3 == sscanf(first, "%d-%d-%d", &tm_r.tm_year, &tm_r.tm_mon, &tm_r.tm_mday)) {
- tm_r.tm_year -= 1900;
- tm_r.tm_mon--;
- tm_r.tm_hour = tm_r.tm_min = tm_r.tm_sec = 0;
- tm_r.tm_isdst = -1; // makes sure mktime() will determine the correct DST setting
- *FirstDay = mktime(&tm_r);
- }
- }
- else
- d = 0;
+bool cTimer::ParseDay(const char *s, time_t &Day, int &WeekDays)
+{
+ // possible formats are:
+ // 19
+ // 2005-03-19
+ // MTWTFSS
+ // MTWTFSS@19
+ // MTWTFSS@2005-03-19
+
+ Day = 0;
+ WeekDays = 0;
+ s = skipspace(s);
+ if (!*s)
+ return false;
+ const char *a = strchr(s, '@');
+ const char *d = a ? a + 1 : isdigit(*s) ? s : NULL;
+ if (d) {
+ if (strlen(d) == 10) {
+ struct tm tm_r;
+ if (3 == sscanf(d, "%d-%d-%d", &tm_r.tm_year, &tm_r.tm_mon, &tm_r.tm_mday)) {
+ tm_r.tm_year -= 1900;
+ tm_r.tm_mon--;
+ tm_r.tm_hour = tm_r.tm_min = tm_r.tm_sec = 0;
+ tm_r.tm_isdst = -1; // makes sure mktime() will determine the correct DST setting
+ Day = mktime(&tm_r);
}
+ else
+ return false;
+ }
+ else {
+ // handle "day of month" for compatibility with older versions:
+ char *tail = NULL;
+ int day = strtol(s, &tail, 10);
+ if (tail && *tail || day < 1 || day > 31)
+ return false;
+ time_t t = time(NULL);
+ int DaysToCheck = 61; // 61 to handle months with 31/30/31
+ for (int i = -1; i <= DaysToCheck; i++) {
+ time_t t0 = IncDay(t, i);
+ if (GetMDay(t0) == day) {
+ Day = SetTime(t0, 0);
+ break;
+ }
+ }
}
}
- else if (d < 1 || d > 31)
- d = 0;
- return d;
+ if (a || !isdigit(*s)) {
+ if ((a && a - s == 7) || strlen(s) == 7) {
+ for (const char *p = s + 6; p >= s; p--) {
+ WeekDays <<= 1;
+ WeekDays |= (*p != '-');
+ }
+ }
+ else
+ return false;
+ }
+ return true;
}
-cString cTimer::PrintDay(int d, time_t FirstDay)
+cString cTimer::PrintDay(time_t Day, int WeekDays)
{
#define DAYBUFFERSIZE 32
char buffer[DAYBUFFERSIZE];
- if ((d & 0x80000000) != 0) {
- char *b = buffer;
+ char *b = buffer;
+ if (WeekDays) {
const char *w = tr("MTWTFSS");
while (*w) {
- *b++ = (d & 1) ? *w : '-';
- d >>= 1;
+ *b++ = (WeekDays & 1) ? *w : '-';
+ WeekDays >>= 1;
w++;
}
- if (FirstDay) {
- struct tm tm_r;
- localtime_r(&FirstDay, &tm_r);
- b += strftime(b, DAYBUFFERSIZE - (b - buffer), "@%Y-%m-%d", &tm_r);
- }
- *b = 0;
+ if (Day)
+ *b++ = '@';
}
- else
- sprintf(buffer, "%d", d);
+ if (Day) {
+ struct tm tm_r;
+ localtime_r(&Day, &tm_r);
+ b += strftime(b, DAYBUFFERSIZE - (b - buffer), "%Y-%m-%d", &tm_r);
+ }
+ *b = 0;
return buffer;
}
-cString cTimer::PrintFirstDay(void)
+cString cTimer::PrintFirstDay(void) const
{
- if (firstday) {
- cString s = PrintDay(day, firstday);
+ if (weekdays) {
+ cString s = PrintDay(day, weekdays);
if (strlen(s) == 18)
return *s + 8;
}
@@ -223,8 +249,7 @@ bool cTimer::Parse(const char *s)
summary = NULL;
}
//TODO add more plausibility checks
- day = ParseDay(daybuffer, &firstday);
- result = day != 0;
+ result = ParseDay(daybuffer, day, weekdays);
strn0cpy(file, filebuffer, MaxFileName);
strreplace(file, '|', ':');
strreplace(summary, '|', '\n');
@@ -251,7 +276,7 @@ bool cTimer::Save(FILE *f)
bool cTimer::IsSingleEvent(void) const
{
- return (day & 0x80000000) == 0;
+ return !weekdays;
}
int cTimer::GetMDay(time_t t)
@@ -267,20 +292,9 @@ int cTimer::GetWDay(time_t t)
return weekday == 0 ? 6 : weekday - 1; // we start with monday==0!
}
-int cTimer::GetWDayFromMDay(int MDay)
-{
- time_t now = time(NULL);
- for (int i = -1; i <= 28; i++) { // looking 4 weeks into the future should be enough
- time_t t0 = IncDay(now, i);
- if (GetMDay(t0) == MDay)
- return GetWDay(t0);
- }
- return GetWDay(now); // just to return something
-}
-
bool cTimer::DayMatches(time_t t) const
{
- return IsSingleEvent() ? GetMDay(t) == day : (day & (1 << GetWDay(t))) != 0;
+ return IsSingleEvent() ? SetTime(t, 0) == day : (weekdays & (1 << GetWDay(t))) != 0;
}
time_t cTimer::IncDay(time_t t, int Days)
@@ -324,26 +338,31 @@ bool cTimer::Matches(time_t t, bool Directly) const
if (length < 0)
length += SECSINDAY;
- int DaysToCheck = IsSingleEvent() ? 61 : 7; // 61 to handle months with 31/30/31
- for (int i = -1; i <= DaysToCheck; i++) {
- time_t t0 = IncDay(t, i);
- if (DayMatches(t0)) {
- time_t a = SetTime(t0, begin);
- time_t b = a + length;
- if ((!firstday || a >= firstday) && t <= b) {
- startTime = a;
- stopTime = b;
- break;
+ if (IsSingleEvent()) {
+ startTime = SetTime(day, begin);
+ stopTime = startTime + length;
+ }
+ else {
+ for (int i = -1; i <= 7; i++) {
+ time_t t0 = IncDay(t, i);
+ if (DayMatches(t0)) {
+ time_t a = SetTime(t0, begin);
+ time_t b = a + length;
+ if ((!day || a >= day) && t <= b) {
+ startTime = a;
+ stopTime = b;
+ break;
+ }
}
}
- }
- if (!startTime)
- startTime = firstday; // just to have something that's more than a week in the future
- else if (!Directly && (t > startTime || t > firstday + SECSINDAY + 3600)) // +3600 in case of DST change
- firstday = 0;
+ if (!startTime)
+ startTime = day; // just to have something that's more than a week in the future
+ else if (!Directly && (t > startTime || t > day + SECSINDAY + 3600)) // +3600 in case of DST change
+ day = 0;
+ }
if (HasFlags(tfActive)) {
- if (HasFlags(tfVps) && !Directly && event && event->Vps()) {
+ if (HasFlags(tfVps) && !Directly && event && event->Vps() && schedule && schedule->PresentSeenWithin(30)) {
startTime = event->StartTime();
stopTime = event->EndTime();
return event->IsRunning(true);
@@ -353,28 +372,42 @@ bool cTimer::Matches(time_t t, bool Directly) const
return false;
}
-int cTimer::Matches(const cEvent *Event)
+#define FULLMATCH 1000
+
+int cTimer::Matches(const cEvent *Event, int *Overlap) const
{
- if (channel->GetChannelID() == Event->ChannelID()) {
+ // Overlap is the percentage of the Event's duration that is covered by
+ // this timer (based on FULLMATCH for finer granularity than just 100).
+ // To make sure a VPS timer can be distinguished from a plain 100% overlap,
+ // it gets an additional 100 added, and a VPS event that is actually running
+ // gets 200 added to the FULLMATCH.
+ if (HasFlags(tfActive) && channel->GetChannelID() == Event->ChannelID()) {
bool UseVps = HasFlags(tfVps) && Event->Vps();
- time_t t1 = UseVps ? Event->Vps() : Event->StartTime();
- time_t t2 = t1 + Event->Duration();
- bool m1 = Matches(t1, true);
- bool m2 = UseVps ? m1 : Matches(t2, true);
+ Matches(UseVps ? Event->Vps() : Event->StartTime(), true);
+ int overlap;
+ if (UseVps)
+ overlap = (startTime == Event->Vps()) ? FULLMATCH + (Event->IsRunning() ? 200 : 100) : 0;
+ else if (startTime <= Event->StartTime() && Event->EndTime() <= stopTime)
+ overlap = FULLMATCH;
+ else if (stopTime <= Event->StartTime() || Event->EndTime() <= startTime)
+ overlap = 0;
+ else
+ overlap = (min(stopTime, Event->EndTime()) - max(startTime, Event->StartTime())) * FULLMATCH / max(Event->Duration(), 1);
startTime = stopTime = 0;
- if (m1 && m2) {
- if (UseVps && Event->IsRunning(true))
- return tmFull;
- if (time(NULL) > Event->EndTime())
- return tmNone;
- return tmFull;
- }
- if ((m1 || m2) && time(NULL) <= Event->EndTime())
- return tmPartial;
+ if (Overlap)
+ *Overlap = overlap;
+ return overlap >= 1000 ? tmFull : overlap > 0 ? tmPartial : tmNone;
}
return tmNone;
}
+#define EXPIRELATENCY 60 // seconds (just in case there's a short glitch in the VPS signal)
+
+bool cTimer::Expired(void) const
+{
+ return IsSingleEvent() && !Recording() && StopTime() + EXPIRELATENCY <= time(NULL);
+}
+
time_t cTimer::StartTime(void) const
{
if (!startTime)
@@ -389,17 +422,18 @@ time_t cTimer::StopTime(void) const
return stopTime;
}
-void cTimer::SetEvent(const cEvent *Event)
+void cTimer::SetEvent(const cSchedule *Schedule, const cEvent *Event)
{
if (event != Event) { //XXX TODO check event data, too???
if (Event) {
char vpsbuf[64] = "";
if (Event->Vps())
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());
+ isyslog("timer %s set to event %s %s-%s %s'%s'", *ToDescr(), *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);
+ isyslog("timer %s set to no event", *ToDescr());
+ schedule = Event ? Schedule : NULL;
event = Event;
}
}
@@ -407,7 +441,7 @@ void cTimer::SetEvent(const cEvent *Event)
void cTimer::SetRecording(bool Recording)
{
recording = Recording;
- isyslog("timer %d (%d %04d-%04d '%s') %s", Index() + 1, Channel()->Number(), start, stop, file, recording ? "start" : "stop");
+ isyslog("timer %s %s", *ToDescr(), recording ? "start" : "stop");
}
void cTimer::SetPending(bool Pending)
@@ -418,7 +452,7 @@ void cTimer::SetPending(bool Pending)
void cTimer::SetInVpsMargin(bool InVpsMargin)
{
if (InVpsMargin && !inVpsMargin)
- isyslog("timer %d (%d %04d-%04d '%s') entered VPS margin", Index() + 1, Channel()->Number(), start, stop, file);
+ isyslog("timer %s entered VPS margin", *ToDescr());
inVpsMargin = InVpsMargin;
}
@@ -444,7 +478,7 @@ bool cTimer::HasFlags(int Flags) const
void cTimer::Skip(void)
{
- firstday = IncDay(SetTime(StartTime(), 0), 1);
+ day = IncDay(SetTime(StartTime(), 0), 1);
event = NULL;
}
@@ -452,8 +486,8 @@ void cTimer::OnOff(void)
{
if (IsSingleEvent())
InvFlags(tfActive);
- else if (firstday) {
- firstday = 0;
+ else if (day) {
+ day = 0;
ClrFlags(tfActive);
}
else if (HasFlags(tfActive))
@@ -536,6 +570,9 @@ bool cTimers::Modified(void)
return Result;
}
+#define EPGLIMITPAST (2 * 3600) // time in seconds around now, within which EPG events will be taken into consideration
+#define EPGLIMITFUTURE (4 * 3600)
+
void cTimers::SetEvents(void)
{
if (time(NULL) - lastSetEvents < 5)
@@ -549,20 +586,40 @@ void cTimers::SetEvents(void)
if (Schedule) {
if (!lastSetEvents || Schedule->Modified() >= lastSetEvents) {
const cEvent *Event = NULL;
- int Match = tmNone;
+ int Overlap = 0;
+ int Distance = INT_MIN;
+ time_t now = time(NULL);
for (const cEvent *e = Schedule->Events()->First(); e; e = Schedule->Events()->Next(e)) {
if (cRemote::HasKeys())
return; // react immediately on user input
- int m = ti->Matches(e);
- if (m > Match) {
- Match = m;
+ if (e->EndTime() < now - EPGLIMITPAST)
+ continue; // skip old events
+ if (e->StartTime() > now + EPGLIMITFUTURE)
+ break; // no need to process events too far in the future
+ int overlap = 0;
+ ti->Matches(e, &overlap);
+ if (overlap && overlap >= Overlap) {
+ int distance = 0;
+ if (now < e->StartTime())
+ distance = e->StartTime() - now;
+ else if (now > e->EndTime())
+ distance = e->EndTime() - now;
+ if (Event && overlap == Overlap) {
+ if (Overlap > FULLMATCH) { // this means VPS
+ if (abs(Distance) < abs(distance))
+ break; // we've already found the closest VPS event
+ }
+ else if (e->Duration() <= Event->Duration())
+ continue; // if overlap is the same, we take the longer event
+ }
+ Overlap = overlap;
+ Distance = distance;
Event = e;
- if (Match == tmFull)
- break;
- //XXX what if there's another event with the same VPS time???
}
}
- ti->SetEvent(Event);
+ if (Event && Event->EndTime() < now - EXPIRELATENCY && !Event->IsRunning())
+ Event = NULL;
+ ti->SetEvent(Schedule, Event);
}
}
}
@@ -570,3 +627,17 @@ void cTimers::SetEvents(void)
}
lastSetEvents = time(NULL);
}
+
+void cTimers::DeleteExpired(void)
+{
+ cTimer *ti = First();
+ while (ti) {
+ cTimer *next = Next(ti);
+ if (ti->Expired()) {
+ isyslog("deleting timer %s", *ti->ToDescr());
+ Del(ti);
+ SetModified();
+ }
+ ti = next;
+ }
+}
diff --git a/timers.h b/timers.h
index 7dcaf16..ae83f5b 100644
--- a/timers.h
+++ b/timers.h
@@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
- * $Id: timers.h 1.13 2004/12/26 12:21:29 kls Exp $
+ * $Id: timers.h 1.18 2005/03/20 14:47:45 kls Exp $
*/
#ifndef __TIMERS_H
@@ -30,14 +30,15 @@ private:
bool recording, pending, inVpsMargin;
int flags;
cChannel *channel;
- int day;
+ mutable time_t day; ///< midnight of the day this timer shall hit, or of the first day it shall hit in case of a repeating timer
+ int weekdays; ///< bitmask, lowest bits: SSFTWTM (the 'M' is the LSB)
int start;
int stop;
int priority;
int lifetime;
char file[MaxFileName];
- mutable time_t firstday;
char *summary;
+ const cSchedule *schedule;
const cEvent *event;
public:
cTimer(bool Instant = false, bool Pause = false);
@@ -45,36 +46,38 @@ public:
virtual ~cTimer();
cTimer& operator= (const cTimer &Timer);
virtual int Compare(const cListObject &ListObject) const;
- bool Recording(void) { return recording; }
- bool Pending(void) { return pending; }
- bool InVpsMargin(void) { return inVpsMargin; }
- int Flags(void) { return flags; }
- const cChannel *Channel(void) { return channel; }
- int Day(void) { return day; }
- int Start(void) { return start; }
- int Stop(void) { return stop; }
- int Priority(void) { return priority; }
- int Lifetime(void) { return lifetime; }
- const char *File(void) { return file; }
- time_t FirstDay(void) { return firstday; }
- const char *Summary(void) { return summary; }
+ bool Recording(void) const { return recording; }
+ bool Pending(void) const { return pending; }
+ bool InVpsMargin(void) const { return inVpsMargin; }
+ int Flags(void) const { return flags; }
+ const cChannel *Channel(void) const { return channel; }
+ time_t Day(void) const { return day; }
+ int WeekDays(void) const { return weekdays; }
+ int Start(void) const { return start; }
+ int Stop(void) const { return stop; }
+ int Priority(void) const { return priority; }
+ int Lifetime(void) const { return lifetime; }
+ const char *File(void) const { return file; }
+ time_t FirstDay(void) const { return weekdays ? day : 0; }
+ const char *Summary(void) const { return summary; }
cString ToText(bool UseChannelID = false);
- const cEvent *Event(void) { return event; }
+ cString ToDescr(void) const;
+ const cEvent *Event(void) const { return event; }
bool Parse(const char *s);
bool Save(FILE *f);
bool IsSingleEvent(void) const;
static int GetMDay(time_t t);
static int GetWDay(time_t t);
- static int GetWDayFromMDay(int MDay);
bool DayMatches(time_t t) const;
static time_t IncDay(time_t t, int Days);
static time_t SetTime(time_t t, int SecondsFromMidnight);
char *SetFile(const char *File);
bool Matches(time_t t = 0, bool Directly = false) const;
- int Matches(const cEvent *Event);
+ int Matches(const cEvent *Event, int *Overlap = NULL) const;
+ bool Expired(void) const;
time_t StartTime(void) const;
time_t StopTime(void) const;
- void SetEvent(const cEvent *Event);
+ void SetEvent(const cSchedule *Schedule, const cEvent *Event);
void SetRecording(bool Recording);
void SetPending(bool Pending);
void SetInVpsMargin(bool InVpsMargin);
@@ -84,10 +87,10 @@ public:
bool HasFlags(int Flags) const;
void Skip(void);
void OnOff(void);
- cString PrintFirstDay(void);
+ cString PrintFirstDay(void) const;
static int TimeToInt(int t);
- static int ParseDay(const char *s, time_t *FirstDay = NULL);
- static cString PrintDay(int d, time_t FirstDay = 0);
+ static bool ParseDay(const char *s, time_t &Day, int &WeekDays);
+ static cString PrintDay(time_t Day, int WeekDays);
};
class cTimers : public cConfig<cTimer> {
@@ -109,6 +112,7 @@ public:
///< Returns true if any of the timers have been modified.
///< Calling this function resets the 'modified' flag to false.
void SetEvents(void);
+ void DeleteExpired(void);
};
extern cTimers Timers;
diff --git a/tools.c b/tools.c
index aee71ec..28ea2af 100644
--- a/tools.c
+++ b/tools.c
@@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
- * $Id: tools.c 1.90 2005/02/19 13:43:03 kls Exp $
+ * $Id: tools.c 1.91 2005/03/20 14:44:33 kls Exp $
*/
#include "tools.h"
@@ -896,7 +896,7 @@ void cListObject::Unlink(void)
next = prev = NULL;
}
-int cListObject::Index(void)
+int cListObject::Index(void) const
{
cListObject *p = prev;
int i = 0;
diff --git a/tools.h b/tools.h
index be8782b..d9e85f3 100644
--- a/tools.h
+++ b/tools.h
@@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
- * $Id: tools.h 1.67 2005/02/12 10:17:14 kls Exp $
+ * $Id: tools.h 1.68 2005/03/20 14:44:24 kls Exp $
*/
#ifndef __TOOLS_H
@@ -202,7 +202,7 @@ public:
void Append(cListObject *Object);
void Insert(cListObject *Object);
void Unlink(void);
- int Index(void);
+ int Index(void) const;
cListObject *Prev(void) const { return prev; }
cListObject *Next(void) const { return next; }
};
diff --git a/vdr.5 b/vdr.5
index 04bdb99..5333be7 100644
--- a/vdr.5
+++ b/vdr.5
@@ -8,9 +8,9 @@
.\" License as specified in the file COPYING that comes with the
.\" vdr distribution.
.\"
-.\" $Id: vdr.5 1.34 2005/01/23 14:16:12 kls Exp $
+.\" $Id: vdr.5 1.35 2005/03/19 15:20:47 kls Exp $
.\"
-.TH vdr 5 "19 Dec 2004" "1.3.18" "Video Disk Recorder Files"
+.TH vdr 5 "19 Mar 2005" "1.3.23" "Video Disk Recorder Files"
.SH NAME
vdr file formats - the Video Disk Recorder Files
.SH DESCRIPTION
@@ -231,8 +231,13 @@ commands, the channels are given as numbers.
.B Day
The day when this timer shall record.
-If this is a `single-shot' timer, this is the day of month on which this
-timer shall record. This must be in the range \fB1...31\fR.
+If this is a `single-shot' timer, this is the date on which this
+timer shall record, given in ISO notation (\fBYYYY-MM-DD\fR), as in:
+
+.B 2005-03-19
+
+For compatibility with earlier versions of VDR this may also be just the day of month
+on which this timer shall record (must be in the range \fB1...31\fR).
In case of a `repeating' timer this is a string consisting of exactly seven
characters, where each character position corresponds to one day of the week
@@ -245,6 +250,7 @@ cause the timer to record on that day. Example:
will define a timer that records on Monday thru Friday and does not record
on weekends. The same result could be achieved with \fBABCDE\-\-\fR (this is
used to allow setting the days with language specific characters).
+Note that only letters may be used here, no digits.
The day definition of a `repeating' timer may be followed by the date when that
timer shall hit for the first time. The format for this is \fB@YYYY\-MM\-DD\fR,
diff --git a/vdr.c b/vdr.c
index 15aff94..72975e3 100644
--- a/vdr.c
+++ b/vdr.c
@@ -22,7 +22,7 @@
*
* The project's page is at http://www.cadsoft.de/vdr
*
- * $Id: vdr.c 1.202 2005/02/12 15:06:16 kls Exp $
+ * $Id: vdr.c 1.203 2005/03/20 10:58:59 kls Exp $
*/
#include <getopt.h>
@@ -606,6 +606,8 @@ int main(int argc, char *argv[])
PreviousChannel[PreviousChannelIndex ^= 1] = LastChannel;
// Timers and Recordings:
if (!Timers.BeingEdited()) {
+ // Delete expired timers:
+ Timers.DeleteExpired();
// Assign events to timers:
Timers.SetEvents();
// Must do all following calls with the exact same time!