Version 0.99

- Fixed a bug in moving timers or channels to the last position in the list
  (thanks to Matthias Schniedermeyer for helping to debug this one).
- Changed the estimated data rate for calculating the remaining disk capacity
  to 25.75 MB/min.
- Only reporting the 'EPG bugfix statistics' if there really were any fixes.
- Added Finnish language texts (thanks to Hannu Savolainen).
- Reverted to the previous way of searching for the EPG record of the current
  recording in case of a periodic timer (i.e. taking the one that is in the
  middle between start and end time).
- Added a typedef for 'in_addr_t' to make it work with glibc < 2.2 (thanks to
  Jrgen Schmidt).
- When the last entry in a "Recordings" menu page is deleted, that page is now
  automatically closed (suggested by Uwe Freese).
- Changed the default name for instant recordings to "TITLE EPISODE" (avoiding
  the '-').
- If Setup.ShowInfoOnChSwitch is set to "no", the box for the EPG display is no
  longer shown (thanks to Andy Grobb).
- If compiled with VFAT=1, characters that can't be handled by a VFAT system are
  now encoded to '#XX'.
- When the user presses the "Power" button and there is a timer about to start
  recording within Setup.MinEventTimeout minutes, there is now a confirmation
  prompt telling the user that there is an upcoming timer event.
- If a recording has no episode title, the trailing '~' is no longer shown in
  the progress display.
This commit is contained in:
Klaus Schmidinger 2002-02-10 18:00:00 +01:00
parent ef0a53af72
commit a1da0e5c5d
12 changed files with 359 additions and 51 deletions

View File

@ -47,6 +47,7 @@ Matthias Schniedermeyer <ms@citd.de>
for implementing the 'MarkInstantRecord' setup option
for his "schnitt" tools
for his "master-timer" tool
for helping to debug the "move to last position in list" bug
Miha Setina <mihasetina@softhome.net>
for translating the OSD texts to the Slovenian language
@ -161,6 +162,7 @@ Simon Bauschulte <SemiSchwabe@Brutzel.de>
Andy Grobb <Charly98@01019freenet.de>
for completing storing the current audio volume in the setup.conf file
for fixing the EPG display in case Setup.ShowInfoOnChSwitch is set to "no"
Thomas Heiligenmann <thomas@heiligenmann.de>
for implementing the SVDRP commands LSTR and DELR
@ -189,3 +191,17 @@ Davide Achilli <davide@objsystem.it>
Michael Paar <mpaar@uumail.de>
for enabling recording of radio channels
Hannu Savolainen <hannu@opensound.com>
for translating the OSD texts to the Finnish language
Jürgen Schmidt <ju@ct.heise.de>
for fixing a problem with 'in_addr_t' on systems with glibc < 2.2.
Uwe Freese <mail@uwe-freese.de>
for suggesting to automatically close an empty recordings page after deleting
an entry
Rainer Zocholl <Usenet-372114@zocki.toppoint.de>
for suggesting a confirmation prompt when the user presses the "Power" button
and there is an upcoming timer event

27
HISTORY
View File

@ -969,3 +969,30 @@ Video Disk Recorder Revision History
radio recordings. Thanks to Michael Paar.
- Fixed a problem with the ERR macro defined by ncurses.h (thanks to Artur
Skawina).
2002-02-10: Version 0.99
- Fixed a bug in moving timers or channels to the last position in the list
(thanks to Matthias Schniedermeyer for helping to debug this one).
- Changed the estimated data rate for calculating the remaining disk capacity
to 25.75 MB/min.
- Only reporting the 'EPG bugfix statistics' if there really were any fixes.
- Added Finnish language texts (thanks to Hannu Savolainen).
- Reverted to the previous way of searching for the EPG record of the current
recording in case of a periodic timer (i.e. taking the one that is in the
middle between start and end time).
- Added a typedef for 'in_addr_t' to make it work with glibc < 2.2 (thanks to
Jürgen Schmidt).
- When the last entry in a "Recordings" menu page is deleted, that page is now
automatically closed (suggested by Uwe Freese).
- Changed the default name for instant recordings to "TITLE EPISODE" (avoiding
the '-').
- If Setup.ShowInfoOnChSwitch is set to "no", the box for the EPG display is no
longer shown (thanks to Andy Grobb).
- If compiled with VFAT=1, characters that can't be handled by a VFAT system are
now encoded to '#XX'.
- When the user presses the "Power" button and there is a timer about to start
recording within Setup.MinEventTimeout minutes, there is now a confirmation
prompt telling the user that there is an upcoming timer event.
- If a recording has no episode title, the trailing '~' is no longer shown in
the progress display.

View File

@ -200,3 +200,4 @@ VIVA2:12552:v:0:22000:171:172:0:0:12120
MTV German:12699:v:0:22000:3031:3032:0:0:28643
IFA-TV:10832:h:0:22000:132:133:32:0:7251
QVC Germany:12552:v:0:22000:165:166:0:0:12100
TANGOTV:10832:h:1:22000:61:62:0:0:61920

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: config.c 1.82 2002/02/03 15:25:44 kls Exp $
* $Id: config.c 1.83 2002/02/10 11:39:00 kls Exp $
*/
#include "config.h"
@ -847,7 +847,7 @@ cSetup::cSetup(void)
ShowInfoOnChSwitch = 1;
MenuScrollPage = 1;
MarkInstantRecord = 1;
strcpy(NameInstantRecord, "TITLE-EPISODE");
strcpy(NameInstantRecord, "TITLE EPISODE");
LnbSLOF = 11700;
LnbFrequLo = 9750;
LnbFrequHi = 10600;

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: config.h 1.93 2002/02/03 15:16:21 kls Exp $
* $Id: config.h 1.95 2002/02/10 15:44:40 kls Exp $
*/
#ifndef __CONFIG_H
@ -19,7 +19,7 @@
#include "eit.h"
#include "tools.h"
#define VDRVERSION "0.99pre5"
#define VDRVERSION "0.99"
#define MAXPRIORITY 99
#define MAXLIFETIME 99
@ -174,6 +174,8 @@ public:
const char *Execute(void);
};
typedef uint32_t in_addr_t; //XXX from /usr/include/netinet/in.h (apparently this is not defined on systems with glibc < 2.2)
class cSVDRPhost : public cListObject {
private:
struct in_addr addr;

47
eit.c
View File

@ -16,7 +16,7 @@
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* $Id: eit.c 1.33 2002/02/02 12:12:26 kls Exp $
* $Id: eit.c 1.34 2002/02/09 14:48:43 kls Exp $
***************************************************************************/
#include "eit.h"
@ -352,7 +352,7 @@ void cEventInfo::Dump(FILE *f, const char *Prefix) const
}
}
#define MAXEPGBUGFIXSTATS 6
#define MAXEPGBUGFIXSTATS 5
#define MAXEPGBUGFIXCHANS 50
struct tEpgBugFixStats {
int hits;
@ -381,32 +381,39 @@ static void EpgBugFixStat(int Number, unsigned int ServiceID)
static void ReportEpgBugFixStats(bool Reset = false)
{
if (Setup.EPGBugfixLevel > 0) {
dsyslog(LOG_INFO, "=====================");
dsyslog(LOG_INFO, "EPG bugfix statistics");
dsyslog(LOG_INFO, "=====================");
dsyslog(LOG_INFO, "IF SOMEBODY WHO IS IN CHARGE OF THE EPG DATA FOR ONE OF THE LISTED");
dsyslog(LOG_INFO, "CHANNELS READS THIS: PLEASE TAKE A LOOK AT THE FUNCTION cEventInfo::FixEpgBugs()");
dsyslog(LOG_INFO, "IN VDR/eit.c TO LEARN WHAT'S WRONG WITH YOUR DATA, AND FIX IT!");
dsyslog(LOG_INFO, "=====================");
dsyslog(LOG_INFO, "Fix\tHits\tChannels");
bool GotHits = false;
char buffer[1024];
for (int i = 0; i < MAXEPGBUGFIXSTATS; i++) {
const char *delim = "\t";
tEpgBugFixStats *p = &EpgBugFixStats[i];
char *q = buffer;
q += snprintf(q, sizeof(buffer) - (q - buffer), "%d\t%d", i, p->hits);
for (int c = 0; c < p->n; c++) {
cChannel *channel = Channels.GetByServiceID(p->serviceIDs[c]);
if (channel) {
q += snprintf(q, sizeof(buffer) - (q - buffer), "%s%s", delim, channel->name);
delim = ", ";
if (p->hits) {
if (!GotHits) {
dsyslog(LOG_INFO, "=====================");
dsyslog(LOG_INFO, "EPG bugfix statistics");
dsyslog(LOG_INFO, "=====================");
dsyslog(LOG_INFO, "IF SOMEBODY WHO IS IN CHARGE OF THE EPG DATA FOR ONE OF THE LISTED");
dsyslog(LOG_INFO, "CHANNELS READS THIS: PLEASE TAKE A LOOK AT THE FUNCTION cEventInfo::FixEpgBugs()");
dsyslog(LOG_INFO, "IN VDR/eit.c TO LEARN WHAT'S WRONG WITH YOUR DATA, AND FIX IT!");
dsyslog(LOG_INFO, "=====================");
dsyslog(LOG_INFO, "Fix\tHits\tChannels");
GotHits = true;
}
char *q = buffer;
q += snprintf(q, sizeof(buffer) - (q - buffer), "%d\t%d", i, p->hits);
for (int c = 0; c < p->n; c++) {
cChannel *channel = Channels.GetByServiceID(p->serviceIDs[c]);
if (channel) {
q += snprintf(q, sizeof(buffer) - (q - buffer), "%s%s", delim, channel->name);
delim = ", ";
}
}
}
dsyslog(LOG_INFO, "%s", buffer);
dsyslog(LOG_INFO, "%s", buffer);
}
if (Reset)
p->hits = p->n = 0;
}
dsyslog(LOG_INFO, "=====================");
if (GotHits)
dsyslog(LOG_INFO, "=====================");
}
}

BIN
gmon.out

Binary file not shown.

182
i18n.c

File diff suppressed because it is too large Load Diff

27
menu.c
View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: menu.c 1.148 2002/02/03 15:42:38 kls Exp $
* $Id: menu.c 1.152 2002/02/10 11:52:34 kls Exp $
*/
#include "menu.h"
@ -1680,6 +1680,8 @@ eOSState cMenuRecordings::Del(void)
cOsdMenu::Del(Current());
Recordings.Del(recording);
Display();
if (!Count())
return osBack;
}
else
Interface->Error(tr("Error while deleting recording!"));
@ -1707,6 +1709,7 @@ eOSState cMenuRecordings::Summary(void)
eOSState cMenuRecordings::ProcessKey(eKeys Key)
{
bool HadSubMenu = HasSubMenu();
eOSState state = cOsdMenu::ProcessKey(Key);
if (state == osUnknown) {
@ -1720,6 +1723,13 @@ eOSState cMenuRecordings::ProcessKey(eKeys Key)
default: break;
}
}
if (Key == kYellow && HadSubMenu && !HasSubMenu()) {
// the last recording in a subdirectory was deleted, so let's go back up
cOsdMenu::Del(Current());
if (!Count())
return osBack;
Display();
}
if (!HasSubMenu() && Key != kNone)
SetHelpKeys();
return state;
@ -1944,13 +1954,14 @@ cMenuMain::cMenuMain(bool Replaying, eOSState State)
// Title with disk usage:
#define MB_PER_MINUTE 30 // this is just an estimate!
#define MB_PER_MINUTE 25.75 // this is just an estimate!
char buffer[40];
int FreeMB;
int Percent = VideoDiskSpace(&FreeMB);
int Hours = int(double(FreeMB) / MB_PER_MINUTE / 60);
int Minutes = (FreeMB / MB_PER_MINUTE) % 60;
int Minutes = int(double(FreeMB) / MB_PER_MINUTE);
int Hours = Minutes / 60;
Minutes %= 60;
snprintf(buffer, sizeof(buffer), "%s - Disk %d%% - %2d:%02d %s", tr("Main"), Percent, Hours, Minutes, tr("free"));
SetTitle(buffer);
@ -2113,10 +2124,11 @@ cDisplayChannel::cDisplayChannel(int Number, bool Switched)
{
group = -1;
withInfo = !Switched || Setup.ShowInfoOnChSwitch;
int EpgLines = withInfo ? 5 : 1;
lines = 0;
oldNumber = number = 0;
cChannel *channel = Channels.GetByNumber(Number);
Interface->Open(Setup.OSDwidth, Setup.ChannelInfoPos ? 5 : -5);
Interface->Open(Setup.OSDwidth, Setup.ChannelInfoPos ? EpgLines : -EpgLines);
if (channel) {
DisplayChannel(channel);
DisplayInfo();
@ -2131,7 +2143,8 @@ cDisplayChannel::cDisplayChannel(eKeys FirstKey)
oldNumber = cDvbApi::CurrentChannel();
number = 0;
lastTime = time_ms();
Interface->Open(Setup.OSDwidth, Setup.ChannelInfoPos ? 5 : -5);
int EpgLines = Setup.ShowInfoOnChSwitch ? 5 : 1;
Interface->Open(Setup.OSDwidth, Setup.ChannelInfoPos ? EpgLines : -EpgLines);
ProcessKey(FirstKey);
}
@ -2340,7 +2353,7 @@ cRecordControl::~cRecordControl()
bool cRecordControl::GetEventInfo(void)
{
cChannel *channel = Channels.GetByNumber(timer->channel);
time_t Time = timer->StartTime() + ((Setup.MarginStart * 2) + 1) * 60;
time_t Time = timer->IsSingleEvent() ? timer->StartTime() + ((Setup.MarginStart * 2) + 1) * 60 : timer->StartTime() + (timer->StopTime() - timer->StartTime()) / 2;
for (int seconds = 0; seconds <= MAXWAIT4EPGINFO; seconds++) {
{
cThreadLock ThreadLock;

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: recording.c 1.49 2002/02/03 15:46:42 kls Exp $
* $Id: recording.c 1.51 2002/02/10 15:41:23 kls Exp $
*/
#include "recording.h"
@ -196,22 +196,82 @@ tCharExchange CharExchange[] = {
{ ' ', '_' },
{ '\'', '\x01' },
{ '/', '\x02' },
#ifdef VFAT
{ ':', '\x03' },
#endif
{ 0, 0 }
};
char *ExchangeChars(char *s, bool ToFileSystem)
static char *ExchangeChars(char *s, bool ToFileSystem)
{
char *p = s;
while (*p) {
#define VFAT 1
#ifdef VFAT
// The VFAT file system can't handle all characters, so we
// have to take extra efforts to encode/decode them:
if (ToFileSystem) {
switch (*p) {
// characters that can be used "as is":
case '!':
case '@':
case '$':
case '%':
case '&':
case '(':
case ')':
case '+':
case ',':
case '-':
case '.':
case ';':
case '=':
case '0' ... '9':
case 'a' ... 'z':
case 'A' ... 'Z': break;
// characters that can be mapped to other characters:
case ' ': *p = '_'; break;
case '~': *p = '/'; break;
// characters that have to be encoded:
default: {
int l = p - s;
s = (char *)realloc(s, strlen(s) + 10);
p = s + l;
char buf[4];
sprintf(buf, "#%02X", (unsigned char)*p);
memmove(p + 2, p, strlen(p) + 1);
strncpy(p, buf, 3);
p += 2;
}
}
}
else {
switch (*p) {
// mapped characters:
case '_': *p = ' '; break;
case '/': *p = '~'; break;
// encodes characters:
case '#': {
if (strlen(p) > 2) {
char buf[3];
sprintf(buf, "%c%c", *(p + 1), *(p + 2));
unsigned char c = strtol(buf, NULL, 16);
*p = c;
memmove(p + 1, p + 3, strlen(p) - 2);
}
}
break;
// backwards compatibility:
case '\x01': *p = '\''; break;
case '\x02': *p = '/'; break;
case '\x03': *p = ':'; break;
}
}
#else
for (struct tCharExchange *ce = CharExchange; ce->a && ce->b; ce++) {
if (*p == (ToFileSystem ? ce->a : ce->b)) {
*p = ToFileSystem ? ce->b : ce->a;
break;
}
}
#endif
p++;
}
return s;
@ -285,7 +345,7 @@ cRecording::cRecording(const char *FileName)
name = new char[p - FileName + 1];
strncpy(name, FileName, p - FileName);
name[p - FileName] = 0;
ExchangeChars(name, false);
name = ExchangeChars(name, false);
}
// read an optional summary file:
char *SummaryFileName = NULL;
@ -384,9 +444,9 @@ const char *cRecording::FileName(void)
if (!fileName) {
struct tm tm_r;
struct tm *t = localtime_r(&start, &tm_r);
ExchangeChars(name, true);
name = ExchangeChars(name, true);
asprintf(&fileName, NAMEFORMAT, VideoDirectory, name, t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, t->tm_hour, t->tm_min, priority, lifetime);
ExchangeChars(name, false);
name = ExchangeChars(name, false);
}
return fileName;
}
@ -399,7 +459,7 @@ const char *cRecording::Title(char Delimiter, bool NewIndicator, int Level)
if (Level < 0 || Level == HierarchyLevels()) {
struct tm tm_r;
struct tm *t = localtime_r(&start, &tm_r);
const char *s;
char *s;
if (Level > 0 && (s = strrchr(name, '~')) != NULL)
s++;
else
@ -413,6 +473,11 @@ const char *cRecording::Title(char Delimiter, bool NewIndicator, int Level)
New,
Delimiter,
s);
// let's not display a trailing '~':
stripspace(titleBuffer);
s = &titleBuffer[strlen(titleBuffer) - 1];
if (*s == '~')
*s = 0;
}
else if (Level < HierarchyLevels()) {
const char *s = name;

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: tools.c 1.56 2002/02/03 16:44:08 kls Exp $
* $Id: tools.c 1.57 2002/02/05 18:16:52 kls Exp $
*/
#include "tools.h"
@ -804,8 +804,10 @@ void cListBase::Move(cListObject *From, cListObject *To)
To->Prev()->Append(From);
From->Append(To);
}
else
else {
lastObject->Append(From);
lastObject = From;
}
if (!From->Prev())
objects = From;
}

11
vdr.c
View File

@ -22,7 +22,7 @@
*
* The project's page is at http://www.cadsoft.de/people/kls/vdr
*
* $Id: vdr.c 1.94 2002/02/02 15:50:43 kls Exp $
* $Id: vdr.c 1.95 2002/02/10 15:12:43 kls Exp $
*/
#include <getopt.h>
@ -494,13 +494,20 @@ int main(int argc, char *argv[])
else
LastActivity = 1;
}
bool UserShutdown = key == kPower;
if (UserShutdown && Next && Delta <= Setup.MinEventTimeout * 60 && !ForceShutdown) {
char *buf;
asprintf(&buf, tr("Recording in %d minutes, shut down anyway?"), Delta / 60);
if (Interface->Confirm(buf))
ForceShutdown = true;
delete buf;
}
if (!Next || Delta > Setup.MinEventTimeout * 60 || ForceShutdown) {
ForceShutdown = false;
if (timer)
dsyslog(LOG_INFO, "next timer event at %s", ctime(&Next));
if (WatchdogTimeout > 0)
signal(SIGALRM, SIG_IGN);
bool UserShutdown = key == kPower;
if (Interface->Confirm(tr("Press any key to cancel shutdown"), UserShutdown ? 5 : SHUTDOWNWAIT, true)) {
int Channel = timer ? timer->channel : 0;
const char *File = timer ? timer->file : "";