vdr/config.c
Klaus Schmidinger 156831036e Version 0.95
- Fixed behaviour in case the shutdown didn't take place (there were many
  "next timer event at..." messages in that case).
- Reduced the default value for MinEventTimeout to 30 minutes.
- Fixed detecting manual start in shutdown feature.
- An error message is now displayed in case the Transfer Mode can't be
  started because the necessary DVB card is currently recording (or there
  is no DVB card that can access this channel).
- Fixed toggling channels with the '0' key in case the "Ok" button has been
  pressed to display the current/next information.
- Pressing the "Power" key now always initiates the shutdown sequence (after
  user confirmation in case of a recording timer), event if there is currently
  a menu or a replay session active. Note the additional remarks in INSTALL
  regarding the values of the two parameters given to the shutdown program
  in case of a currently recording timer.
- Switching through channel groups with the "Left" and "Right" keys now
  always starts at the group that contains the current channel.
- Implemented "Multi Speed Mode" (thanks to Stefan Huelswitt).
- Implemented backtracing to hit the right spot after fast forward/rewind
  (thanks to Stefan Huelswitt).
- Implemented replay mode display (thanks to Stefan Huelswitt, with a few
  rewrites by kls).
- Changed the size of all input buffers used to parse config files or receive
  SVDRP commands to the same value of 10KB. This allows long strings to be
  used in the 'summary' field of a timer, for instance.
- The pipe to the Dolby Digital replay command (option '-a') now closes all
  unused file descriptors in the child process to avoid crashing when the
  OSD is used (thanks to Andreas Vitting).
- Switched to the driver's new tuning API (VDR now requires a driver version
  dated 2001-09-14 or higher).
- Changed obsolete macro VIDEO_WINDOW_CHROMAKEY to VID_TYPE_CHROMAKEY (thanks
  to Guido Fiala).
- New version of the "Master-Timer" tool (thanks to Matthias Schniedermeyer).
- Better error handling when writing configuration files.
- Fixed putting the final editing mark into the edited version's marks file.
- Fixed manipulating an editing mark at the very end of a recording.
- Fixed starting a new replay immediately after stopping a previous one (had
  caused a mix between live video and replay).
- Three new keys ("Volume+", Volume-" and "Mute") to control the DVB card's
  audio output volume.
- New version of the 'epg2timers' tool (thanks to Carsten Koch).
2001-09-16 18:00:00 +02:00

935 lines
27 KiB
C

/*
* config.c: Configuration file handling
*
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: config.c 1.72 2001/09/16 14:54:32 kls Exp $
*/
#include "config.h"
#include <ctype.h>
#include <stdlib.h>
#include "dvbapi.h"
#include "i18n.h"
#include "interface.h"
// -- cKeys ------------------------------------------------------------------
tKey keyTable[] = { // "Up" and "Down" must be the first two keys!
{ kUp, "Up", 0 },
{ kDown, "Down", 0 },
{ kMenu, "Menu", 0 },
{ kOk, "Ok", 0 },
{ kBack, "Back", 0 },
{ kLeft, "Left", 0 },
{ kRight, "Right", 0 },
{ kRed, "Red", 0 },
{ kGreen, "Green", 0 },
{ kYellow, "Yellow", 0 },
{ kBlue, "Blue", 0 },
{ k0, "0", 0 },
{ k1, "1", 0 },
{ k2, "2", 0 },
{ k3, "3", 0 },
{ k4, "4", 0 },
{ k5, "5", 0 },
{ k6, "6", 0 },
{ k7, "7", 0 },
{ k8, "8", 0 },
{ k9, "9", 0 },
{ kPower, "Power", 0 },
{ kVolUp, "Volume+", 0 },
{ kVolDn, "Volume-", 0 },
{ kMute, "Mute", 0 },
{ kNone, "", 0 },
};
cKeys::cKeys(void)
{
fileName = NULL;
code = 0;
address = 0;
keys = keyTable;
}
void cKeys::Clear(void)
{
for (tKey *k = keys; k->type != kNone; k++)
k->code = 0;
}
void cKeys::SetDummyValues(void)
{
for (tKey *k = keys; k->type != kNone; k++)
k->code = k->type + 1; // '+1' to avoid 0
}
bool cKeys::Load(const char *FileName)
{
isyslog(LOG_INFO, "loading %s", FileName);
bool result = false;
if (FileName)
fileName = strdup(FileName);
if (fileName) {
FILE *f = fopen(fileName, "r");
if (f) {
int line = 0;
char buffer[MAXPARSEBUFFER];
result = true;
while (fgets(buffer, sizeof(buffer), f) > 0) {
line++;
if (!isempty(buffer)) {
char *Name = buffer;
char *p = strpbrk(Name, " \t");
if (p) {
*p = 0; // terminates 'Name'
while (*++p && isspace(*p))
;
if (*p) {
if (strcasecmp(Name, "Code") == 0)
code = *p;
else if (strcasecmp(Name, "Address") == 0)
address = strtol(p, NULL, 16);
else {
for (tKey *k = keys; k->type != kNone; k++) {
if (strcasecmp(Name, k->name) == 0) {
k->code = strtol(p, NULL, 16);
Name = NULL; // to indicate that we found it
break;
}
}
if (Name) {
esyslog(LOG_ERR, "unknown key in %s, line %d\n", fileName, line);
result = false;
break;
}
}
}
continue;
}
esyslog(LOG_ERR, "error in %s, line %d\n", fileName, line);
result = false;
break;
}
}
fclose(f);
}
else
esyslog(LOG_ERR, "can't open '%s'\n", fileName);
}
else
esyslog(LOG_ERR, "no key configuration file name supplied!\n");
return result;
}
bool cKeys::Save(void)
{
cSafeFile f(fileName);
if (f.Open()) {
fprintf(f, "Code\t%c\nAddress\t%04X\n", code, address);
for (tKey *k = keys; k->type != kNone; k++)
fprintf(f, "%s\t%08X\n", k->name, k->code);
return f.Close();
}
return false;
}
eKeys cKeys::Get(unsigned int Code)
{
if (Code != 0) {
tKey *k;
for (k = keys; k->type != kNone; k++) {
if (k->code == Code)
break;
}
return k->type;
}
return kNone;
}
eKeys cKeys::Translate(const char *Command)
{
if (Command) {
const tKey *k = keys;
while ((k->type != kNone) && strcasecmp(k->name, Command) != 0)
k++;
return k->type;
}
return kNone;
}
unsigned int cKeys::Encode(const char *Command)
{
eKeys k = Translate(Command);
if (k != kNone)
return keys[k].code;
return 0;
}
void cKeys::Set(eKeys Key, unsigned int Code)
{
for (tKey *k = keys; k->type != kNone; k++) {
if (k->type == Key) {
k->code = Code;
break;
}
}
}
// -- cChannel ---------------------------------------------------------------
char *cChannel::buffer = NULL;
cChannel::cChannel(void)
{
*name = 0;
}
cChannel::cChannel(const cChannel *Channel)
{
strcpy(name, Channel ? Channel->name : "Pro7");
frequency = Channel ? Channel->frequency : 12480;
polarization = Channel ? Channel->polarization : 'v';
diseqc = Channel ? Channel->diseqc : 0;
srate = Channel ? Channel->srate : 27500;
vpid = Channel ? Channel->vpid : 255;
apid1 = Channel ? Channel->apid1 : 256;
apid2 = Channel ? Channel->apid2 : 0;
dpid1 = Channel ? Channel->dpid1 : 257;
dpid2 = Channel ? Channel->dpid2 : 0;
tpid = Channel ? Channel->tpid : 32;
ca = Channel ? Channel->ca : 0;
pnr = Channel ? Channel->pnr : 0;
groupSep = Channel ? Channel->groupSep : false;
}
const char *cChannel::ToText(cChannel *Channel)
{
char buf[MaxChannelName * 2];
char *s = Channel->name;
if (strchr(s, ':')) {
s = strcpy(buf, s);
strreplace(s, ':', '|');
}
delete buffer;
if (Channel->groupSep)
asprintf(&buffer, ":%s\n", s);
else {
char apidbuf[32];
char *q = apidbuf;
q += snprintf(q, sizeof(apidbuf), "%d", Channel->apid1);
if (Channel->apid2)
q += snprintf(q, sizeof(apidbuf) - (q - apidbuf), ",%d", Channel->apid2);
if (Channel->dpid1 || Channel->dpid2)
q += snprintf(q, sizeof(apidbuf) - (q - apidbuf), ";%d", Channel->dpid1);
if (Channel->dpid2)
q += snprintf(q, sizeof(apidbuf) - (q - apidbuf), ",%d", Channel->dpid2);
*q = 0;
asprintf(&buffer, "%s:%d:%c:%d:%d:%d:%s:%d:%d:%d\n", s, Channel->frequency, Channel->polarization, Channel->diseqc, Channel->srate, Channel->vpid, apidbuf, Channel->tpid, Channel->ca, Channel->pnr);
}
return buffer;
}
const char *cChannel::ToText(void)
{
return ToText(this);
}
bool cChannel::Parse(const char *s)
{
char *buffer = NULL;
if (*s == ':') {
if (*++s) {
strn0cpy(name, s, MaxChannelName);
name[strlen(name) - 1] = 0; // strip the '\n'
groupSep = true;
}
else
return false;
}
else {
groupSep = false;
char *apidbuf = NULL;
int fields = sscanf(s, "%a[^:]:%d:%c:%d:%d:%d:%a[^:]:%d:%d:%d", &buffer, &frequency, &polarization, &diseqc, &srate, &vpid, &apidbuf, &tpid, &ca, &pnr);
apid1 = apid2 = 0;
dpid1 = dpid2 = 0;
if (apidbuf) {
char *p = strchr(apidbuf, ';');
if (p)
*p++ = 0;
sscanf(apidbuf, "%d,%d", &apid1, &apid2);
if (p)
sscanf(p, "%d,%d", &dpid1, &dpid2);
delete apidbuf;
}
else
return false;
if (fields >= 9) {
if (fields == 9) {
// allow reading of old format
pnr = ca;
ca = tpid;
tpid = 0;
}
strn0cpy(name, buffer, MaxChannelName);
delete buffer;
}
else
return false;
}
strreplace(name, '|', ':');
return true;
}
bool cChannel::Save(FILE *f)
{
return fprintf(f, ToText()) > 0;
}
bool cChannel::Switch(cDvbApi *DvbApi, bool Log)
{
if (!DvbApi)
DvbApi = cDvbApi::PrimaryDvbApi;
if (!DvbApi->Recording() && !groupSep) {
if (Log) {
isyslog(LOG_INFO, "switching to channel %d", number);
}
for (int i = 3; i--;) {
switch (DvbApi->SetChannel(number, frequency, polarization, diseqc, srate, vpid, apid1, apid2, dpid1, dpid2, tpid, ca, pnr)) {
case scrOk: return true;
case scrNoTransfer: if (Interface)
Interface->Error(tr("Can't start Transfer Mode!"));
return false;
case scrFailed: break; // loop will retry
}
esyslog(LOG_ERR, "retrying");
}
return false;
}
if (DvbApi->Recording())
Interface->Error(tr("Channel locked (recording)!"));
return false;
}
// -- cTimer -----------------------------------------------------------------
char *cTimer::buffer = NULL;
cTimer::cTimer(bool Instant)
{
startTime = stopTime = 0;
recording = pending = false;
active = Instant;
cChannel *ch = Channels.GetByNumber(cDvbApi::CurrentChannel());
channel = ch ? ch->number : 0;
time_t t = time(NULL);
struct tm *now = localtime(&t);
day = now->tm_mday;
start = now->tm_hour * 100 + now->tm_min;
stop = start + 200; // "instant recording" records 2 hours by default
if (stop >= 2400)
stop -= 2400;
//TODO VPS???
priority = Setup.DefaultPriority;
lifetime = Setup.DefaultLifetime;
*file = 0;
summary = NULL;
if (Instant && ch)
snprintf(file, sizeof(file), "%s%s", Setup.MarkInstantRecord ? "@" : "", ch->name);
}
cTimer::cTimer(const cEventInfo *EventInfo)
{
startTime = stopTime = 0;
recording = pending = false;
active = true;
cChannel *ch = Channels.GetByServiceID(EventInfo->GetServiceID());
channel = ch ? ch->number : 0;
time_t tstart = EventInfo->GetTime();
time_t tstop = tstart + EventInfo->GetDuration() + Setup.MarginStop * 60;
tstart -= Setup.MarginStart * 60;
struct tm *time = localtime(&tstart);
day = time->tm_mday;
start = time->tm_hour * 100 + time->tm_min;
time = localtime(&tstop);
stop = time->tm_hour * 100 + time->tm_min;
if (stop >= 2400)
stop -= 2400;
priority = Setup.DefaultPriority;
lifetime = Setup.DefaultLifetime;
*file = 0;
const char *Title = EventInfo->GetTitle();
if (!isempty(Title))
strn0cpy(file, EventInfo->GetTitle(), sizeof(file));
summary = NULL;
}
cTimer::~cTimer()
{
delete summary;
}
cTimer& cTimer::operator= (const cTimer &Timer)
{
memcpy(this, &Timer, sizeof(*this));
if (summary)
summary = strdup(summary);
return *this;
}
bool cTimer::operator< (const cTimer &Timer)
{
time_t t1 = StartTime();
time_t t2 = (*(cTimer *)&Timer).StartTime();
return t1 < t2 || (t1 == t2 && priority > Timer.priority);
}
const char *cTimer::ToText(cTimer *Timer)
{
delete buffer;
strreplace(Timer->file, ':', '|');
strreplace(Timer->summary, '\n', '|');
asprintf(&buffer, "%d:%d:%s:%04d:%04d:%d:%d:%s:%s\n", Timer->active, Timer->channel, PrintDay(Timer->day), Timer->start, Timer->stop, Timer->priority, Timer->lifetime, Timer->file, Timer->summary ? Timer->summary : "");
strreplace(Timer->summary, '|', '\n');
strreplace(Timer->file, '|', ':');
return buffer;
}
const char *cTimer::ToText(void)
{
return ToText(this);
}
int cTimer::TimeToInt(int t)
{
return (t / 100 * 60 + t % 100) * 60;
}
int cTimer::ParseDay(const char *s)
{
char *tail;
int d = strtol(s, &tail, 10);
if (tail && *tail) {
d = 0;
if (tail == s) {
if (strlen(s) == 7) {
for (const char *p = s + 6; p >= s; p--) {
d <<= 1;
d |= (*p != '-');
}
d |= 0x80000000;
}
}
}
else if (d < 1 || d > 31)
d = 0;
return d;
}
const char *cTimer::PrintDay(int d)
{
static char buffer[8];
if ((d & 0x80000000) != 0) {
char *b = buffer;
const char *w = tr("MTWTFSS");
*b = 0;
while (*w) {
*b++ = (d & 1) ? *w : '-';
d >>= 1;
w++;
}
}
else
sprintf(buffer, "%d", d);
return buffer;
}
bool cTimer::Parse(const char *s)
{
char *buffer1 = NULL;
char *buffer2 = NULL;
delete summary;
summary = NULL;
//XXX Apparently sscanf() doesn't work correctly if the last %a argument
//XXX results in an empty string (this first occured when the EIT gathering
//XXX was put into a separate thread - don't know why this happens...
//XXX As a cure we copy the original string and add a blank.
//XXX If anybody can shed some light on why sscanf() failes here, I'd love
//XXX to hear about that!
char *s2 = NULL;
int l2 = strlen(s);
while (l2 > 0 && isspace(s[l2 - 1]))
l2--;
if (s[l2 - 1] == ':') {
s2 = (char *)malloc(l2 + 3);
strcat(strn0cpy(s2, s, l2 + 1), " \n");
s = s2;
}
if (8 <= sscanf(s, "%d:%d:%a[^:]:%d:%d:%d:%d:%a[^:\n]:%a[^\n]", &active, &channel, &buffer1, &start, &stop, &priority, &lifetime, &buffer2, &summary)) {
if (summary && !*skipspace(summary)) {
delete summary;
summary = NULL;
}
//TODO add more plausibility checks
day = ParseDay(buffer1);
strn0cpy(file, buffer2, MaxFileName);
strreplace(file, '|', ':');
strreplace(summary, '|', '\n');
delete buffer1;
delete buffer2;
delete s2;
return day != 0;
}
delete s2;
return false;
}
bool cTimer::Save(FILE *f)
{
return fprintf(f, ToText()) > 0;
}
bool cTimer::IsSingleEvent(void)
{
return (day & 0x80000000) == 0;
}
int cTimer::GetMDay(time_t t)
{
return localtime(&t)->tm_mday;
}
int cTimer::GetWDay(time_t t)
{
int weekday = localtime(&t)->tm_wday;
return weekday == 0 ? 6 : weekday - 1; // we start with monday==0!
}
bool cTimer::DayMatches(time_t t)
{
return IsSingleEvent() ? GetMDay(t) == day : (day & (1 << GetWDay(t))) != 0;
}
time_t cTimer::IncDay(time_t t, int Days)
{
tm tm = *localtime(&t);
tm.tm_mday += Days; // now tm_mday may be out of its valid range
int h = tm.tm_hour; // save original hour to compensate for DST change
t = mktime(&tm); // normalize all values
tm.tm_hour = h; // compensate for DST change
return mktime(&tm); // calculate final result
}
time_t cTimer::SetTime(time_t t, int SecondsFromMidnight)
{
tm tm = *localtime(&t);
tm.tm_hour = SecondsFromMidnight / 3600;
tm.tm_min = (SecondsFromMidnight % 3600) / 60;
tm.tm_sec = SecondsFromMidnight % 60;
return mktime(&tm);
}
bool cTimer::Matches(time_t t)
{
startTime = stopTime = 0;
if (t == 0)
t = time(NULL);
int begin = TimeToInt(start); // seconds from midnight
int length = TimeToInt(stop) - begin;
if (length < 0)
length += SECSINDAY;
int DaysToCheck = IsSingleEvent() ? 31 : 7;
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 (t <= b) {
startTime = a;
stopTime = b;
break;
}
}
}
return active && startTime <= t && t < stopTime; // must stop *before* stopTime to allow adjacent timers
}
time_t cTimer::StartTime(void)
{
if (!startTime)
Matches();
return startTime;
}
time_t cTimer::StopTime(void)
{
if (!stopTime)
Matches();
return stopTime;
}
void cTimer::SetRecording(bool Recording)
{
recording = Recording;
isyslog(LOG_INFO, "timer %d %s", Index() + 1, recording ? "start" : "stop");
}
void cTimer::SetPending(bool Pending)
{
pending = Pending;
}
// --- cCommand -------------------------------------------------------------
char *cCommand::result = NULL;
cCommand::cCommand(void)
{
title = command = NULL;
}
cCommand::~cCommand()
{
delete title;
delete command;
}
bool cCommand::Parse(const char *s)
{
const char *p = strchr(s, ':');
if (p) {
int l = p - s;
if (l > 0) {
title = new char[l + 1];
strn0cpy(title, s, l + 1);
if (!isempty(title)) {
command = stripspace(strdup(skipspace(p + 1)));
return !isempty(command);
}
}
}
return false;
}
const char *cCommand::Execute(void)
{
dsyslog(LOG_INFO, "executing command '%s'", command);
delete result;
result = NULL;
FILE *p = popen(command, "r");
if (p) {
int l = 0;
int c;
while ((c = fgetc(p)) != EOF) {
if (l % 20 == 0)
result = (char *)realloc(result, l + 21);
result[l++] = c;
}
if (result)
result[l] = 0;
pclose(p);
}
else
esyslog(LOG_ERR, "ERROR: can't open pipe for command '%s'", command);
return result;
}
// -- cKeys ------------------------------------------------------------------
cKeys Keys;
// -- cCommands --------------------------------------------------------------
cCommands Commands;
// -- cChannels --------------------------------------------------------------
cChannels Channels;
bool cChannels::Load(const char *FileName)
{
if (cConfig<cChannel>::Load(FileName)) {
ReNumber();
return true;
}
return false;
}
int cChannels::GetNextGroup(int Idx)
{
cChannel *channel = Get(++Idx);
while (channel && !channel->groupSep)
channel = Get(++Idx);
return channel ? Idx : -1;
}
int cChannels::GetPrevGroup(int Idx)
{
cChannel *channel = Get(--Idx);
while (channel && !channel->groupSep)
channel = Get(--Idx);
return channel ? Idx : -1;
}
int cChannels::GetNextNormal(int Idx)
{
cChannel *channel = Get(++Idx);
while (channel && channel->groupSep)
channel = Get(++Idx);
return channel ? Idx : -1;
}
void cChannels::ReNumber( void )
{
int Number = 0;
cChannel *ch = (cChannel *)First();
while (ch) {
if (!ch->groupSep)
ch->number = ++Number;
ch = (cChannel *)ch->Next();
}
maxNumber = Number;
}
cChannel *cChannels::GetByNumber(int Number)
{
cChannel *channel = (cChannel *)First();
while (channel) {
if (channel->number == Number)
return channel;
channel = (cChannel *)channel->Next();
}
return NULL;
}
cChannel *cChannels::GetByServiceID(unsigned short ServiceId)
{
cChannel *channel = (cChannel *)First();
while (channel) {
if (channel->pnr == ServiceId)
return channel;
channel = (cChannel *)channel->Next();
}
return NULL;
}
bool cChannels::SwitchTo(int Number, cDvbApi *DvbApi)
{
cChannel *channel = GetByNumber(Number);
return channel && channel->Switch(DvbApi);
}
const char *cChannels::GetChannelNameByNumber(int Number)
{
cChannel *channel = GetByNumber(Number);
return channel ? channel->name : NULL;
}
// -- cTimers ----------------------------------------------------------------
cTimers Timers;
cTimer *cTimers::GetTimer(cTimer *Timer)
{
cTimer *ti = (cTimer *)First();
while (ti) {
if (ti->channel == Timer->channel && ti->day == Timer->day && ti->start == Timer->start && ti->stop == Timer->stop)
return ti;
ti = (cTimer *)ti->Next();
}
return NULL;
}
cTimer *cTimers::GetMatch(time_t t)
{
cTimer *t0 = NULL;
cTimer *ti = First();
while (ti) {
if (!ti->recording && ti->Matches(t)) {
if (!t0 || ti->priority > t0->priority)
t0 = ti;
}
ti = (cTimer *)ti->Next();
}
return t0;
}
cTimer *cTimers::GetNextActiveTimer(void)
{
cTimer *t0 = NULL;
cTimer *ti = First();
while (ti) {
if (ti->active && (!t0 || *ti < *t0))
t0 = ti;
ti = (cTimer *)ti->Next();
}
return t0;
}
// -- cSetup -----------------------------------------------------------------
cSetup Setup;
char *cSetup::fileName = NULL;
cSetup::cSetup(void)
{
OSDLanguage = 0;
PrimaryDVB = 1;
ShowInfoOnChSwitch = 1;
MenuScrollPage = 1;
MarkInstantRecord = 1;
LnbSLOF = 11700;
LnbFrequLo = 9750;
LnbFrequHi = 10600;
DiSEqC = 0;
SetSystemTime = 0;
MarginStart = 2;
MarginStop = 10;
EPGScanTimeout = 5;
EPGBugfixLevel = 2;
SVDRPTimeout = 300;
SortTimers = 1;
PrimaryLimit = 0;
DefaultPriority = 50;
DefaultLifetime = 50;
UseSubtitle = 1;
VideoFormat = VIDEO_FORMAT_4_3;
ChannelInfoPos = 0;
OSDwidth = 52;
OSDheight = 18;
OSDMessageTime = 1;
MaxVideoFileSize = MAXVIDEOFILESIZE;
MinEventTimeout = 30;
MinUserInactivity = 120;
MultiSpeedMode = 0;
ShowReplayMode = 0;
CurrentChannel = -1;
}
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, "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, "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
return false;
return true;
}
return false;
}
bool cSetup::Load(const char *FileName)
{
isyslog(LOG_INFO, "loading %s", FileName);
delete fileName;
fileName = strdup(FileName);
FILE *f = fopen(fileName, "r");
if (f) {
int line = 0;
char buffer[MAXPARSEBUFFER];
bool result = true;
while (fgets(buffer, sizeof(buffer), f) > 0) {
line++;
if (!isempty(buffer)) {
if (*buffer != '#' && !Parse(buffer)) {
esyslog(LOG_ERR, "error in %s, line %d\n", fileName, line);
result = false;
break;
}
}
}
fclose(f);
return result;
}
else
LOG_ERROR_STR(FileName);
return false;
}
bool cSetup::Save(const char *FileName)
{
if (!FileName)
FileName = fileName;
if (FileName) {
cSafeFile f(FileName);
if (f.Open()) {
fprintf(f, "# VDR Setup\n");
fprintf(f, "OSDLanguage = %d\n", OSDLanguage);
fprintf(f, "PrimaryDVB = %d\n", PrimaryDVB);
fprintf(f, "ShowInfoOnChSwitch = %d\n", ShowInfoOnChSwitch);
fprintf(f, "MenuScrollPage = %d\n", MenuScrollPage);
fprintf(f, "MarkInstantRecord = %d\n", MarkInstantRecord);
fprintf(f, "LnbSLOF = %d\n", LnbSLOF);
fprintf(f, "LnbFrequLo = %d\n", LnbFrequLo);
fprintf(f, "LnbFrequHi = %d\n", LnbFrequHi);
fprintf(f, "DiSEqC = %d\n", DiSEqC);
fprintf(f, "SetSystemTime = %d\n", SetSystemTime);
fprintf(f, "MarginStart = %d\n", MarginStart);
fprintf(f, "MarginStop = %d\n", MarginStop);
fprintf(f, "EPGScanTimeout = %d\n", EPGScanTimeout);
fprintf(f, "EPGBugfixLevel = %d\n", EPGBugfixLevel);
fprintf(f, "SVDRPTimeout = %d\n", SVDRPTimeout);
fprintf(f, "SortTimers = %d\n", SortTimers);
fprintf(f, "PrimaryLimit = %d\n", PrimaryLimit);
fprintf(f, "DefaultPriority = %d\n", DefaultPriority);
fprintf(f, "DefaultLifetime = %d\n", DefaultLifetime);
fprintf(f, "UseSubtitle = %d\n", UseSubtitle);
fprintf(f, "VideoFormat = %d\n", VideoFormat);
fprintf(f, "ChannelInfoPos = %d\n", ChannelInfoPos);
fprintf(f, "OSDwidth = %d\n", OSDwidth);
fprintf(f, "OSDheight = %d\n", OSDheight);
fprintf(f, "OSDMessageTime = %d\n", OSDMessageTime);
fprintf(f, "MaxVideoFileSize = %d\n", MaxVideoFileSize);
fprintf(f, "MinEventTimeout = %d\n", MinEventTimeout);
fprintf(f, "MinUserInactivity = %d\n", MinUserInactivity);
fprintf(f, "MultiSpeedMode = %d\n", MultiSpeedMode);
fprintf(f, "ShowReplayMode = %d\n", ShowReplayMode);
fprintf(f, "CurrentChannel = %d\n", CurrentChannel);
if (f.Close()) {
isyslog(LOG_INFO, "saved setup to %s", FileName);
return true;
}
}
}
else
esyslog(LOG_ERR, "attempt to save setup without file name");
return false;
}