Version 0.99pre5

- Updated channel settings for 'N24' (thanks to Andreas Gebel).
- Fixed handling hierarchical recordings menu in case of directories starting
  with the same sequence of characters.
- Fixed handling timers on the 29th, 30th or 31st of a month in case the next
  month has less than 31 days.
- Added a description of the sort order of individual episodes in the
  recordings menu to the MANUAL.
- Removed the EPG bugfix for "Title / Subtitle" cleanup. Apparently Pro-7 has
  finally stopped this nasty habit.
- Added some EPG bugfix statistics (printed to the log file every time the EPG
  data is cleaned up and when VDR is terminated). Maybe somebody in charge of
  the EPG data at the listed channels will read this and take the necessary
  actions to fix these things...
- Changed the [dei]syslog macros in tools.h to use a variable number of args,
  thus making it safe to use them in nested 'if/else' statements.
- Fixed error handling in establishing an SVDRP connection (thanks to Davide
  Achilli) for pointing this out).
- The new configuration file 'svdrphosts.conf' is now used to define which
  hosts may access the SVDRP port (by default only 'localhost' has access).
  See FORMATS for details.
- The special keywords TITLE and EPISODE can now be used in timer file names
  (see MANUAL and FORMATS for details).
- The new setup parameter NameInstantRecord can be used to define how an
  instant recording will be named (see MANUAL for details).
- When looking for the EPG record of the timer that starts a recording, now
  that record is taken which covers the time calculated as
  'start + (Setup.MarginStart * 2) + 1)' in order to have a better chance of
  hitting the right record in case of an instant recording. Timers that start
  further in the future should always be programmed via the "Schedules" menu.
- The special VPIDs '0' and '1' are now used to enable recording radio channels.
  Actually '0' should be enough, but '1' must be used with encrypted channels
  (driver bug?). Note, though, that since VDR is mainly a *video recorder*, some
  features like, e. g.,  the progress display, may not work as expected with
  radio recordings. Thanks to Michael Paar.
- Fixed a problem with the ERR macro defined by ncurses.h (thanks to Artur
  Skawina).
This commit is contained in:
Klaus Schmidinger 2002-02-03 18:00:00 +01:00
parent 3db2d636b2
commit ef0a53af72
24 changed files with 427 additions and 116 deletions

View File

@ -137,6 +137,7 @@ Matjaz Thaler <matjaz.thaler@guest.arnes.si>
Artur Skawina <skawina@geocities.com> Artur Skawina <skawina@geocities.com>
for improving the font file generation in the Makefile for improving the font file generation in the Makefile
for pointing out a problem with the ERR macro defined by ncurses.h
Werner Fink <werner@suse.de> Werner Fink <werner@suse.de>
for making I/O more robust by handling EINTR for making I/O more robust by handling EINTR
@ -179,3 +180,12 @@ Lauri Pesonen <lauri.pesonen@firsthop.com>
Sergei Haller <Sergei.Haller@math.uni-giessen.de> Sergei Haller <Sergei.Haller@math.uni-giessen.de>
for fixing the LastActivity timestamp after a shutdown prompt for fixing the LastActivity timestamp after a shutdown prompt
Andreas Gebel <andreas@xcapenet.de>
for his help in keeping 'channels.conf' up to date
Davide Achilli <davide@objsystem.it>
for pointing out a bug in error handling while establishing an SVDRP connection
Michael Paar <mpaar@uumail.de>
for enabling recording of radio channels

27
FORMATS
View File

@ -24,7 +24,7 @@ Video Disk Recorder File Formats
- Polarization (one of 'h', 'H', 'v', 'V') ** - Polarization (one of 'h', 'H', 'v', 'V') **
- Diseqc number ** - Diseqc number **
- Symbol rate *** - Symbol rate ***
- Video PID - Video PID (set to '0' for radio channels, '1' for encrypted radio channels)
- Audio PID (either one number, or two, separated by a comma) - Audio PID (either one number, or two, separated by a comma)
If this channel also carries Dolby Digital sound, the Dolby PIDs follow If this channel also carries Dolby Digital sound, the Dolby PIDs follow
the audio PIDs, separated by a semicolon, as in "...:101,102;103,104:..." the audio PIDs, separated by a semicolon, as in "...:101,102;103,104:..."
@ -72,6 +72,11 @@ Video Disk Recorder File Formats
any ':' characters, these have to be replaced with '|'. If the name shall any ':' characters, these have to be replaced with '|'. If the name shall
contain subdirectories, these have to be delimited by '~' (since the '/' contain subdirectories, these have to be delimited by '~' (since the '/'
character may be part of a regular programme name). character may be part of a regular programme name).
The special keywords TITLE and EPISODE, if present, will be replaced
with the title and episode information from the EPG data at the time of
recording (if that data is available). If at the time of recording either
of these cannot be determined, TITLE will default to the channel name, and
EPISODE will default to a blank.
- Summary (any newline characters in the summary have to be replaced with '|'; - Summary (any newline characters in the summary have to be replaced with '|';
the summary may contain ':' characters) the summary may contain ':' characters)
@ -111,6 +116,26 @@ Video Disk Recorder File Formats
1..9, the command can be selected directly by pressing the respective numerical 1..9, the command can be selected directly by pressing the respective numerical
key on the remote control. key on the remote control.
* svdrphosts.conf
This file contains the IP numbers of all hosts that are allowed to access the
SVDRP port.
Each line contains one IP number in the format
IP-Address[/Netmask]
where 'IP-Address' is the address of a host or a network in the usual dot
separated notation (as in 192.168.100.1). If the optional 'Netmask' is given
only the given number of bits of 'IP-Address' are taken into account. This
allows you to grant SVDRP access to all hosts of an entire network. 'Netmask'
can be any integer from 1 to 32. The special value of 0 is only accepted if
the 'IP-Address' is 0.0.0.0, because this will give access to any host (USE
THIS WITH CARE!).
Everything following (and including) a '#' character is considered to be
comment.
* marks.vdr * marks.vdr
This file (if present in a recording directory) contains the editing marks This file (if present in a recording directory) contains the editing marks

39
HISTORY
View File

@ -930,3 +930,42 @@ Video Disk Recorder Revision History
2002-01-30: Version 0.99pre4 2002-01-30: Version 0.99pre4
- Fixed handling improperly formatted EIT data (thanks to Rolf Hakenes). - Fixed handling improperly formatted EIT data (thanks to Rolf Hakenes).
2002-02-03: Version 0.99pre5
- Updated channel settings for 'N24' (thanks to Andreas Gebel).
- Fixed handling hierarchical recordings menu in case of directories starting
with the same sequence of characters.
- Fixed handling timers on the 29th, 30th or 31st of a month in case the next
month has less than 31 days.
- Added a description of the sort order of individual episodes in the
recordings menu to the MANUAL.
- Removed the EPG bugfix for "Title / Subtitle" cleanup. Apparently Pro-7 has
finally stopped this nasty habit.
- Added some EPG bugfix statistics (printed to the log file every time the EPG
data is cleaned up and when VDR is terminated). Maybe somebody in charge of
the EPG data at the listed channels will read this and take the necessary
actions to fix these things...
- Changed the [dei]syslog macros in tools.h to use a variable number of args,
thus making it safe to use them in nested 'if/else' statements.
- Fixed error handling in establishing an SVDRP connection (thanks to Davide
Achilli) for pointing this out).
- The new configuration file 'svdrphosts.conf' is now used to define which
hosts may access the SVDRP port (by default only 'localhost' has access).
See FORMATS for details.
- The special keywords TITLE and EPISODE can now be used in timer file names
(see MANUAL and FORMATS for details).
- The new setup parameter NameInstantRecord can be used to define how an
instant recording will be named (see MANUAL for details).
- When looking for the EPG record of the timer that starts a recording, now
that record is taken which covers the time calculated as
'start + (Setup.MarginStart * 2) + 1)' in order to have a better chance of
hitting the right record in case of an instant recording. Timers that start
further in the future should always be programmed via the "Schedules" menu.
- The special VPIDs '0' and '1' are now used to enable recording radio channels.
Actually '0' should be enough, but '1' must be used with encrypted channels
(driver bug?). Note, though, that since VDR is mainly a *video recorder*, some
features like, e. g., the progress display, may not work as expected with
radio recordings. Thanks to Michael Paar.
- Fixed a problem with the ERR macro defined by ncurses.h (thanks to Artur
Skawina).

View File

@ -81,6 +81,11 @@ WARNING: DUE TO THE OPEN SVDRP PORT THIS PROGRAM MAY CONSTITUTE A
A CONTROLLED ENVIRONMENT, YOU MAY WANT TO DISABLE SVDRP A CONTROLLED ENVIRONMENT, YOU MAY WANT TO DISABLE SVDRP
BY USING '--port=0'! BY USING '--port=0'!
The file 'svdrphosts.conf' can be used to define which hosts are allowed
to access the SVDRP port. By default only localhost (127.0.0.1) is granted
access. If you want to give other hosts access to your SVDRP port you need to
add their IP numbers to 'svdrphosts.conf'.
If the program shall run as a daemon, use the --daemon option. This If the program shall run as a daemon, use the --daemon option. This
will completely detach it from the terminal and will continue as a will completely detach it from the terminal and will continue as a
background process. background process.

16
MANUAL
View File

@ -166,6 +166,14 @@ Video Disk Recorder User's Manual
that directory (and any possible subdirectory thereof) as well as the total that directory (and any possible subdirectory thereof) as well as the total
number of new recordings (as opposed to a recording's entry, which displays number of new recordings (as opposed to a recording's entry, which displays
the date and time of the recording). the date and time of the recording).
If the setup parameter UseSubtitle was turned on when a recording took place,
VDR adds the "subtitle" (which is usually the name of the episode in case of
a series) to the recording's name. The "Recordings" menu then displays all
recordings of a periodic timer in chronological order, since these are
usually the individual episodes of a series, which you may want to view in
the order in which they were broadcast.
Playback can be stopped via the "Main" menu by selecting "Stop replaying", Playback can be stopped via the "Main" menu by selecting "Stop replaying",
or by pressing the "Blue" button outside the menu. or by pressing the "Blue" button outside the menu.
A previously stopped playback session can be resumed by pressing the "Blue" A previously stopped playback session can be resumed by pressing the "Blue"
@ -377,6 +385,14 @@ Video Disk Recorder User's Manual
0 = instant recordings will not be marked 0 = instant recordings will not be marked
1 = instant recordings will be marked. 1 = instant recordings will be marked.
NameInstantRecord = TITLE-EPISODE
Defines how to name an instant recording. If the keywords
TITLE and/or EPISODE are present, they will be replaced
with the title and episode information from the EPG data
at the time of recording (if that data is available).
If this parameter is empty, the channel name will be used
by default.
LnbSLOF = 11700 The switching frequency (in MHz) between low and high LOF LnbSLOF = 11700 The switching frequency (in MHz) between low and high LOF
LnbFrequLo = 9750 The LNB's low and high local oscillator frequencies (in MHz) LnbFrequLo = 9750 The LNB's low and high local oscillator frequencies (in MHz)
LnbFrequHi = 10600 (these have no meaning for DVB-C receivers) LnbFrequHi = 10600 (these have no meaning for DVB-C receivers)

View File

@ -4,7 +4,7 @@
# See the main source file 'vdr.c' for copyright information and # See the main source file 'vdr.c' for copyright information and
# how to reach the author. # how to reach the author.
# #
# $Id: Makefile 1.29 2002/01/13 16:57:27 kls Exp $ # $Id: Makefile 1.30 2002/02/01 14:40:09 kls Exp $
.DELETE_ON_ERROR: .DELETE_ON_ERROR:
@ -105,7 +105,7 @@ $(DTVLIB) $(DTVDIR)/libdtv.h:
clean: clean:
make -C $(AC3DIR) clean make -C $(AC3DIR) clean
make -C $(DTVDIR) clean make -C $(DTVDIR) clean
-rm -f $(OBJS) $(DEPFILE) vdr genfontfile genfontfile.o core *~ -rm -f $(OBJS) $(DEPFILE) vdr genfontfile genfontfile.o core* *~
fontclean: fontclean:
-rm -f fontfix.c fontosd.c -rm -f fontfix.c fontosd.c
CLEAN: clean fontclean CLEAN: clean fontclean

View File

@ -96,7 +96,7 @@ Cinedom 5A:11758:h:0:27500:1279:1280:0:3:194
Cinedom 5B:11720:h:0:27500:1791:1792:0:3:177 Cinedom 5B:11720:h:0:27500:1791:1792:0:3:177
Cinedom 5C:12070:h:0:27500:1023:1024:0:3:186 Cinedom 5C:12070:h:0:27500:1023:1024:0:3:186
:Beta Digital :Beta Digital
N24:11914:H:0:27500:255:256:8191:3:52 N24:12480:v:0:27500:2047:2048:0:0:47
CNBC:11954:h:0:27500:510:520:0:0:28010 CNBC:11954:h:0:27500:510:520:0:0:28010
Liberty TV.com:12610:V:0:22000:941:943,942:0:0:12199 Liberty TV.com:12610:V:0:22000:941:943,942:0:0:12199
:PW Erotic :PW Erotic

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: config.c 1.77 2002/01/19 16:06:42 kls Exp $ * $Id: config.c 1.82 2002/02/03 15:25:44 kls Exp $
*/ */
#include "config.h" #include "config.h"
@ -296,9 +296,8 @@ bool cChannel::Switch(cDvbApi *DvbApi, bool Log)
if (!DvbApi) if (!DvbApi)
DvbApi = cDvbApi::PrimaryDvbApi; DvbApi = cDvbApi::PrimaryDvbApi;
if (!DvbApi->Recording() && !groupSep) { if (!DvbApi->Recording() && !groupSep) {
if (Log) { if (Log)
isyslog(LOG_INFO, "switching to channel %d", number); isyslog(LOG_INFO, "switching to channel %d", number);
}
for (int i = 3; i--;) { for (int i = 3; i--;) {
switch (DvbApi->SetChannel(number, frequency, polarization, diseqc, srate, vpid, apid1, apid2, dpid1, dpid2, tpid, ca, pnr)) { switch (DvbApi->SetChannel(number, frequency, polarization, diseqc, srate, vpid, apid1, apid2, dpid1, dpid2, tpid, ca, pnr)) {
case scrOk: return true; case scrOk: return true;
@ -341,7 +340,7 @@ cTimer::cTimer(bool Instant)
*file = 0; *file = 0;
summary = NULL; summary = NULL;
if (Instant && ch) if (Instant && ch)
snprintf(file, sizeof(file), "%s%s", Setup.MarkInstantRecord ? "@" : "", ch->name); snprintf(file, sizeof(file), "%s%s", Setup.MarkInstantRecord ? "@" : "", *Setup.NameInstantRecord ? Setup.NameInstantRecord : ch->name);
} }
cTimer::cTimer(const cEventInfo *EventInfo) cTimer::cTimer(const cEventInfo *EventInfo)
@ -540,6 +539,13 @@ time_t cTimer::SetTime(time_t t, int SecondsFromMidnight)
return mktime(&tm); return mktime(&tm);
} }
char *cTimer::SetFile(const char *File)
{
if (!isempty(File))
strn0cpy(file, File, sizeof(file));
return file;
}
bool cTimer::Matches(time_t t) bool cTimer::Matches(time_t t)
{ {
startTime = stopTime = 0; startTime = stopTime = 0;
@ -551,7 +557,7 @@ bool cTimer::Matches(time_t t)
if (length < 0) if (length < 0)
length += SECSINDAY; length += SECSINDAY;
int DaysToCheck = IsSingleEvent() ? 31 : 7; int DaysToCheck = IsSingleEvent() ? 61 : 7; // 61 to handle months with 31/30/31
for (int i = -1; i <= DaysToCheck; i++) { for (int i = -1; i <= DaysToCheck; i++) {
time_t t0 = IncDay(t, i); time_t t0 = IncDay(t, i);
if (DayMatches(t0)) { if (DayMatches(t0)) {
@ -647,6 +653,40 @@ const char *cCommand::Execute(void)
return result; return result;
} }
// -- cSVDRPhost -------------------------------------------------------------
cSVDRPhost::cSVDRPhost(void)
{
addr.s_addr = 0;
mask = 0;
}
bool cSVDRPhost::Parse(const char *s)
{
mask = 0xFFFFFFFF;
const char *p = strchr(s, '/');
if (p) {
char *error = NULL;
int m = strtoul(p + 1, &error, 10);
if (error && !isspace(*error) || m > 32)
return false;
*(char *)p = 0; // yes, we know it's 'const' - will be restored!
if (m == 0)
mask = 0;
else
mask >>= (32 - m);
}
int result = inet_aton(s, &addr);
if (p)
*(char *)p = '/'; // there it is again
return result != 0 && (mask != 0 || addr.s_addr == 0);
}
bool cSVDRPhost::Accepts(in_addr_t Address)
{
return (Address & mask) == addr.s_addr;
}
// -- cKeys ------------------------------------------------------------------ // -- cKeys ------------------------------------------------------------------
cKeys Keys; cKeys Keys;
@ -659,9 +699,9 @@ cCommands Commands;
cChannels Channels; cChannels Channels;
bool cChannels::Load(const char *FileName) bool cChannels::Load(const char *FileName, bool AllowComments)
{ {
if (cConfig<cChannel>::Load(FileName)) { if (cConfig<cChannel>::Load(FileName, AllowComments)) {
ReNumber(); ReNumber();
return true; return true;
} }
@ -779,6 +819,21 @@ cTimer *cTimers::GetNextActiveTimer(void)
return t0; return t0;
} }
// -- cSVDRPhosts ------------------------------------------------------------
cSVDRPhosts SVDRPhosts;
bool cSVDRPhosts::Acceptable(in_addr_t Address)
{
cSVDRPhost *h = First();
while (h) {
if (h->Accepts(Address))
return true;
h = (cSVDRPhost *)h->Next();
}
return false;
}
// -- cSetup ----------------------------------------------------------------- // -- cSetup -----------------------------------------------------------------
cSetup Setup; cSetup Setup;
@ -792,6 +847,7 @@ cSetup::cSetup(void)
ShowInfoOnChSwitch = 1; ShowInfoOnChSwitch = 1;
MenuScrollPage = 1; MenuScrollPage = 1;
MarkInstantRecord = 1; MarkInstantRecord = 1;
strcpy(NameInstantRecord, "TITLE-EPISODE");
LnbSLOF = 11700; LnbSLOF = 11700;
LnbFrequLo = 9750; LnbFrequLo = 9750;
LnbFrequHi = 10600; LnbFrequHi = 10600;
@ -825,15 +881,18 @@ cSetup::cSetup(void)
bool cSetup::Parse(char *s) bool cSetup::Parse(char *s)
{ {
const char *Delimiters = " \t\n="; char *p = strchr(s, '=');
char *Name = strtok(s, Delimiters); if (p) {
char *Value = strtok(NULL, Delimiters); *p = 0;
if (Name && Value) { char *Name = compactspace(s);
char *Value = compactspace(p + 1);
if (*Name && *Value) {
if (!strcasecmp(Name, "OSDLanguage")) OSDLanguage = atoi(Value); if (!strcasecmp(Name, "OSDLanguage")) OSDLanguage = atoi(Value);
else if (!strcasecmp(Name, "PrimaryDVB")) PrimaryDVB = atoi(Value); else if (!strcasecmp(Name, "PrimaryDVB")) PrimaryDVB = atoi(Value);
else if (!strcasecmp(Name, "ShowInfoOnChSwitch")) ShowInfoOnChSwitch = atoi(Value); else if (!strcasecmp(Name, "ShowInfoOnChSwitch")) ShowInfoOnChSwitch = atoi(Value);
else if (!strcasecmp(Name, "MenuScrollPage")) MenuScrollPage = atoi(Value); else if (!strcasecmp(Name, "MenuScrollPage")) MenuScrollPage = atoi(Value);
else if (!strcasecmp(Name, "MarkInstantRecord")) MarkInstantRecord = atoi(Value); else if (!strcasecmp(Name, "MarkInstantRecord")) MarkInstantRecord = atoi(Value);
else if (!strcasecmp(Name, "NameInstantRecord")) strn0cpy(NameInstantRecord, Value, MaxFileName);
else if (!strcasecmp(Name, "LnbSLOF")) LnbSLOF = atoi(Value); else if (!strcasecmp(Name, "LnbSLOF")) LnbSLOF = atoi(Value);
else if (!strcasecmp(Name, "LnbFrequLo")) LnbFrequLo = atoi(Value); else if (!strcasecmp(Name, "LnbFrequLo")) LnbFrequLo = atoi(Value);
else if (!strcasecmp(Name, "LnbFrequHi")) LnbFrequHi = atoi(Value); else if (!strcasecmp(Name, "LnbFrequHi")) LnbFrequHi = atoi(Value);
@ -867,6 +926,7 @@ bool cSetup::Parse(char *s)
return false; return false;
return true; return true;
} }
}
return false; return false;
} }
@ -882,6 +942,7 @@ bool cSetup::Load(const char *FileName)
bool result = true; bool result = true;
while (fgets(buffer, sizeof(buffer), f) > 0) { while (fgets(buffer, sizeof(buffer), f) > 0) {
line++; line++;
stripspace(buffer);
if (!isempty(buffer)) { if (!isempty(buffer)) {
if (*buffer != '#' && !Parse(buffer)) { if (*buffer != '#' && !Parse(buffer)) {
esyslog(LOG_ERR, "error in %s, line %d\n", fileName, line); esyslog(LOG_ERR, "error in %s, line %d\n", fileName, line);
@ -911,6 +972,7 @@ bool cSetup::Save(const char *FileName)
fprintf(f, "ShowInfoOnChSwitch = %d\n", ShowInfoOnChSwitch); fprintf(f, "ShowInfoOnChSwitch = %d\n", ShowInfoOnChSwitch);
fprintf(f, "MenuScrollPage = %d\n", MenuScrollPage); fprintf(f, "MenuScrollPage = %d\n", MenuScrollPage);
fprintf(f, "MarkInstantRecord = %d\n", MarkInstantRecord); fprintf(f, "MarkInstantRecord = %d\n", MarkInstantRecord);
fprintf(f, "NameInstantRecord = %s\n", NameInstantRecord);
fprintf(f, "LnbSLOF = %d\n", LnbSLOF); fprintf(f, "LnbSLOF = %d\n", LnbSLOF);
fprintf(f, "LnbFrequLo = %d\n", LnbFrequLo); fprintf(f, "LnbFrequLo = %d\n", LnbFrequLo);
fprintf(f, "LnbFrequHi = %d\n", LnbFrequHi); fprintf(f, "LnbFrequHi = %d\n", LnbFrequHi);

View File

@ -4,12 +4,13 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: config.h 1.90 2002/01/30 18:30:03 kls Exp $ * $Id: config.h 1.93 2002/02/03 15:16:21 kls Exp $
*/ */
#ifndef __CONFIG_H #ifndef __CONFIG_H
#define __CONFIG_H #define __CONFIG_H
#include <arpa/inet.h>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <time.h> #include <time.h>
@ -18,7 +19,7 @@
#include "eit.h" #include "eit.h"
#include "tools.h" #include "tools.h"
#define VDRVERSION "0.99pre4" #define VDRVERSION "0.99pre5"
#define MAXPRIORITY 99 #define MAXPRIORITY 99
#define MAXLIFETIME 99 #define MAXLIFETIME 99
@ -65,6 +66,8 @@ enum eKeys { // "Up" and "Down" must be the first two keys!
#define ISRAWKEY(k) ((k) != kNone && ((k) & k_Flags) == 0) #define ISRAWKEY(k) ((k) != kNone && ((k) & k_Flags) == 0)
#define NORMALKEY(k) (eKeys((k) & ~k_Repeat)) #define NORMALKEY(k) (eKeys((k) & ~k_Repeat))
#define MaxFileName 256
struct tKey { struct tKey {
eKeys type; eKeys type;
char *name; char *name;
@ -122,7 +125,6 @@ private:
static char *buffer; static char *buffer;
static const char *ToText(cTimer *Timer); static const char *ToText(cTimer *Timer);
public: public:
enum { MaxFileName = 256 };
bool recording, pending; bool recording, pending;
int active; int active;
int channel; int channel;
@ -148,6 +150,7 @@ public:
bool DayMatches(time_t t); bool DayMatches(time_t t);
time_t IncDay(time_t t, int Days); time_t IncDay(time_t t, int Days);
time_t SetTime(time_t t, int SecondsFromMidnight); time_t SetTime(time_t t, int SecondsFromMidnight);
char *SetFile(const char *File);
bool Matches(time_t t = 0); bool Matches(time_t t = 0);
time_t StartTime(void); time_t StartTime(void);
time_t StopTime(void); time_t StopTime(void);
@ -171,6 +174,16 @@ public:
const char *Execute(void); const char *Execute(void);
}; };
class cSVDRPhost : public cListObject {
private:
struct in_addr addr;
in_addr_t mask;
public:
cSVDRPhost(void);
bool Parse(const char *s);
bool Accepts(in_addr_t Address);
};
template<class T> class cConfig : public cList<T> { template<class T> class cConfig : public cList<T> {
private: private:
char *fileName; char *fileName;
@ -182,7 +195,7 @@ private:
public: public:
cConfig(void) { fileName = NULL; } cConfig(void) { fileName = NULL; }
virtual ~cConfig() { delete fileName; } virtual ~cConfig() { delete fileName; }
virtual bool Load(const char *FileName) virtual bool Load(const char *FileName, bool AllowComments = false)
{ {
Clear(); Clear();
fileName = strdup(FileName); fileName = strdup(FileName);
@ -196,6 +209,11 @@ public:
result = true; result = true;
while (fgets(buffer, sizeof(buffer), f) > 0) { while (fgets(buffer, sizeof(buffer), f) > 0) {
line++; line++;
if (AllowComments) {
char *p = strchr(buffer, '#');
if (p)
*p = 0;
}
if (!isempty(buffer)) { if (!isempty(buffer)) {
T *l = new T; T *l = new T;
if (l->Parse(buffer)) if (l->Parse(buffer))
@ -242,7 +260,7 @@ protected:
int maxNumber; int maxNumber;
public: public:
cChannels(void) { maxNumber = 0; } cChannels(void) { maxNumber = 0; }
virtual bool Load(const char *FileName); virtual bool Load(const char *FileName, bool AllowComments = false);
int GetNextGroup(int Idx); // Get next channel group int GetNextGroup(int Idx); // Get next channel group
int GetPrevGroup(int Idx); // Get previous channel group int GetPrevGroup(int Idx); // Get previous channel group
int GetNextNormal(int Idx); // Get next normal channel (not group) int GetNextNormal(int Idx); // Get next normal channel (not group)
@ -263,10 +281,16 @@ public:
class cCommands : public cConfig<cCommand> {}; class cCommands : public cConfig<cCommand> {};
class cSVDRPhosts : public cConfig<cSVDRPhost> {
public:
bool Acceptable(in_addr_t Address);
};
extern cChannels Channels; extern cChannels Channels;
extern cTimers Timers; extern cTimers Timers;
extern cKeys Keys; extern cKeys Keys;
extern cCommands Commands; extern cCommands Commands;
extern cSVDRPhosts SVDRPhosts;
class cSetup { class cSetup {
private: private:
@ -279,6 +303,7 @@ public:
int ShowInfoOnChSwitch; int ShowInfoOnChSwitch;
int MenuScrollPage; int MenuScrollPage;
int MarkInstantRecord; int MarkInstantRecord;
char NameInstantRecord[MaxFileName];
int LnbSLOF; int LnbSLOF;
int LnbFrequLo; int LnbFrequLo;
int LnbFrequHi; int LnbFrequHi;

View File

@ -7,7 +7,7 @@
* DVD support initially written by Andreas Schultz <aschultz@warp10.net> * DVD support initially written by Andreas Schultz <aschultz@warp10.net>
* based on dvdplayer-0.5 by Matjaz Thaler <matjaz.thaler@guest.arnes.si> * based on dvdplayer-0.5 by Matjaz Thaler <matjaz.thaler@guest.arnes.si>
* *
* $Id: dvbapi.c 1.146 2002/01/26 15:39:48 kls Exp $ * $Id: dvbapi.c 1.147 2002/02/02 13:04:00 kls Exp $
*/ */
//#define DVDDEBUG 1 //#define DVDDEBUG 1
@ -548,9 +548,8 @@ void cRecordBuffer::Input(void)
} }
else if (r < 0) { else if (r < 0) {
if (FATALERRNO) { if (FATALERRNO) {
if (errno == EBUFFEROVERFLOW) { // this error code is not defined in the library if (errno == EBUFFEROVERFLOW) // this error code is not defined in the library
esyslog(LOG_ERR, "ERROR (%s,%d): DVB driver buffer overflow", __FILE__, __LINE__); esyslog(LOG_ERR, "ERROR (%s,%d): DVB driver buffer overflow", __FILE__, __LINE__);
}
else { else {
LOG_ERROR; LOG_ERROR;
break; break;
@ -1064,9 +1063,8 @@ cReplayBuffer::cReplayBuffer(cDvbApi *DvbApi, int VideoDev, int AudioDev, const
return; return;
// Create the index file: // Create the index file:
index = new cIndexFile(FileName, false); index = new cIndexFile(FileName, false);
if (!index) { if (!index)
esyslog(LOG_ERR, "ERROR: can't allocate index"); esyslog(LOG_ERR, "ERROR: can't allocate index");
}
else if (!index->Ok()) { else if (!index->Ok()) {
delete index; delete index;
index = NULL; index = NULL;
@ -2251,9 +2249,8 @@ void cTransferBuffer::Input(void)
} }
else if (r < 0) { else if (r < 0) {
if (FATALERRNO) { if (FATALERRNO) {
if (errno == EBUFFEROVERFLOW) { // this error code is not defined in the library if (errno == EBUFFEROVERFLOW) // this error code is not defined in the library
esyslog(LOG_ERR, "ERROR (%s,%d): DVB driver buffer overflow", __FILE__, __LINE__); esyslog(LOG_ERR, "ERROR (%s,%d): DVB driver buffer overflow", __FILE__, __LINE__);
}
else { else {
LOG_ERROR; LOG_ERROR;
break; break;
@ -2719,12 +2716,10 @@ bool cDvbApi::Init(void)
} }
} }
PrimaryDvbApi = dvbApi[0]; PrimaryDvbApi = dvbApi[0];
if (NumDvbApis > 0) { if (NumDvbApis > 0)
isyslog(LOG_INFO, "found %d video device%s", NumDvbApis, NumDvbApis > 1 ? "s" : ""); isyslog(LOG_INFO, "found %d video device%s", NumDvbApis, NumDvbApis > 1 ? "s" : "");
} // need braces because of isyslog-macro else
else {
esyslog(LOG_ERR, "ERROR: no video device found, giving up!"); esyslog(LOG_ERR, "ERROR: no video device found, giving up!");
}
return NumDvbApis > 0; return NumDvbApis > 0;
} }

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: dvbapi.h 1.60 2002/01/26 13:01:16 kls Exp $ * $Id: dvbapi.h 1.61 2002/02/03 16:43:38 kls Exp $
*/ */
#ifndef __DVBAPI_H #ifndef __DVBAPI_H
@ -12,6 +12,7 @@
#if defined(DEBUG_OSD) || defined(REMOTE_KBD) #if defined(DEBUG_OSD) || defined(REMOTE_KBD)
#include <ncurses.h> #include <ncurses.h>
#undef ERR //XXX ncurses defines this - but this clashes with newer system header files
#endif #endif
#include <stdlib.h> // FIXME: this is apparently necessary for the ost/... header files #include <stdlib.h> // FIXME: this is apparently necessary for the ost/... header files
// FIXME: shouldn't every header file include ALL the other header // FIXME: shouldn't every header file include ALL the other header

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: dvbosd.h 1.9 2001/12/09 15:11:05 kls Exp $ * $Id: dvbosd.h 1.10 2002/02/03 16:43:50 kls Exp $
*/ */
#ifndef __DVBOSD_H #ifndef __DVBOSD_H
@ -12,6 +12,7 @@
#if defined(DEBUG_OSD) || defined(REMOTE_KBD) #if defined(DEBUG_OSD) || defined(REMOTE_KBD)
#include <ncurses.h> #include <ncurses.h>
#undef ERR //XXX ncurses defines this - but this clashes with newer system header files
#endif #endif
#include <ost/osd.h> #include <ost/osd.h>
#include <stdio.h> #include <stdio.h>

85
eit.c
View File

@ -16,7 +16,7 @@
* the Free Software Foundation; either version 2 of the License, or * * the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. * * (at your option) any later version. *
* * * *
* $Id: eit.c 1.31 2002/01/13 16:14:31 kls Exp $ * $Id: eit.c 1.33 2002/02/02 12:12:26 kls Exp $
***************************************************************************/ ***************************************************************************/
#include "eit.h" #include "eit.h"
@ -352,6 +352,64 @@ void cEventInfo::Dump(FILE *f, const char *Prefix) const
} }
} }
#define MAXEPGBUGFIXSTATS 6
#define MAXEPGBUGFIXCHANS 50
struct tEpgBugFixStats {
int hits;
int n;
unsigned short serviceIDs[MAXEPGBUGFIXCHANS];
tEpgBugFixStats(void) { hits = n = 0; }
};
tEpgBugFixStats EpgBugFixStats[MAXEPGBUGFIXSTATS];
static void EpgBugFixStat(int Number, unsigned int ServiceID)
{
if (0 <= Number && Number < MAXEPGBUGFIXSTATS) {
tEpgBugFixStats *p = &EpgBugFixStats[Number];
p->hits++;
int i = 0;
for (; i < p->n; i++) {
if (p->serviceIDs[i] == ServiceID)
break;
}
if (i == p->n && p->n < MAXEPGBUGFIXCHANS)
p->serviceIDs[p->n++] = 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");
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 = ", ";
}
}
dsyslog(LOG_INFO, "%s", buffer);
if (Reset)
p->hits = p->n = 0;
}
dsyslog(LOG_INFO, "=====================");
}
}
void cEventInfo::FixEpgBugs(void) void cEventInfo::FixEpgBugs(void)
{ {
// VDR can't usefully handle newline characters in the EPG data, so let's // VDR can't usefully handle newline characters in the EPG data, so let's
@ -367,20 +425,6 @@ void cEventInfo::FixEpgBugs(void)
// EPG data. Let's fix their bugs as good as we can: // EPG data. Let's fix their bugs as good as we can:
if (pTitle) { if (pTitle) {
// Pro7 preceeds the Subtitle with the Title:
//
// Title
// Title / Subtitle
//
if (pSubtitle && strstr(pSubtitle, pTitle) == pSubtitle) {
char *p = pSubtitle + strlen(pTitle);
const char *delim = " / ";
if (strstr(p, delim) == p) {
p += strlen(delim);
memmove(pSubtitle, p, strlen(p) + 1);
}
}
// VOX and VIVA put the Subtitle in quotes and use either the Subtitle // VOX and VIVA put the Subtitle in quotes and use either the Subtitle
// or the Extended Description field, depending on how long the string is: // or the Extended Description field, depending on how long the string is:
// //
@ -400,6 +444,7 @@ void cEventInfo::FixEpgBugs(void)
delete pExtendedDescription; delete pExtendedDescription;
pSubtitle = s; pSubtitle = s;
pExtendedDescription = d; pExtendedDescription = d;
EpgBugFixStat(0, GetServiceID());
} }
} }
} }
@ -416,6 +461,7 @@ void cEventInfo::FixEpgBugs(void)
memmove(pSubtitle, pSubtitle + 1, strlen(pSubtitle)); memmove(pSubtitle, pSubtitle + 1, strlen(pSubtitle));
pExtendedDescription = pSubtitle; pExtendedDescription = pSubtitle;
pSubtitle = NULL; pSubtitle = NULL;
EpgBugFixStat(1, GetServiceID());
} }
} }
@ -427,6 +473,7 @@ void cEventInfo::FixEpgBugs(void)
if (pSubtitle && strcmp(pTitle, pSubtitle) == 0) { if (pSubtitle && strcmp(pTitle, pSubtitle) == 0) {
delete pSubtitle; delete pSubtitle;
pSubtitle = NULL; pSubtitle = NULL;
EpgBugFixStat(2, GetServiceID());
} }
// ZDF.info puts the Subtitle between double quotes, which is nothing // ZDF.info puts the Subtitle between double quotes, which is nothing
@ -442,6 +489,7 @@ void cEventInfo::FixEpgBugs(void)
char *p = strrchr(pSubtitle, '"'); char *p = strrchr(pSubtitle, '"');
if (p) if (p)
*p = 0; *p = 0;
EpgBugFixStat(3, GetServiceID());
} }
} }
@ -460,8 +508,10 @@ void cEventInfo::FixEpgBugs(void)
char *p = pExtendedDescription + 1; char *p = pExtendedDescription + 1;
while (*p) { while (*p) {
if (*p == '-' && *(p + 1) == ' ' && *(p + 2) && islower(*(p - 1)) && islower(*(p + 2))) { if (*p == '-' && *(p + 1) == ' ' && *(p + 2) && islower(*(p - 1)) && islower(*(p + 2))) {
if (!startswith(p + 2, "und ")) // special case in German, as in "Lach- und Sachgeschichten" if (!startswith(p + 2, "und ")) { // special case in German, as in "Lach- und Sachgeschichten"
memmove(p, p + 2, strlen(p + 2) + 1); memmove(p, p + 2, strlen(p + 2) + 1);
EpgBugFixStat(4, GetServiceID());
}
} }
p++; p++;
} }
@ -845,6 +895,8 @@ cSIProcessor::cSIProcessor(const char *FileName)
cSIProcessor::~cSIProcessor() cSIProcessor::~cSIProcessor()
{ {
if (masterSIProcessor)
ReportEpgBugFixStats();
active = false; active = false;
Cancel(3); Cancel(3);
ShutDownFilters(); ShutDownFilters();
@ -913,6 +965,7 @@ void cSIProcessor::Action()
schedules->Cleanup(); schedules->Cleanup();
schedulesMutex.Unlock(); schedulesMutex.Unlock();
lastCleanup = now; lastCleanup = now;
ReportEpgBugFixStats(true);
} }
if (epgDataFileName && now - lastDump > 600) if (epgDataFileName && now - lastDump > 600)
{ {

BIN
gmon.out Normal file

Binary file not shown.

11
i18n.c
View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: i18n.c 1.50 2002/01/27 15:52:32 kls Exp $ * $Id: i18n.c 1.51 2002/02/03 14:34:33 kls Exp $
* *
* Slovenian translations provided by Miha Setina <mihasetina@softhome.net> * Slovenian translations provided by Miha Setina <mihasetina@softhome.net>
* Italian translations provided by Alberto Carraro <bertocar@tin.it> * Italian translations provided by Alberto Carraro <bertocar@tin.it>
@ -776,6 +776,15 @@ const tPhrase Phrases[] = {
"Enregistrement immédiat", "Enregistrement immédiat",
"Markere direkteopptak", "Markere direkteopptak",
}, },
{ "NameInstantRecord",
"Direktaufz. benennen",
"", // TODO
"", // TODO
"", // TODO
"", // TODO
"", // TODO
"", // TODO
},
{ "LnbSLOF", { "LnbSLOF",
"LnbSLOF", "LnbSLOF",
"LnbSLOF", "LnbSLOF",

13
menu.c
View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: menu.c 1.146 2002/01/27 15:50:50 kls Exp $ * $Id: menu.c 1.148 2002/02/03 15:42:38 kls Exp $
*/ */
#include "menu.h" #include "menu.h"
@ -1553,7 +1553,7 @@ cMenuRecordings::cMenuRecordings(const char *Base, int Level, bool OpenSubMenus)
cMenuRecordingItem *LastItem = NULL; cMenuRecordingItem *LastItem = NULL;
char *LastItemText = NULL; char *LastItemText = NULL;
for (cRecording *recording = Recordings.First(); recording; recording = Recordings.Next(recording)) { for (cRecording *recording = Recordings.First(); recording; recording = Recordings.Next(recording)) {
if (!Base || strstr(recording->Name(), Base) == recording->Name()) { if (!Base || (strstr(recording->Name(), Base) == recording->Name() && recording->Name()[strlen(Base)] == '~')) {
cMenuRecordingItem *Item = new cMenuRecordingItem(recording, level); cMenuRecordingItem *Item = new cMenuRecordingItem(recording, level);
if (*Item->Text() && (!LastItem || strcmp(Item->Text(), LastItemText) != 0)) { if (*Item->Text() && (!LastItem || strcmp(Item->Text(), LastItemText) != 0)) {
Add(Item); Add(Item);
@ -1829,6 +1829,7 @@ void cMenuSetup::Set(void)
Add(new cMenuEditBoolItem(tr("ShowInfoOnChSwitch"), &data.ShowInfoOnChSwitch)); Add(new cMenuEditBoolItem(tr("ShowInfoOnChSwitch"), &data.ShowInfoOnChSwitch));
Add(new cMenuEditBoolItem(tr("MenuScrollPage"), &data.MenuScrollPage)); Add(new cMenuEditBoolItem(tr("MenuScrollPage"), &data.MenuScrollPage));
Add(new cMenuEditBoolItem(tr("MarkInstantRecord"), &data.MarkInstantRecord)); Add(new cMenuEditBoolItem(tr("MarkInstantRecord"), &data.MarkInstantRecord));
Add(new cMenuEditStrItem( tr("NameInstantRecord"), data.NameInstantRecord, sizeof(data.NameInstantRecord), FileNameChars));
Add(new cMenuEditIntItem( tr("LnbSLOF"), &data.LnbSLOF)); Add(new cMenuEditIntItem( tr("LnbSLOF"), &data.LnbSLOF));
Add(new cMenuEditIntItem( tr("LnbFrequLo"), &data.LnbFrequLo)); Add(new cMenuEditIntItem( tr("LnbFrequLo"), &data.LnbFrequLo));
Add(new cMenuEditIntItem( tr("LnbFrequHi"), &data.LnbFrequHi)); Add(new cMenuEditIntItem( tr("LnbFrequHi"), &data.LnbFrequHi));
@ -2309,14 +2310,16 @@ cRecordControl::cRecordControl(cDvbApi *DvbApi, cTimer *Timer)
timer->SetPending(true); timer->SetPending(true);
timer->SetRecording(true); timer->SetRecording(true);
if (Channels.SwitchTo(timer->channel, dvbApi)) { if (Channels.SwitchTo(timer->channel, dvbApi)) {
const char *Title = NULL;
const char *Subtitle = NULL; const char *Subtitle = NULL;
const char *Summary = NULL; const char *Summary = NULL;
if (GetEventInfo()) { if (GetEventInfo()) {
dsyslog(LOG_INFO, "Title: '%s' Subtitle: '%s'", eventInfo->GetTitle(), eventInfo->GetSubtitle()); Title = eventInfo->GetTitle();
Subtitle = eventInfo->GetSubtitle(); Subtitle = eventInfo->GetSubtitle();
Summary = eventInfo->GetExtendedDescription(); Summary = eventInfo->GetExtendedDescription();
dsyslog(LOG_INFO, "Title: '%s' Subtitle: '%s'", Title, Subtitle);
} }
cRecording Recording(timer, Subtitle, Summary); cRecording Recording(timer, Title, Subtitle, Summary);
fileName = strdup(Recording.FileName()); fileName = strdup(Recording.FileName());
cRecordingUserCommand::InvokeCommand(RUC_BEFORERECORDING, fileName); cRecordingUserCommand::InvokeCommand(RUC_BEFORERECORDING, fileName);
if (dvbApi->StartRecord(fileName, Channels.GetByNumber(timer->channel)->ca, timer->priority)) if (dvbApi->StartRecord(fileName, Channels.GetByNumber(timer->channel)->ca, timer->priority))
@ -2337,7 +2340,7 @@ cRecordControl::~cRecordControl()
bool cRecordControl::GetEventInfo(void) bool cRecordControl::GetEventInfo(void)
{ {
cChannel *channel = Channels.GetByNumber(timer->channel); cChannel *channel = Channels.GetByNumber(timer->channel);
time_t Time = timer->StartTime() + (timer->StopTime() - timer->StartTime()) / 2; time_t Time = timer->StartTime() + ((Setup.MarginStart * 2) + 1) * 60;
for (int seconds = 0; seconds <= MAXWAIT4EPGINFO; seconds++) { for (int seconds = 0; seconds <= MAXWAIT4EPGINFO; seconds++) {
{ {
cThreadLock ThreadLock; cThreadLock ThreadLock;

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: recording.c 1.48 2002/01/27 15:14:45 kls Exp $ * $Id: recording.c 1.49 2002/02/03 15:46:42 kls Exp $
*/ */
#include "recording.h" #include "recording.h"
@ -41,6 +41,9 @@
#define DISKCHECKDELTA 100 // seconds between checks for free disk space #define DISKCHECKDELTA 100 // seconds between checks for free disk space
#define REMOVELATENCY 10 // seconds to wait until next check after removing a file #define REMOVELATENCY 10 // seconds to wait until next check after removing a file
#define TIMERMACRO_TITLE "TITLE"
#define TIMERMACRO_EPISODE "EPISODE"
void RemoveDeletedRecordings(void) void RemoveDeletedRecordings(void)
{ {
static time_t LastRemoveCheck = 0; static time_t LastRemoveCheck = 0;
@ -214,19 +217,33 @@ char *ExchangeChars(char *s, bool ToFileSystem)
return s; return s;
} }
cRecording::cRecording(cTimer *Timer, const char *Subtitle, const char *Summary) cRecording::cRecording(cTimer *Timer, const char *Title, const char *Subtitle, const char *Summary)
{ {
resume = RESUME_NOT_INITIALIZED; resume = RESUME_NOT_INITIALIZED;
titleBuffer = NULL; titleBuffer = NULL;
sortBuffer = NULL; sortBuffer = NULL;
fileName = NULL; fileName = NULL;
if (Timer->IsSingleEvent() || !Setup.UseSubtitle) name = NULL;
name = strdup(Timer->file); // set up the actual name:
else { if (isempty(Title))
Title = Channels.GetChannelNameByNumber(Timer->channel);
if (isempty(Subtitle)) if (isempty(Subtitle))
Subtitle = " "; Subtitle = " ";
asprintf(&name, "%s~%s", Timer->file, Subtitle); char *macroTITLE = strstr(Timer->file, TIMERMACRO_TITLE);
char *macroEPISODE = strstr(Timer->file, TIMERMACRO_EPISODE);
if (macroTITLE || macroEPISODE) {
name = strdup(Timer->file);
name = strreplace(name, TIMERMACRO_TITLE, Title);
name = strreplace(name, TIMERMACRO_EPISODE, Subtitle);
if (Timer->IsSingleEvent()) {
Timer->SetFile(name); // this was an instant recording, so let's set the actual data
Timers.Save();
} }
}
else if (Timer->IsSingleEvent() || !Setup.UseSubtitle)
name = strdup(Timer->file);
else
asprintf(&name, "%s~%s", Timer->file, Subtitle);
// substitute characters that would cause problems in file names: // substitute characters that would cause problems in file names:
strreplace(name, '\n', ' '); strreplace(name, '\n', ' ');
start = Timer->StartTime(); start = Timer->StartTime();

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: recording.h 1.21 2002/01/26 15:18:16 kls Exp $ * $Id: recording.h 1.22 2002/02/03 11:59:49 kls Exp $
*/ */
#ifndef __RECORDING_H #ifndef __RECORDING_H
@ -43,7 +43,7 @@ public:
time_t start; time_t start;
int priority; int priority;
int lifetime; int lifetime;
cRecording(cTimer *Timer, const char *Subtitle, const char *Summary); cRecording(cTimer *Timer, const char *Title, const char *Subtitle, const char *Summary);
cRecording(const char *FileName); cRecording(const char *FileName);
~cRecording(); ~cRecording();
virtual bool operator< (const cListObject &ListObject); virtual bool operator< (const cListObject &ListObject);

16
remux.c
View File

@ -8,7 +8,7 @@
* the Linux DVB driver's 'tuxplayer' example and were rewritten to suit * the Linux DVB driver's 'tuxplayer' example and were rewritten to suit
* VDR's needs. * VDR's needs.
* *
* $Id: remux.c 1.6 2001/08/19 11:52:05 kls Exp $ * $Id: remux.c 1.8 2002/02/03 16:20:37 kls Exp $
*/ */
/* The calling interface of the 'cRemux::Process()' function is defined /* The calling interface of the 'cRemux::Process()' function is defined
@ -555,6 +555,17 @@ XXX*/
return Result ? resultBuffer : NULL; return Result ? resultBuffer : NULL;
XXX*/ XXX*/
// Special VPID case to enable recording radio channels:
if (vPid == 0 || vPid == 1 || vPid == 0x1FFF) {
// XXX actually '0' should be enough, but '1' must be used with encrypted channels (driver bug?)
// XXX also allowing 0x1FFF to not break Michael Paar's original patch,
// XXX but it would probably be best to only use '0'
*PictureType = I_FRAME;
Result = resultDelivered = resultCount;
return Result ? resultBuffer : NULL;
}
// Check if we're getting anywhere here: // Check if we're getting anywhere here:
if (!synced && skipped >= 0) { if (!synced && skipped >= 0) {
@ -583,9 +594,8 @@ XXX*/
if (l < 0) if (l < 0)
return NULL; // no useful data found, wait for more return NULL; // no useful data found, wait for more
if (pt != NO_PICTURE) { if (pt != NO_PICTURE) {
if (pt < I_FRAME || B_FRAME < pt) { if (pt < I_FRAME || B_FRAME < pt)
esyslog(LOG_ERR, "ERROR: unknown picture type '%d'", pt); esyslog(LOG_ERR, "ERROR: unknown picture type '%d'", pt);
}
else if (!synced) { else if (!synced) {
if (pt == I_FRAME) { if (pt == I_FRAME) {
resultDelivered = i; // will drop everything before this position resultDelivered = i; // will drop everything before this position

16
svdrp.c
View File

@ -10,7 +10,7 @@
* and interact with the Video Disk Recorder - or write a full featured * and interact with the Video Disk Recorder - or write a full featured
* graphical interface that sits on top of an SVDRP connection. * graphical interface that sits on top of an SVDRP connection.
* *
* $Id: svdrp.c 1.28 2002/01/13 16:07:42 kls Exp $ * $Id: svdrp.c 1.30 2002/02/02 15:39:46 kls Exp $
*/ */
#include "svdrp.h" #include "svdrp.h"
@ -101,9 +101,17 @@ int cSocket::Accept(void)
struct sockaddr_in clientname; struct sockaddr_in clientname;
uint size = sizeof(clientname); uint size = sizeof(clientname);
int newsock = accept(sock, (struct sockaddr *)&clientname, &size); int newsock = accept(sock, (struct sockaddr *)&clientname, &size);
if (newsock > 0) if (newsock > 0) {
isyslog(LOG_INFO, "connect from %s, port %hd", inet_ntoa(clientname.sin_addr), ntohs(clientname.sin_port)); bool accepted = SVDRPhosts.Acceptable(clientname.sin_addr.s_addr);
else if (errno != EINTR) if (!accepted) {
const char *s = "Access denied!\n";
write(newsock, s, strlen(s));
close(newsock);
newsock = -1;
}
isyslog(LOG_INFO, "connect from %s, port %hd - %s", inet_ntoa(clientname.sin_addr), ntohs(clientname.sin_port), accepted ? "accepted" : "DENIED");
}
else if (errno != EINTR && errno != EAGAIN)
LOG_ERROR; LOG_ERROR;
return newsock; return newsock;
} }

13
svdrphosts.conf Normal file
View File

@ -0,0 +1,13 @@
#
# svdrphosts This file describes a number of host addresses that
# are allowed to connect to the SVDRP port of the Video
# Disk Recorder (VDR) running on this system.
# Syntax:
#
# IP-Address[/Netmask]
#
127.0.0.1 # always accept localhost
#192.168.100.0/24 # any host on the local net
#204.152.189.113 # a specific host
#0.0.0.0/0 # any host on any net (USE THIS WITH CARE!)

23
tools.c
View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: tools.c 1.53 2002/01/27 12:36:23 kls Exp $ * $Id: tools.c 1.56 2002/02/03 16:44:08 kls Exp $
*/ */
#include "tools.h" #include "tools.h"
@ -13,6 +13,7 @@
#include <errno.h> #include <errno.h>
#if defined(DEBUG_OSD) #if defined(DEBUG_OSD)
#include <ncurses.h> #include <ncurses.h>
#undef ERR //XXX ncurses defines this - but this clashes with newer system header files
#endif #endif
#include <stdlib.h> #include <stdlib.h>
#include <sys/time.h> #include <sys/time.h>
@ -100,6 +101,23 @@ char *strreplace(char *s, char c1, char c2)
return s; return s;
} }
char *strreplace(char *s, const char *s1, const char *s2)
{
char *p = strstr(s, s1);
if (p) {
int of = p - s;
int l = strlen(s);
int l1 = strlen(s1);
int l2 = strlen(s2);
if (l2 > l1)
s = (char *)realloc(s, strlen(s) + l2 - l1 + 1);
if (l2 != l1)
memmove(s + of + l2, s + of + l1, l - of - l1 + 1);
strncpy(s + of, s2, l2);
}
return s;
}
char *skipspace(const char *s) char *skipspace(const char *s)
{ {
while (*s && isspace(*s)) while (*s && isspace(*s))
@ -404,10 +422,9 @@ char *ReadLink(const char *FileName)
if (n < 0) { if (n < 0) {
if (errno == ENOENT || errno == EINVAL) // file doesn't exist or is not a symlink if (errno == ENOENT || errno == EINVAL) // file doesn't exist or is not a symlink
TargetName = FileName; TargetName = FileName;
else { // some other error occurred else // some other error occurred
LOG_ERROR_STR(FileName); LOG_ERROR_STR(FileName);
} }
}
else if (n < int(sizeof(RealName))) { // got it! else if (n < int(sizeof(RealName))) { // got it!
RealName[n] = 0; RealName[n] = 0;
TargetName = RealName; TargetName = RealName;

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: tools.h 1.39 2002/01/26 15:38:10 kls Exp $ * $Id: tools.h 1.41 2002/02/03 12:36:25 kls Exp $
*/ */
#ifndef __TOOLS_H #ifndef __TOOLS_H
@ -20,9 +20,9 @@
extern int SysLogLevel; extern int SysLogLevel;
#define esyslog if (SysLogLevel > 0) syslog #define esyslog(a...) void( (SysLogLevel > 0) ? syslog(a) : void() )
#define isyslog if (SysLogLevel > 1) syslog #define isyslog(a...) void( (SysLogLevel > 1) ? syslog(a) : void() )
#define dsyslog if (SysLogLevel > 2) syslog #define dsyslog(a...) void( (SysLogLevel > 2) ? syslog(a) : void() )
#define LOG_ERROR esyslog(LOG_ERR, "ERROR (%s,%d): %m", __FILE__, __LINE__) #define LOG_ERROR esyslog(LOG_ERR, "ERROR (%s,%d): %m", __FILE__, __LINE__)
#define LOG_ERROR_STR(s) esyslog(LOG_ERR, "ERROR: %s: %m", s) #define LOG_ERROR_STR(s) esyslog(LOG_ERR, "ERROR: %s: %m", s)
@ -47,6 +47,7 @@ char *readline(FILE *f);
char *strcpyrealloc(char *dest, const char *src); char *strcpyrealloc(char *dest, const char *src);
char *strn0cpy(char *dest, const char *src, size_t n); char *strn0cpy(char *dest, const char *src, size_t n);
char *strreplace(char *s, char c1, char c2); char *strreplace(char *s, char c1, char c2);
char *strreplace(char *s, const char *s1, const char *s2); // re-allocates 's' and deletes the original string if necessary!
char *skipspace(const char *s); char *skipspace(const char *s);
char *stripspace(char *s); char *stripspace(char *s);
char *compactspace(char *s); char *compactspace(char *s);

3
vdr.c
View File

@ -22,7 +22,7 @@
* *
* The project's page is at http://www.cadsoft.de/people/kls/vdr * The project's page is at http://www.cadsoft.de/people/kls/vdr
* *
* $Id: vdr.c 1.93 2002/01/26 14:07:01 kls Exp $ * $Id: vdr.c 1.94 2002/02/02 15:50:43 kls Exp $
*/ */
#include <getopt.h> #include <getopt.h>
@ -272,6 +272,7 @@ int main(int argc, char *argv[])
Channels.Load(AddDirectory(ConfigDirectory, "channels.conf")); Channels.Load(AddDirectory(ConfigDirectory, "channels.conf"));
Timers.Load(AddDirectory(ConfigDirectory, "timers.conf")); Timers.Load(AddDirectory(ConfigDirectory, "timers.conf"));
Commands.Load(AddDirectory(ConfigDirectory, "commands.conf")); Commands.Load(AddDirectory(ConfigDirectory, "commands.conf"));
SVDRPhosts.Load(AddDirectory(ConfigDirectory, "svdrphosts.conf"), true);
#if defined(REMOTE_LIRC) #if defined(REMOTE_LIRC)
Keys.SetDummyValues(); Keys.SetDummyValues();
#elif !defined(REMOTE_NONE) #elif !defined(REMOTE_NONE)