VDR now supports "Satellite Channel Routing" (SCR)

This commit is contained in:
Klaus Schmidinger 2011-09-11 14:09:03 +02:00
parent 78e89efee8
commit 413a0e6373
10 changed files with 292 additions and 52 deletions

View File

@ -2661,6 +2661,7 @@ Stephan Austerm
Lars Hanisch <dvb@flensrocker.de>
for suggesting to assign the source character 'V' to "Analog Video"
for a patch that was used to implement SCR (Satellite Channel Routing)
Alex Lasnier <alex@fepg.org>
for adding tuning support for ATSC devices

View File

@ -6743,8 +6743,15 @@ Video Disk Recorder Revision History
extends over TS packet boundaries is now done by locally skipping TS packets
in cFrameDetector.
2011-09-10: Version 1.7.22
2011-09-11: Version 1.7.22
- Fixed scaling subtitles in case the primary device's GetVideoSize() function doesn't
return actual values (thanks to Luca Olivetti).
- The DiSEqC codes are now copied in the call to cDiseqc::Execute().
- VDR now supports "Satellite Channel Routing" (SCR) (based on the "unicable" patch
from Lars Hanisch). Since "Unicable" is a registered trademark and stands for only
one of many implementations of SCR, the following changes have been made compared
to the patch, which need to be taken into account by people who have set up their
system using the patch:
- The 'U' parameter in the diseqc.conf file has been changed to 'S' ("Scr").
- The configuration file name has been changed from "unicable.conf" to "scr.conf".

View File

@ -386,6 +386,12 @@ accessed using DiSEqC, you have to go to the "Setup" menu and set the "DiSEqC"
parameter to "on". You also need to set up the file 'diseqc.conf' to properly
access your DiSEqC equipment (see man vdr(5) for details).
A special form of DiSEqC is used to connect several receivers to one signal
source using only a single cable. This method, known as "Satellite Channel Routing"
according to EN50494 (aka "Unicable(TM)", "OLT(TM)", "SatCR", "Single Cable
Distribution", "Channel Stacking System" or "Single Cable Interface") uses
the file "scr.conf" to specify which SCR channels use which user band frequency.
Running VDR with DVB-C (cable) or DVB-T (terrestrial):
------------------------------------------------------

118
diseqc.c
View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: diseqc.c 2.6 2011/09/10 13:38:38 kls Exp $
* $Id: diseqc.c 2.7 2011/09/11 13:39:48 kls Exp $
*/
#include "diseqc.h"
@ -12,6 +12,51 @@
#include "sources.h"
#include "thread.h"
// --- cScr ------------------------------------------------------------------
cScr::cScr(void)
{
channel = -1;
userBand = 0;
pin = -1;
used = false;
}
bool cScr::Parse(const char *s)
{
bool result = false;
int fields = sscanf(s, "%d %u %d", &channel, &userBand, &pin);
if (fields == 2 || fields == 3) {
if (channel >= 0 && channel < 8) {
result = true;
if (fields == 3 && (pin < 0 || pin > 255)) {
esyslog("Error: invalid SCR pin '%d'", pin);
result = false;
}
}
else
esyslog("Error: invalid SCR channel '%d'", channel);
}
return result;
}
// --- cScrs -----------------------------------------------------------------
cScrs Scrs;
cScr *cScrs::GetUnused(void)
{
cMutexLock MutexLock(&mutex);
for (cScr *p = First(); p; p = Next(p)) {
if (!p->Used()) {
p->SetUsed(true);
return p;
}
}
return NULL;
}
// --- cDiseqc ---------------------------------------------------------------
cDiseqc::cDiseqc(void)
@ -21,6 +66,7 @@ cDiseqc::cDiseqc(void)
slof = 0;
polarization = 0;
lof = 0;
scrBank = -1;
commands = NULL;
parsing = false;
}
@ -59,7 +105,7 @@ bool cDiseqc::Parse(const char *s)
if (polarization == 'V' || polarization == 'H' || polarization == 'L' || polarization == 'R') {
parsing = true;
const char *CurrentAction = NULL;
while (Execute(&CurrentAction, NULL, NULL) != daNone)
while (Execute(&CurrentAction, NULL, NULL, NULL, NULL) != daNone)
;
parsing = false;
result = !commands || !*CurrentAction;
@ -74,6 +120,31 @@ bool cDiseqc::Parse(const char *s)
return result;
}
uint cDiseqc::SetScrFrequency(uint SatFrequency, const cScr *Scr, uint8_t *Codes) const
{
uint t = SatFrequency == 0 ? 0 : (SatFrequency + Scr->UserBand() + 2) / 4 - 350;
if (t < 1024 && Scr->Channel() >= 0 && Scr->Channel() < 8) {
Codes[3] = t >> 8 | (t == 0 ? 0 : scrBank << 2) | Scr->Channel() << 5;
Codes[4] = t;
if (t)
return (t + 350) * 4 - SatFrequency;
}
return 0;
}
int cDiseqc::SetScrPin(const cScr *Scr, uint8_t *Codes) const
{
if (Scr->Pin() >= 0 && Scr->Pin() <= 255) {
Codes[2] = 0x5C;
Codes[5] = Scr->Pin();
return 6;
}
else {
Codes[2] = 0x5A;
return 5;
}
}
const char *cDiseqc::Wait(const char *s) const
{
char *p = NULL;
@ -88,6 +159,24 @@ const char *cDiseqc::Wait(const char *s) const
return NULL;
}
const char *cDiseqc::GetScrBank(const char *s) const
{
char *p = NULL;
errno = 0;
int n = strtol(s, &p, 10);
if (!errno && p != s && n >= 0 && n < 8) {
if (parsing) {
if (scrBank < 0)
scrBank = n;
else
esyslog("ERROR: more than one scr bank in '%s'", s - 1);
}
return p;
}
esyslog("ERROR: more than one scr bank in '%s'", s - 1);
return NULL;
}
const char *cDiseqc::GetCodes(const char *s, uchar *Codes, uint8_t *MaxCodes) const
{
const char *e = strchr(s, ']');
@ -129,7 +218,7 @@ const char *cDiseqc::GetCodes(const char *s, uchar *Codes, uint8_t *MaxCodes) co
return NULL;
}
cDiseqc::eDiseqcActions cDiseqc::Execute(const char **CurrentAction, uchar *Codes, uint8_t *MaxCodes) const
cDiseqc::eDiseqcActions cDiseqc::Execute(const char **CurrentAction, uchar *Codes, uint8_t *MaxCodes, const cScr *Scr, uint *Frequency) const
{
if (!*CurrentAction)
*CurrentAction = commands;
@ -143,7 +232,16 @@ cDiseqc::eDiseqcActions cDiseqc::Execute(const char **CurrentAction, uchar *Code
case 'A': return daMiniA;
case 'B': return daMiniB;
case 'W': *CurrentAction = Wait(*CurrentAction); break;
case '[': *CurrentAction = GetCodes(*CurrentAction, Codes, MaxCodes); return *CurrentAction ? daCodes : daNone;
case 'S': *CurrentAction = GetScrBank(*CurrentAction); break;
case '[': *CurrentAction = GetCodes(*CurrentAction, Codes, MaxCodes);
if (*CurrentAction) {
if (Scr && Frequency) {
*Frequency = SetScrFrequency(*Frequency, Scr, Codes);
*MaxCodes = SetScrPin(Scr, Codes);
}
return daCodes;
}
break;
default: return daNone;
}
}
@ -154,7 +252,7 @@ cDiseqc::eDiseqcActions cDiseqc::Execute(const char **CurrentAction, uchar *Code
cDiseqcs Diseqcs;
const cDiseqc *cDiseqcs::Get(int Device, int Source, int Frequency, char Polarization) const
const cDiseqc *cDiseqcs::Get(int Device, int Source, int Frequency, char Polarization, const cScr **Scr) const
{
int Devices = 0;
for (const cDiseqc *p = First(); p; p = Next(p)) {
@ -164,8 +262,16 @@ const cDiseqc *cDiseqcs::Get(int Device, int Source, int Frequency, char Polariz
}
if (Devices && !(Devices & (1 << Device - 1)))
continue;
if (p->Source() == Source && p->Slof() > Frequency && p->Polarization() == toupper(Polarization))
if (p->Source() == Source && p->Slof() > Frequency && p->Polarization() == toupper(Polarization)) {
if (p->IsScr() && Scr && !*Scr) {
*Scr = Scrs.GetUnused();
if (*Scr)
dsyslog("SCR %d assigned to device %d", (*Scr)->Index(), Device);
else
esyslog("ERROR: no free SCR entry available for device %d", Device);
}
return p;
}
}
return NULL;
}

View File

@ -18,6 +18,7 @@
# V voltage high (18V)
# A mini A
# B mini B
# Sn Satellite channel routing code sequence for bank n follows
# Wnn wait nn milliseconds (nn may be any positive integer number)
# [xx ...] hex code sequence (max. 6)
#
@ -75,3 +76,15 @@ S13.0E 99999 H 10600 t V W15 [E0 10 38 F7] W15 B W15 T
# S19.2E 99999 H 10560 t v
# S19.2E 12110 V 11080 t v
# S19.2E 99999 V 10720 t v
#
# SCR (Satellite Channel Routing):
#
# S19.2E 11700 V 9750 t V W10 S0 [E0 10 5A 00 00] W10 v
# S19.2E 99999 V 10600 t V W10 S1 [E0 10 5A 00 00] W10 v
# S19.2E 11700 H 9750 t V W10 S2 [E0 10 5A 00 00] W10 v
# S19.2E 99999 H 10600 t V W10 S3 [E0 10 5A 00 00] W10 v
#
# S13.0E 11700 V 9750 t V W10 S4 [E0 10 5A 00 00] W10 v
# S13.0E 99999 V 10600 t V W10 S5 [E0 10 5A 00 00] W10 v
# S13.0E 11700 H 9750 t V W10 S6 [E0 10 5A 00 00] W10 v
# S13.0E 99999 H 10600 t V W10 S7 [E0 10 5A 00 00] W10 v

View File

@ -4,13 +4,39 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: diseqc.h 2.3 2011/09/10 13:36:50 kls Exp $
* $Id: diseqc.h 2.4 2011/09/11 13:40:16 kls Exp $
*/
#ifndef __DISEQC_H
#define __DISEQC_H
#include "config.h"
#include "thread.h"
class cScr : public cListObject {
private:
int channel;
uint userBand;
int pin;
bool used;
public:
cScr(void);
bool Parse(const char *s);
int Channel(void) const { return channel; }
uint UserBand(void) const { return userBand; }
int Pin(void) const { return pin; }
bool Used(void) const { return used; }
void SetUsed(bool Used) { used = Used; }
};
class cScrs : public cConfig<cScr> {
private:
cMutex mutex;
public:
cScr *GetUnused(void);
};
extern cScrs Scrs;
class cDiseqc : public cListObject {
public:
@ -22,6 +48,7 @@ public:
daVoltage18,
daMiniA,
daMiniB,
daScr,
daCodes,
};
enum { MaxDiseqcCodes = 6 };
@ -31,37 +58,53 @@ private:
int slof;
char polarization;
int lof;
mutable int scrBank;
char *commands;
bool parsing;
uint SetScrFrequency(uint SatFrequency, const cScr *Scr, uint8_t *Codes) const;
int SetScrPin(const cScr *Scr, uint8_t *Codes) const;
const char *Wait(const char *s) const;
const char *GetScrBank(const char *s) const;
const char *GetCodes(const char *s, uchar *Codes = NULL, uint8_t *MaxCodes = NULL) const;
public:
cDiseqc(void);
~cDiseqc();
bool Parse(const char *s);
eDiseqcActions Execute(const char **CurrentAction, uchar *Codes, uint8_t *MaxCodes) const;
// Parses the DiSEqC commands and returns the appropriate action code
// with every call. CurrentAction must be the address of a character pointer,
// which is initialized to NULL. This pointer is used internally while parsing
// the commands and shall not be modified once Execute() has been called with
// it. Call Execute() repeatedly (always providing the same CurrentAction pointer)
// until it returns daNone. After a successful execution of all commands
// *CurrentAction points to the value 0x00.
// If the current action consists of sending code bytes to the device, those
// bytes will be copied into Codes. MaxCodes must be initialized to the maximum
// number of bytes Codes can handle, and will be set to the actual number of
// bytes copied to Codes upon return.
eDiseqcActions Execute(const char **CurrentAction, uchar *Codes, uint8_t *MaxCodes, const cScr *Scr, uint *Frequency) const;
///< Parses the DiSEqC commands and returns the appropriate action code
///< with every call. CurrentAction must be the address of a character pointer,
///< which is initialized to NULL. This pointer is used internally while parsing
///< the commands and shall not be modified once Execute() has been called with
///< it. Call Execute() repeatedly (always providing the same CurrentAction pointer)
///< until it returns daNone. After a successful execution of all commands
///< *CurrentAction points to the value 0x00.
///< If the current action consists of sending code bytes to the device, those
///< bytes will be copied into Codes. MaxCodes must be initialized to the maximum
///< number of bytes Codes can handle, and will be set to the actual number of
///< bytes copied to Codes upon return.
///< If this DiSEqC entry requires SCR, the given Scr will be used. This must
///< be a pointer returned from a previous call to cDiseqcs::Get().
///< Frequency must be the frequency the tuner will be tuned to, and will be
///< set to the proper SCR frequency upon return (if SCR is used).
int Devices(void) const { return devices; }
int Source(void) const { return source; }
int Slof(void) const { return slof; }
char Polarization(void) const { return polarization; }
int Lof(void) const { return lof; }
bool IsScr() const { return scrBank >= 0; }
const char *Commands(void) const { return commands; }
};
class cDiseqcs : public cConfig<cDiseqc> {
public:
const cDiseqc *Get(int Device, int Source, int Frequency, char Polarization) const;
const cDiseqc *Get(int Device, int Source, int Frequency, char Polarization, const cScr **Scr) const;
///< Selects a DiSEqC entry suitable for the given Device and tuning parameters.
///< If this DiSEqC entry requires SCR and the given *Scr is NULL
///< a free one will be selected from the Scrs and a pointer to that will
///< be returned in Scr. The caller shall memorize that pointer and reuse it in
///< subsequent calls.
///< Scr may be NULL for checking whether there is any DiSEqC entry for the
///< given transponder.
};
extern cDiseqcs Diseqcs;

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: dvbdevice.c 2.44 2011/09/10 13:34:02 kls Exp $
* $Id: dvbdevice.c 2.45 2011/09/11 13:50:20 kls Exp $
*/
#include "dvbdevice.h"
@ -267,13 +267,15 @@ private:
time_t lastTimeoutReport;
fe_delivery_system frontendType;
cChannel channel;
const char *diseqcCommands;
const cDiseqc *lastDiseqc;
const cScr *scr;
eTunerStatus tunerStatus;
cMutex mutex;
cCondVar locked;
cCondVar newSet;
void ClearEventQueue(void) const;
bool GetFrontendStatus(fe_status_t &Status) const;
void ExecuteDiseqc(const cDiseqc *Diseqc, unsigned int *Frequency) const;
bool SetFrontend(void);
virtual void Action(void);
public:
@ -299,7 +301,8 @@ cDvbTuner::cDvbTuner(int Device, int Fd_Frontend, int Adapter, int Frontend, fe_
tuneTimeout = 0;
lockTimeout = 0;
lastTimeoutReport = 0;
diseqcCommands = NULL;
lastDiseqc = NULL;
scr = NULL;
tunerStatus = tsIdle;
if (frontendType == SYS_DVBS || frontendType == SYS_DVBS2)
CHECK(ioctl(fd_frontend, FE_SET_VOLTAGE, SEC_VOLTAGE_13)); // must explicitly turn on LNB power
@ -313,6 +316,10 @@ cDvbTuner::~cDvbTuner()
newSet.Broadcast();
locked.Broadcast();
Cancel(3);
if (lastDiseqc && lastDiseqc->IsScr()) {
unsigned int Frequency = 0;
ExecuteDiseqc(lastDiseqc, &Frequency);
}
}
bool cDvbTuner::IsTunedTo(const cChannel *Channel) const
@ -482,6 +489,30 @@ static unsigned int FrequencyToHz(unsigned int f)
return f;
}
void cDvbTuner::ExecuteDiseqc(const cDiseqc *Diseqc, unsigned int *Frequency) const
{
struct dvb_diseqc_master_cmd cmd;
const char *CurrentAction = NULL;
for (;;) {
cmd.msg_len = sizeof(cmd.msg);
cDiseqc::eDiseqcActions da = Diseqc->Execute(&CurrentAction, cmd.msg, &cmd.msg_len, scr, Frequency);
if (da == cDiseqc::daNone)
break;
switch (da) {
case cDiseqc::daToneOff: CHECK(ioctl(fd_frontend, FE_SET_TONE, SEC_TONE_OFF)); break;
case cDiseqc::daToneOn: CHECK(ioctl(fd_frontend, FE_SET_TONE, SEC_TONE_ON)); break;
case cDiseqc::daVoltage13: CHECK(ioctl(fd_frontend, FE_SET_VOLTAGE, SEC_VOLTAGE_13)); break;
case cDiseqc::daVoltage18: CHECK(ioctl(fd_frontend, FE_SET_VOLTAGE, SEC_VOLTAGE_18)); break;
case cDiseqc::daMiniA: CHECK(ioctl(fd_frontend, FE_DISEQC_SEND_BURST, SEC_MINI_A)); break;
case cDiseqc::daMiniB: CHECK(ioctl(fd_frontend, FE_DISEQC_SEND_BURST, SEC_MINI_B)); break;
case cDiseqc::daCodes: CHECK(ioctl(fd_frontend, FE_DISEQC_SEND_MASTER_CMD, &cmd)); break;
default: esyslog("ERROR: unknown diseqc command %d", da);
}
}
if (scr)
CHECK(ioctl(fd_frontend, FE_SET_VOLTAGE, SEC_VOLTAGE_13)); // makes sure we don't block the bus!
}
bool cDvbTuner::SetFrontend(void)
{
#define MAXFRONTENDCMDS 16
@ -509,30 +540,14 @@ bool cDvbTuner::SetFrontend(void)
if (frontendType == SYS_DVBS || frontendType == SYS_DVBS2) {
unsigned int frequency = channel.Frequency();
if (Setup.DiSEqC) {
const cDiseqc *diseqc = Diseqcs.Get(device, channel.Source(), frequency, dtp.Polarization());
if (diseqc) {
if (diseqc->Commands() && (!diseqcCommands || strcmp(diseqcCommands, diseqc->Commands()) != 0)) {
struct dvb_diseqc_master_cmd cmd;
const char *CurrentAction = NULL;
for (;;) {
cmd.msg_len = sizeof(cmd.msg);
cDiseqc::eDiseqcActions da = diseqc->Execute(&CurrentAction, cmd.msg, &cmd.msg_len);
if (da == cDiseqc::daNone)
break;
switch (da) {
case cDiseqc::daToneOff: CHECK(ioctl(fd_frontend, FE_SET_TONE, SEC_TONE_OFF)); break;
case cDiseqc::daToneOn: CHECK(ioctl(fd_frontend, FE_SET_TONE, SEC_TONE_ON)); break;
case cDiseqc::daVoltage13: CHECK(ioctl(fd_frontend, FE_SET_VOLTAGE, SEC_VOLTAGE_13)); break;
case cDiseqc::daVoltage18: CHECK(ioctl(fd_frontend, FE_SET_VOLTAGE, SEC_VOLTAGE_18)); break;
case cDiseqc::daMiniA: CHECK(ioctl(fd_frontend, FE_DISEQC_SEND_BURST, SEC_MINI_A)); break;
case cDiseqc::daMiniB: CHECK(ioctl(fd_frontend, FE_DISEQC_SEND_BURST, SEC_MINI_B)); break;
case cDiseqc::daCodes: CHECK(ioctl(fd_frontend, FE_DISEQC_SEND_MASTER_CMD, &cmd)); break;
default: esyslog("ERROR: unknown diseqc command %d", da);
}
}
diseqcCommands = diseqc->Commands();
}
if (const cDiseqc *diseqc = Diseqcs.Get(device, channel.Source(), frequency, dtp.Polarization(), &scr)) {
frequency -= diseqc->Lof();
if (diseqc != lastDiseqc || diseqc->IsScr()) {
ExecuteDiseqc(diseqc, &frequency);
if (frequency == 0)
return false;
lastDiseqc = diseqc;
}
}
else {
esyslog("ERROR: no DiSEqC parameters found for channel %d", channel.Number());
@ -651,7 +666,7 @@ void cDvbTuner::Action(void)
case tsTuned:
if (Timer.TimedOut()) {
tunerStatus = tsSet;
diseqcCommands = NULL;
lastDiseqc = NULL;
if (time(NULL) - lastTimeoutReport > 60) { // let's not get too many of these
isyslog("frontend %d/%d timed out while tuning to channel %d, tp %d", adapter, frontend, channel.Number(), channel.Transponder());
lastTimeoutReport = time(NULL);
@ -661,7 +676,7 @@ void cDvbTuner::Action(void)
case tsLocked:
if (Status & FE_REINIT) {
tunerStatus = tsSet;
diseqcCommands = NULL;
lastDiseqc = NULL;
isyslog("frontend %d/%d was reinitialized", adapter, frontend);
lastTimeoutReport = 0;
continue;
@ -1036,7 +1051,7 @@ bool cDvbDevice::ProvidesTransponder(const cChannel *Channel) const
dtp.Modulation() == PSK_8 && !(frontendInfo.caps & FE_CAN_TURBO_FEC) && dtp.System() == SYS_DVBS) // "turbo fec" is a non standard FEC used by North American broadcasters - this is a best guess to determine this condition
return false; // requires modulation system which frontend doesn't provide
if (!cSource::IsSat(Channel->Source()) ||
!Setup.DiSEqC || Diseqcs.Get(CardIndex() + 1, Channel->Source(), Channel->Frequency(), dtp.Polarization()))
!Setup.DiSEqC || Diseqcs.Get(CardIndex() + 1, Channel->Source(), Channel->Frequency(), dtp.Polarization(), NULL))
return DeviceHooksProvidesTransponder(Channel);
return false;
}

20
scr.conf Normal file
View File

@ -0,0 +1,20 @@
# SCR (Satellite Channel Routing) configuration for VDR
#
# Format:
#
# channel frequency [pin]
#
# channel: SCR channel index (0-7)
# frequency: frequency of the SCR channel ("user band")
# pin: optional pin of the SCR channel (0-255)
#
# Examples:
# 0 1284
# 1 1400
# 2 1516
# 3 1632
# 4 1748
# 5 1864
# 6 1980
# 7 2096

30
vdr.5
View File

@ -8,7 +8,7 @@
.\" License as specified in the file COPYING that comes with the
.\" vdr distribution.
.\"
.\" $Id: vdr.5 2.23 2011/08/21 14:06:50 kls Exp $
.\" $Id: vdr.5 2.24 2011/09/10 14:45:00 kls Exp $
.\"
.TH vdr 5 "10 Feb 2008" "1.6" "Video Disk Recorder Files"
.SH NAME
@ -467,6 +467,7 @@ l l.
\fBV\fR@voltage high (18V)
\fBA\fR@mini A
\fBB\fR@mini B
\fBSn\fR@Satellite channel routing code sequence for bank n follows
\fBWnn\fR@wait nn milliseconds (nn may be any positive integer number)
\fB[xx ...]\fR@hex code sequence (max. 6)
.TE
@ -484,6 +485,33 @@ to receive the satellites following thereafter. In this case, only the devices
1, 2 and 4 would be able to receive any satellites following this line and up
to the next such line, or the end of the file. Devices may be listed more than
once.
.SS SATELLITE CHANNEL ROUTING (SCR)
The file \fIscr.conf\fR contains the channel definitions of the SCR device in use.
The format is
channel frequency [pin]
where channel is the SCR device's channel index (0-7), frequency is the user band
frequency of the given channel, and pin is an optional pin number (0-255). The
actual values are device specific and can be found in the SCR device's manual.
Examples:
0 1284
.br
1 1400
.br
2 1516
.br
3 1632
.br
4 1748
.br
5 1864
.br
6 1980
.br
7 2096
.SS REMOTE CONTROL KEYS
The file \fIremote.conf\fR contains the key assignments for all remote control
units. Each line consists of one key assignment in the following format:

3
vdr.c
View File

@ -22,7 +22,7 @@
*
* The project's page is at http://www.tvdr.de
*
* $Id: vdr.c 2.23 2011/08/15 12:42:39 kls Exp $
* $Id: vdr.c 2.24 2011/09/10 15:03:23 kls Exp $
*/
#include <getopt.h>
@ -598,6 +598,7 @@ int main(int argc, char *argv[])
Setup.Load(AddDirectory(ConfigDirectory, "setup.conf"));
Sources.Load(AddDirectory(ConfigDirectory, "sources.conf"), true, true);
Diseqcs.Load(AddDirectory(ConfigDirectory, "diseqc.conf"), true, Setup.DiSEqC);
Scrs.Load(AddDirectory(ConfigDirectory, "scr.conf"), true);
Channels.Load(AddDirectory(ConfigDirectory, "channels.conf"), false, true);
Timers.Load(AddDirectory(ConfigDirectory, "timers.conf"));
Commands.Load(AddDirectory(ConfigDirectory, "commands.conf"));