summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKlaus Schmidinger <vdr@tvdr.de>2002-02-03 15:55:04 +0100
committerKlaus Schmidinger <vdr@tvdr.de>2002-02-03 15:55:04 +0100
commitdeb9f887106521797cacd77f1ae48de1d7b3277e (patch)
treeca79d7e3988bed90e1f18bcc9b39cecee67a91c7
parent0b7e9057daceab33b13238f4dea90976b5d2074d (diff)
downloadvdr-deb9f887106521797cacd77f1ae48de1d7b3277e.tar.gz
vdr-deb9f887106521797cacd77f1ae48de1d7b3277e.tar.bz2
Implemented TITLE and EPISODE keywords
-rw-r--r--FORMATS5
-rw-r--r--HISTORY11
-rw-r--r--MANUAL8
-rw-r--r--config.c100
-rw-r--r--config.h9
-rw-r--r--i18n.c11
-rw-r--r--menu.c11
-rw-r--r--recording.c31
-rw-r--r--recording.h4
-rw-r--r--tools.c19
-rw-r--r--tools.h3
11 files changed, 149 insertions, 63 deletions
diff --git a/FORMATS b/FORMATS
index 7cc4333d..46fd543e 100644
--- a/FORMATS
+++ b/FORMATS
@@ -72,6 +72,11 @@ Video Disk Recorder File Formats
any ':' characters, these have to be replaced with '|'. If the name shall
contain subdirectories, these have to be delimited by '~' (since the '/'
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 '|';
the summary may contain ':' characters)
diff --git a/HISTORY b/HISTORY
index 75966ef0..87a2eb80 100644
--- a/HISTORY
+++ b/HISTORY
@@ -931,7 +931,7 @@ Video Disk Recorder Revision History
- Fixed handling improperly formatted EIT data (thanks to Rolf Hakenes).
-2002-02-02: Version 0.99pre5
+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
@@ -953,3 +953,12 @@ Video Disk Recorder Revision History
- 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.
diff --git a/MANUAL b/MANUAL
index a564786d..d0ce7a2c 100644
--- a/MANUAL
+++ b/MANUAL
@@ -385,6 +385,14 @@ Video Disk Recorder User's Manual
0 = instant recordings will not 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
LnbFrequLo = 9750 The LNB's low and high local oscillator frequencies (in MHz)
LnbFrequHi = 10600 (these have no meaning for DVB-C receivers)
diff --git a/config.c b/config.c
index 9a2ab7a0..974aed0c 100644
--- a/config.c
+++ b/config.c
@@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
- * $Id: config.c 1.81 2002/02/02 17:15:03 kls Exp $
+ * $Id: config.c 1.82 2002/02/03 15:25:44 kls Exp $
*/
#include "config.h"
@@ -340,7 +340,7 @@ cTimer::cTimer(bool Instant)
*file = 0;
summary = NULL;
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)
@@ -539,6 +539,13 @@ time_t cTimer::SetTime(time_t t, int SecondsFromMidnight)
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)
{
startTime = stopTime = 0;
@@ -840,6 +847,7 @@ cSetup::cSetup(void)
ShowInfoOnChSwitch = 1;
MenuScrollPage = 1;
MarkInstantRecord = 1;
+ strcpy(NameInstantRecord, "TITLE-EPISODE");
LnbSLOF = 11700;
LnbFrequLo = 9750;
LnbFrequHi = 10600;
@@ -873,47 +881,51 @@ cSetup::cSetup(void)
bool cSetup::Parse(char *s)
{
- const char *Delimiters = " \t\n=";
- char *Name = strtok(s, Delimiters);
- char *Value = strtok(NULL, Delimiters);
- if (Name && Value) {
- if (!strcasecmp(Name, "OSDLanguage")) OSDLanguage = atoi(Value);
- else if (!strcasecmp(Name, "PrimaryDVB")) PrimaryDVB = atoi(Value);
- else if (!strcasecmp(Name, "ShowInfoOnChSwitch")) ShowInfoOnChSwitch = atoi(Value);
- else if (!strcasecmp(Name, "MenuScrollPage")) MenuScrollPage = atoi(Value);
- else if (!strcasecmp(Name, "MarkInstantRecord")) MarkInstantRecord = atoi(Value);
- else if (!strcasecmp(Name, "LnbSLOF")) LnbSLOF = atoi(Value);
- else if (!strcasecmp(Name, "LnbFrequLo")) LnbFrequLo = atoi(Value);
- else if (!strcasecmp(Name, "LnbFrequHi")) LnbFrequHi = atoi(Value);
- else if (!strcasecmp(Name, "DiSEqC")) DiSEqC = atoi(Value);
- else if (!strcasecmp(Name, "SetSystemTime")) SetSystemTime = atoi(Value);
- else if (!strcasecmp(Name, "MarginStart")) MarginStart = atoi(Value);
- else if (!strcasecmp(Name, "MarginStop")) MarginStop = atoi(Value);
- else if (!strcasecmp(Name, "EPGScanTimeout")) EPGScanTimeout = atoi(Value);
- else if (!strcasecmp(Name, "EPGBugfixLevel")) EPGBugfixLevel = atoi(Value);
- else if (!strcasecmp(Name, "SVDRPTimeout")) SVDRPTimeout = atoi(Value);
- else if (!strcasecmp(Name, "SortTimers")) SortTimers = atoi(Value);
- else if (!strcasecmp(Name, "PrimaryLimit")) PrimaryLimit = atoi(Value);
- else if (!strcasecmp(Name, "DefaultPriority")) DefaultPriority = atoi(Value);
- else if (!strcasecmp(Name, "DefaultLifetime")) DefaultLifetime = atoi(Value);
- else if (!strcasecmp(Name, "UseSubtitle")) UseSubtitle = atoi(Value);
- else if (!strcasecmp(Name, "RecordingDirs")) RecordingDirs = atoi(Value);
- else if (!strcasecmp(Name, "VideoFormat")) VideoFormat = atoi(Value);
- else if (!strcasecmp(Name, "ChannelInfoPos")) ChannelInfoPos = atoi(Value);
- else if (!strcasecmp(Name, "OSDwidth")) OSDwidth = atoi(Value);
- else if (!strcasecmp(Name, "OSDheight")) OSDheight = atoi(Value);
- else if (!strcasecmp(Name, "OSDMessageTime")) OSDMessageTime = atoi(Value);
- else if (!strcasecmp(Name, "MaxVideoFileSize")) MaxVideoFileSize = atoi(Value);
- else if (!strcasecmp(Name, "SplitEditedFiles")) SplitEditedFiles = atoi(Value);
- else if (!strcasecmp(Name, "MinEventTimeout")) MinEventTimeout = atoi(Value);
- else if (!strcasecmp(Name, "MinUserInactivity")) MinUserInactivity = atoi(Value);
- else if (!strcasecmp(Name, "MultiSpeedMode")) MultiSpeedMode = atoi(Value);
- else if (!strcasecmp(Name, "ShowReplayMode")) ShowReplayMode = atoi(Value);
- else if (!strcasecmp(Name, "CurrentChannel")) CurrentChannel = atoi(Value);
- else if (!strcasecmp(Name, "CurrentVolume")) CurrentVolume = atoi(Value);
- else
- return false;
- return true;
+ char *p = strchr(s, '=');
+ if (p) {
+ *p = 0;
+ char *Name = compactspace(s);
+ char *Value = compactspace(p + 1);
+ if (*Name && *Value) {
+ if (!strcasecmp(Name, "OSDLanguage")) OSDLanguage = atoi(Value);
+ else if (!strcasecmp(Name, "PrimaryDVB")) PrimaryDVB = atoi(Value);
+ else if (!strcasecmp(Name, "ShowInfoOnChSwitch")) ShowInfoOnChSwitch = atoi(Value);
+ else if (!strcasecmp(Name, "MenuScrollPage")) MenuScrollPage = 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, "LnbFrequLo")) LnbFrequLo = atoi(Value);
+ else if (!strcasecmp(Name, "LnbFrequHi")) LnbFrequHi = atoi(Value);
+ else if (!strcasecmp(Name, "DiSEqC")) DiSEqC = atoi(Value);
+ else if (!strcasecmp(Name, "SetSystemTime")) SetSystemTime = atoi(Value);
+ else if (!strcasecmp(Name, "MarginStart")) MarginStart = atoi(Value);
+ else if (!strcasecmp(Name, "MarginStop")) MarginStop = atoi(Value);
+ else if (!strcasecmp(Name, "EPGScanTimeout")) EPGScanTimeout = atoi(Value);
+ else if (!strcasecmp(Name, "EPGBugfixLevel")) EPGBugfixLevel = atoi(Value);
+ else if (!strcasecmp(Name, "SVDRPTimeout")) SVDRPTimeout = atoi(Value);
+ else if (!strcasecmp(Name, "SortTimers")) SortTimers = atoi(Value);
+ else if (!strcasecmp(Name, "PrimaryLimit")) PrimaryLimit = atoi(Value);
+ else if (!strcasecmp(Name, "DefaultPriority")) DefaultPriority = atoi(Value);
+ else if (!strcasecmp(Name, "DefaultLifetime")) DefaultLifetime = atoi(Value);
+ else if (!strcasecmp(Name, "UseSubtitle")) UseSubtitle = atoi(Value);
+ else if (!strcasecmp(Name, "RecordingDirs")) RecordingDirs = atoi(Value);
+ else if (!strcasecmp(Name, "VideoFormat")) VideoFormat = atoi(Value);
+ else if (!strcasecmp(Name, "ChannelInfoPos")) ChannelInfoPos = atoi(Value);
+ else if (!strcasecmp(Name, "OSDwidth")) OSDwidth = atoi(Value);
+ else if (!strcasecmp(Name, "OSDheight")) OSDheight = atoi(Value);
+ else if (!strcasecmp(Name, "OSDMessageTime")) OSDMessageTime = atoi(Value);
+ else if (!strcasecmp(Name, "MaxVideoFileSize")) MaxVideoFileSize = atoi(Value);
+ else if (!strcasecmp(Name, "SplitEditedFiles")) SplitEditedFiles = atoi(Value);
+ else if (!strcasecmp(Name, "MinEventTimeout")) MinEventTimeout = atoi(Value);
+ else if (!strcasecmp(Name, "MinUserInactivity")) MinUserInactivity = atoi(Value);
+ else if (!strcasecmp(Name, "MultiSpeedMode")) MultiSpeedMode = atoi(Value);
+ else if (!strcasecmp(Name, "ShowReplayMode")) ShowReplayMode = atoi(Value);
+ else if (!strcasecmp(Name, "CurrentChannel")) CurrentChannel = atoi(Value);
+ else if (!strcasecmp(Name, "CurrentVolume")) CurrentVolume = atoi(Value);
+ else
+ return false;
+ return true;
+ }
}
return false;
}
@@ -930,6 +942,7 @@ bool cSetup::Load(const char *FileName)
bool result = true;
while (fgets(buffer, sizeof(buffer), f) > 0) {
line++;
+ stripspace(buffer);
if (!isempty(buffer)) {
if (*buffer != '#' && !Parse(buffer)) {
esyslog(LOG_ERR, "error in %s, line %d\n", fileName, line);
@@ -959,6 +972,7 @@ bool cSetup::Save(const char *FileName)
fprintf(f, "ShowInfoOnChSwitch = %d\n", ShowInfoOnChSwitch);
fprintf(f, "MenuScrollPage = %d\n", MenuScrollPage);
fprintf(f, "MarkInstantRecord = %d\n", MarkInstantRecord);
+ fprintf(f, "NameInstantRecord = %s\n", NameInstantRecord);
fprintf(f, "LnbSLOF = %d\n", LnbSLOF);
fprintf(f, "LnbFrequLo = %d\n", LnbFrequLo);
fprintf(f, "LnbFrequHi = %d\n", LnbFrequHi);
diff --git a/config.h b/config.h
index 06cd583d..325f4ef2 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.92 2002/02/02 15:59:18 kls Exp $
+ * $Id: config.h 1.93 2002/02/03 15:16:21 kls Exp $
*/
#ifndef __CONFIG_H
@@ -19,7 +19,7 @@
#include "eit.h"
#include "tools.h"
-#define VDRVERSION "0.99pre4"
+#define VDRVERSION "0.99pre5"
#define MAXPRIORITY 99
#define MAXLIFETIME 99
@@ -66,6 +66,8 @@ enum eKeys { // "Up" and "Down" must be the first two keys!
#define ISRAWKEY(k) ((k) != kNone && ((k) & k_Flags) == 0)
#define NORMALKEY(k) (eKeys((k) & ~k_Repeat))
+#define MaxFileName 256
+
struct tKey {
eKeys type;
char *name;
@@ -123,7 +125,6 @@ private:
static char *buffer;
static const char *ToText(cTimer *Timer);
public:
- enum { MaxFileName = 256 };
bool recording, pending;
int active;
int channel;
@@ -149,6 +150,7 @@ public:
bool DayMatches(time_t t);
time_t IncDay(time_t t, int Days);
time_t SetTime(time_t t, int SecondsFromMidnight);
+ char *SetFile(const char *File);
bool Matches(time_t t = 0);
time_t StartTime(void);
time_t StopTime(void);
@@ -301,6 +303,7 @@ public:
int ShowInfoOnChSwitch;
int MenuScrollPage;
int MarkInstantRecord;
+ char NameInstantRecord[MaxFileName];
int LnbSLOF;
int LnbFrequLo;
int LnbFrequHi;
diff --git a/i18n.c b/i18n.c
index 7977fcd4..3d9089ae 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.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>
* Italian translations provided by Alberto Carraro <bertocar@tin.it>
@@ -776,6 +776,15 @@ const tPhrase Phrases[] = {
"Enregistrement immédiat",
"Markere direkteopptak",
},
+ { "NameInstantRecord",
+ "Direktaufz. benennen",
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ "", // TODO
+ },
{ "LnbSLOF",
"LnbSLOF",
"LnbSLOF",
diff --git a/menu.c b/menu.c
index abc8d45f..40ac1859 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.147 2002/02/01 15:08:44 kls Exp $
+ * $Id: menu.c 1.148 2002/02/03 15:42:38 kls Exp $
*/
#include "menu.h"
@@ -1829,6 +1829,7 @@ void cMenuSetup::Set(void)
Add(new cMenuEditBoolItem(tr("ShowInfoOnChSwitch"), &data.ShowInfoOnChSwitch));
Add(new cMenuEditBoolItem(tr("MenuScrollPage"), &data.MenuScrollPage));
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("LnbFrequLo"), &data.LnbFrequLo));
Add(new cMenuEditIntItem( tr("LnbFrequHi"), &data.LnbFrequHi));
@@ -2309,14 +2310,16 @@ cRecordControl::cRecordControl(cDvbApi *DvbApi, cTimer *Timer)
timer->SetPending(true);
timer->SetRecording(true);
if (Channels.SwitchTo(timer->channel, dvbApi)) {
+ const char *Title = NULL;
const char *Subtitle = NULL;
const char *Summary = NULL;
if (GetEventInfo()) {
- dsyslog(LOG_INFO, "Title: '%s' Subtitle: '%s'", eventInfo->GetTitle(), eventInfo->GetSubtitle());
+ Title = eventInfo->GetTitle();
Subtitle = eventInfo->GetSubtitle();
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());
cRecordingUserCommand::InvokeCommand(RUC_BEFORERECORDING, fileName);
if (dvbApi->StartRecord(fileName, Channels.GetByNumber(timer->channel)->ca, timer->priority))
@@ -2337,7 +2340,7 @@ cRecordControl::~cRecordControl()
bool cRecordControl::GetEventInfo(void)
{
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++) {
{
cThreadLock ThreadLock;
diff --git a/recording.c b/recording.c
index acdf264c..7a55e1a7 100644
--- a/recording.c
+++ b/recording.c
@@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
- * $Id: recording.c 1.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"
@@ -41,6 +41,9 @@
#define DISKCHECKDELTA 100 // seconds between checks for free disk space
#define REMOVELATENCY 10 // seconds to wait until next check after removing a file
+#define TIMERMACRO_TITLE "TITLE"
+#define TIMERMACRO_EPISODE "EPISODE"
+
void RemoveDeletedRecordings(void)
{
static time_t LastRemoveCheck = 0;
@@ -214,19 +217,33 @@ char *ExchangeChars(char *s, bool ToFileSystem)
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;
titleBuffer = NULL;
sortBuffer = NULL;
fileName = NULL;
- if (Timer->IsSingleEvent() || !Setup.UseSubtitle)
+ name = NULL;
+ // set up the actual name:
+ if (isempty(Title))
+ Title = Channels.GetChannelNameByNumber(Timer->channel);
+ if (isempty(Subtitle))
+ Subtitle = " ";
+ char *macroTITLE = strstr(Timer->file, TIMERMACRO_TITLE);
+ char *macroEPISODE = strstr(Timer->file, TIMERMACRO_EPISODE);
+ if (macroTITLE || macroEPISODE) {
name = strdup(Timer->file);
- else {
- if (isempty(Subtitle))
- Subtitle = " ";
- asprintf(&name, "%s~%s", Timer->file, Subtitle);
+ 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:
strreplace(name, '\n', ' ');
start = Timer->StartTime();
diff --git a/recording.h b/recording.h
index 478ad0b7..38626f85 100644
--- a/recording.h
+++ b/recording.h
@@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
- * $Id: recording.h 1.21 2002/01/26 15:28:41 kls Exp $
+ * $Id: recording.h 1.22 2002/02/03 11:59:49 kls Exp $
*/
#ifndef __RECORDING_H
@@ -43,7 +43,7 @@ public:
time_t start;
int priority;
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();
virtual bool operator< (const cListObject &ListObject);
diff --git a/tools.c b/tools.c
index 0aedad8d..f55935bd 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.54 2002/02/02 13:03:40 kls Exp $
+ * $Id: tools.c 1.55 2002/02/03 13:35:38 kls Exp $
*/
#include "tools.h"
@@ -100,6 +100,23 @@ char *strreplace(char *s, char c1, char c2)
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)
{
while (*s && isspace(*s))
diff --git a/tools.h b/tools.h
index 4a1132ef..9663a8ed 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.40 2002/02/02 13:16:47 kls Exp $
+ * $Id: tools.h 1.41 2002/02/03 12:36:25 kls Exp $
*/
#ifndef __TOOLS_H
@@ -47,6 +47,7 @@ char *readline(FILE *f);
char *strcpyrealloc(char *dest, const char *src);
char *strn0cpy(char *dest, const char *src, size_t n);
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 *stripspace(char *s);
char *compactspace(char *s);