From patchwork Sat Sep 1 13:49:09 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Klaus Schmidinger X-Patchwork-Id: 14130 Received: from localhost ([127.0.0.1] helo=www.linuxtv.org) by www.linuxtv.org with esmtp (Exim 4.72) (envelope-from ) id 1T7o53-0005d4-Ec; Sat, 01 Sep 2012 15:49:45 +0200 Received: from mail.tu-berlin.de ([130.149.7.33]) by www.linuxtv.org with esmtp (Exim 4.72) (envelope-from ) id 1T7o4c-0005ct-2c for vdr@linuxtv.org; Sat, 01 Sep 2012 15:49:43 +0200 X-tubIT-Incoming-IP: 188.40.50.18 Received: from racoon.tvdr.de ([188.40.50.18]) by mail.tu-berlin.de (exim-4.75/mailfrontend-2) with esmtps [TLSv1:AES256-SHA:256] for id 1T7o4b-0002MP-Ir; Sat, 01 Sep 2012 15:49:17 +0200 Received: from dolphin.tvdr.de (dolphin.tvdr.de [192.168.100.2]) by racoon.tvdr.de (8.14.5/8.14.5) with ESMTP id q81DnGES024863 for ; Sat, 1 Sep 2012 15:49:16 +0200 Received: from [192.168.100.10] (hawk.tvdr.de [192.168.100.10]) by dolphin.tvdr.de (8.14.4/8.14.4) with ESMTP id q81Dn9II013146 for ; Sat, 1 Sep 2012 15:49:09 +0200 Message-ID: <50421255.3050204@tvdr.de> Date: Sat, 01 Sep 2012 15:49:09 +0200 From: Klaus Schmidinger User-Agent: Mozilla/5.0 (X11; Linux i686; rv:15.0) Gecko/20120825 Thunderbird/15.0 MIME-Version: 1.0 To: vdr@linuxtv.org References: <4F802386.2080706@gmx.de> <4F8142C8.4040005@gmx.de> <4F81C974.6030809@gmx.de> <4F82B1D9.6090908@tvdr.de> <4F82E1A7.6020906@gmx.de> <4F82F094.8020509@tvdr.de> <4FAA810A.10209@gmx.de> In-Reply-To: <4FAA810A.10209@gmx.de> X-PMX-Version: 5.6.1.2065439, Antispam-Engine: 2.7.2.376379, Antispam-Data: 2012.9.1.134219 X-PMX-Spam: Gauge=IIIIIIII, Probability=8%, Report=' HTML_00_01 0.05, HTML_00_10 0.05, MIME_TEXT_ONLY_MP_MIXED 0.05, BODYTEXTP_SIZE_3000_LESS 0, BODY_SIZE_10000_PLUS 0, __ANY_URI 0, __BAT_BOUNDARY 0, __BOUNCE_CHALLENGE_SUBJ 0, __BOUNCE_NDR_SUBJ_EXEMPT 0, __CT 0, __CTYPE_HAS_BOUNDARY 0, __CTYPE_MULTIPART 0, __CTYPE_MULTIPART_MIXED 0, __FW_1LN_BOT_MSGID 0, __HAS_FROM 0, __HAS_MSGID 0, __MIME_TEXT_ONLY 0, __MIME_VERSION 0, __MOZILLA_MSGID 0, __SANE_MSGID 0, __TO_MALFORMED_2 0, __TO_NO_NAME 0, __URI_NO_MAILTO 0, __URI_NO_PATH 0, __URI_NO_WWW 0, __USER_AGENT 0' X-LSpam-Score: -1.1 (-) X-LSpam-Report: No, score=-1.1 required=5.0 tests=BAYES_00=-1.9, RDNS_NONE=0.793 autolearn=no Subject: Re: [vdr] Filesystem hierachy standard patch needs review. X-BeenThere: vdr@linuxtv.org X-Mailman-Version: 2.1.13 Precedence: list Reply-To: VDR Mailing List List-Id: VDR Mailing List List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: vdr-bounces@linuxtv.org Errors-To: vdr-bounces@linuxtv.org On 09.05.2012 16:36, Manuel Reimer wrote: > Hello, > > what is the current status in this topic? Anyone working on this? Attached is a revised version of the patch, as I intend to adopt it in version 1.7.30. Please try it and let me know if it works as expected. Klaus diff -u -b -r2.13 ./INSTALL --- ./INSTALL 2012/06/03 09:24:21 2.13 +++ ./INSTALL 2012/09/01 10:35:08 @@ -386,6 +386,15 @@ VDR archive into your video directory (or into your config directory, respectively, in case you have redirected it with the -c option). +If you prefer to have your system set up according to the FHS +("File system Hierarchy Standard") and thus have your files spread +all over the place ;-), you can do this by copying the file Make.config.template +to Make.config in the VDR source directory, and activating the line + +#USEFHS = 1 + +in that file. + Setting up DiSEqC: ------------------ diff -u -b -r2.8 ./Make.config.template --- ./Make.config.template 2012/03/20 11:20:13 2.8 +++ ./Make.config.template 2012/09/01 10:31:33 @@ -28,11 +28,22 @@ MANDIR = $(PREFIX)/man BINDIR = $(PREFIX)/bin +# By default locale and plugin files are built under the source directory: LOCDIR = ./locale PLUGINDIR = ./PLUGINS PLUGINLIBDIR = $(PLUGINDIR)/lib +# By default VDR requires only one single directory to operate: VIDEODIR = /video -CONFDIR = $(VIDEODIR) +# Activate the following line to build VDR according to the FHS ("File system Hierarchy Standard"): +#USEFHS = 1 +ifdef USEFHS +VIDEODIR = /srv/vdr/video +CONFDIR = /var/lib/vdr +CACHEDIR = /var/cache/vdr +RESDIR = $(PREFIX)/share/vdr +LOCDIR = $(PREFIX)/share/locale +PLUGINLIBDIR = $(PREFIX)/lib/vdr +endif ### The remote control: diff -u -b -r2.27 ./Makefile --- ./Makefile 2012/04/15 13:21:31 2.27 +++ ./Makefile 2012/09/01 13:22:33 @@ -27,8 +27,9 @@ PLUGINDIR= ./PLUGINS PLUGINLIBDIR= $(PLUGINDIR)/lib +# By default VDR requires only one single directory to operate: VIDEODIR = /video -CONFDIR = $(VIDEODIR) +# See Make.config.template if you want to build VDR according to the FHS ("File system Hierarchy Standard") DOXYGEN ?= /usr/bin/doxygen DOXYFILE = Doxyfile @@ -70,6 +71,8 @@ DEFINES += -DVIDEODIR=\"$(VIDEODIR)\" DEFINES += -DCONFDIR=\"$(CONFDIR)\" +DEFINES += -DCACHEDIR=\"$(CACHEDIR)\" +DEFINES += -DRESDIR=\"$(RESDIR)\" DEFINES += -DPLUGINDIR=\"$(PLUGINLIBDIR)\" DEFINES += -DLOCDIR=\"$(LOCDIR)\" @@ -111,6 +114,8 @@ @echo "includedir=$(INCDIR)" >> $@ @echo "configdir=$(CONFDIR)" >> $@ @echo "videodir=$(VIDEODIR)" >> $@ + @echo "cachedir=$(CACHEDIR)" >> $@ + @echo "resdir=$(RESDIR)" >> $@ @echo "plugindir=$(PLUGINLIBDIR)" >> $@ @echo "localedir=$(LOCDIR)" >> $@ @echo "apiversion=$(APIVERSION)" >> $@ @@ -183,7 +188,7 @@ # Install the files: -install: install-bin install-conf install-doc install-plugins install-i18n install-includes install-pc +install: install-bin install-dirs install-conf install-doc install-plugins install-i18n install-includes install-pc # VDR binary: @@ -193,12 +198,15 @@ # Configuration files: -install-conf: +install-dirs: @mkdir -p $(DESTDIR)$(VIDEODIR) - @if [ ! -d $(DESTDIR)$(CONFDIR) ]; then\ - mkdir -p $(DESTDIR)$(CONFDIR);\ - cp *.conf $(DESTDIR)$(CONFDIR);\ - fi + @mkdir -p $(DESTDIR)$(CONFDIR) + @mkdir -p $(DESTDIR)$(CACHEDIR) + @mkdir -p $(DESTDIR)$(RESDIR) + +install-conf: + @cp *.conf $(DESTDIR)$(CONFDIR) + # Documentation: diff -u -b -r2.15 ./PLUGINS.html --- ./PLUGINS.html 2012/08/26 13:09:01 2.15 +++ ./PLUGINS.html 2012/08/31 12:46:07 @@ -82,7 +82,7 @@
  • Wakeup
  • Setup parameters
  • The Setup menu -
  • Configuration files +
  • Additional files
  • Internationalization
  • Custom services
  • SVDRP commands @@ -885,39 +885,70 @@ your setup parameters and use that one to copy all parameters with one single statement (like VDR does with its cSetup class). -

    Configuration files

    +

    Additional files

    I want my own stuff!

    -There may be situations where a plugin requires configuration files of its own, maybe -for data that can't be stored in the simple setup parameters -of VDR, or maybe because it needs to launch other programs that simply need a separate -configuration file. While the plugin is free to store such files anywhere it -sees fit, it might be a good idea to put them in a common place, preferably -where other configuration data already exists. VDR provides the function + +There may be situations where a plugin requires files of its own. While the plugin is +free to store such files anywhere it sees fit, it might be a good idea to put them in a common +place, preferably where such data already exists. + +

    + +configuration files, maybe for data that can't be stored in the simple +setup parameters of VDR, or maybe because it needs to +launch other programs that simply need a separate configuration file. + +

    + +cache files, to store data so that future requests for that data can be served faster. The data +that is stored within a cache might be values that have been computed earlier or duplicates of +original values that are stored elsewhere. + +

    + +resource files, for providing additional files, like pictures, movie clips or channel logos. + +

    + +Threfore VDR provides the functions

    +
     const char *ConfigDirectory(const char *PluginName = NULL);
    +const char *CacheDirectory(const char *PluginName = NULL);
    +const char *ResourceDirectory(const char *PluginName = NULL);
    +
     

    -which returns a string containing the directory that VDR uses for its own configuration -files (defined through the -c option in the call to VDR), extended by + +each of which returns a string containing the directory that VDR uses for its own +files (defined through the options in the call to VDR), extended by + "/plugins". So assuming the VDR configuration directory is /video (the default if no -c or -v option is given), a call to ConfigDirectory() will return /video/plugins. The first call to ConfigDirectory() will automatically make sure that the plugins subdirectory will exist. If, for some reason, this cannot be achieved, NULL will be returned. + +The behavoir of CacheDirectory() and ResourceDirectory() is similar. +

    The additional plugins directory is used to keep files from plugins apart from those of VDR itself, making sure there will be no name clashes. If a plugin -needs only one extra configuration file, it is suggested that this file be named -name.conf, where name shall be the name of the plugin. + +needs only one extra file, it is suggested that this file be named name.*, +where name shall be the name of the plugin. +

    If a plugin needs more than one such file, it is suggested that the plugin stores these in a subdirectory of its own, named after the plugin. To easily get such a name -the ConfigDirectory() function can be given an additional string that will -be appended to the returned directory name, as in + +the functions can be given an additional string that will be appended to the returned +directory name, as in +

     const char *MyConfigDir = ConfigDirectory(Name());
    @@ -928,13 +959,16 @@
     (or return NULL in case of an error).
     

    -The returned string is statically allocated and will be overwritten by subsequent -calls to ConfigDirectory()! + +The returned strings are statically allocated and will be overwritten by subsequent calls! +

    -The ConfigDirectory() function is a static member function of the cPlugin -class. This allows it to be called even from outside any member function of the derived -plugin class, by writing + +The ConfigDirectory(), CacheDirectory() and ResourceDirectory() +functions are static member functions of the cPlugin class. This allows them to be +called even from outside any member function of the derived plugin class, by writing +

     const char *MyConfigDir = cPlugin::ConfigDirectory();
    diff -u -b -r2.4 ./i18n.c
    --- ./i18n.c	2011/08/15 10:01:45	2.4
    +++ ./i18n.c	2012/09/01 10:53:43
    @@ -63,7 +63,7 @@
       NULL
       };
     
    -static const char *I18nLocaleDir = LOCDIR;
    +static cString I18nLocaleDir;
     
     static cStringList LanguageLocales;
     static cStringList LanguageNames;
    @@ -102,7 +102,6 @@
     
     void I18nInitialize(const char *LocaleDir)
     {
    -  if (LocaleDir)
          I18nLocaleDir = LocaleDir;
       LanguageLocales.Append(strdup(I18N_DEFAULT_LOCALE));
       LanguageNames.Append(strdup(SkipContext(LanguageName)));
    @@ -113,7 +112,7 @@
       if (Locales.Size() > 0) {
          char *OldLocale = strdup(setlocale(LC_MESSAGES, NULL));
          for (int i = 0; i < Locales.Size(); i++) {
    -         cString FileName = cString::sprintf("%s/%s/LC_MESSAGES/vdr.mo", I18nLocaleDir, Locales[i]);
    +         cString FileName = cString::sprintf("%s/%s/LC_MESSAGES/vdr.mo", *I18nLocaleDir, Locales[i]);
              if (access(FileName, F_OK) == 0) { // found a locale with VDR texts
                 if (NumLocales < I18N_MAX_LANGUAGES - 1) {
                    SetEnvLanguage(Locales[i]);
    @@ -142,7 +141,7 @@
              }
          SetEnvLanguage(LanguageLocales[CurrentLanguage]);
          free(OldLocale);
    -     dsyslog("found %d locales in %s", NumLocales - 1, I18nLocaleDir);
    +     dsyslog("found %d locales in %s", NumLocales - 1, *I18nLocaleDir);
          }
       // Prepare any known language codes for which there was no locale:
       for (const char **lc = LanguageCodeList; *lc; lc++) {
    diff -u -b -r2.3 ./plugin.c
    --- ./plugin.c	2012/03/11 13:56:02	2.3
    +++ ./plugin.c	2012/09/01 13:10:27
    @@ -25,7 +25,9 @@
     
     // --- cPlugin ---------------------------------------------------------------
     
    -char *cPlugin::configDirectory = NULL;
    +cString cPlugin::configDirectory;
    +cString cPlugin::cacheDirectory;
    +cString cPlugin::resourceDirectory;
     
     cPlugin::cPlugin(void)
     {
    @@ -132,8 +134,7 @@
     
     void cPlugin::SetConfigDirectory(const char *Dir)
     {
    -  free(configDirectory);
    -  configDirectory = strdup(Dir);
    +  configDirectory = Dir;
     }
     
     const char *cPlugin::ConfigDirectory(const char *PluginName)
    @@ -141,7 +142,35 @@
       static cString buffer;
       if (!cThread::IsMainThread())
          esyslog("ERROR: plugin '%s' called cPlugin::ConfigDirectory(), which is not thread safe!", PluginName ? PluginName : "");
    -  buffer = cString::sprintf("%s/plugins%s%s", configDirectory, PluginName ? "/" : "", PluginName ? PluginName : "");
    +  buffer = cString::sprintf("%s/plugins%s%s", *configDirectory, PluginName ? "/" : "", PluginName ? PluginName : "");
    +  return MakeDirs(buffer, true) ? *buffer : NULL;
    +}
    +
    +void cPlugin::SetCacheDirectory(const char *Dir)
    +{
    +  cacheDirectory = Dir;
    +}
    +
    +const char *cPlugin::CacheDirectory(const char *PluginName)
    +{
    +  static cString buffer;
    +  if (!cThread::IsMainThread())
    +     esyslog("ERROR: plugin '%s' called cPlugin::CacheDirectory(), which is not thread safe!", PluginName ? PluginName : "");
    +  buffer = cString::sprintf("%s/plugins%s%s", *cacheDirectory, PluginName ? "/" : "", PluginName ? PluginName : "");
    +  return MakeDirs(buffer, true) ? *buffer : NULL;
    +}
    +
    +void cPlugin::SetResourceDirectory(const char *Dir)
    +{
    +  resourceDirectory = Dir;
    +}
    +
    +const char *cPlugin::ResourceDirectory(const char *PluginName)
    +{
    +  static cString buffer;
    +  if (!cThread::IsMainThread())
    +     esyslog("ERROR: plugin '%s' called cPlugin::ResourceDirectory(), which is not thread safe!", PluginName ? PluginName : "");
    +  buffer = cString::sprintf("%s/plugins%s%s", *resourceDirectory, PluginName ? "/" : "", PluginName ? PluginName : "");
       return MakeDirs(buffer, true) ? *buffer : NULL;
     }
     
    diff -u -b -r2.1 ./plugin.h
    --- ./plugin.h	2012/03/11 13:55:56	2.1
    +++ ./plugin.h	2012/09/01 13:08:54
    @@ -21,7 +21,9 @@
       friend class cDll;
       friend class cPluginManager;
     private:
    -  static char *configDirectory;
    +  static cString configDirectory;
    +  static cString cacheDirectory;
    +  static cString resourceDirectory;
       const char *name;
       bool started;
       void SetName(const char *s);
    @@ -57,6 +59,10 @@
     
       static void SetConfigDirectory(const char *Dir);
       static const char *ConfigDirectory(const char *PluginName = NULL);
    +  static void SetCacheDirectory(const char *Dir);
    +  static const char *CacheDirectory(const char *PluginName = NULL);
    +  static void SetResourceDirectory(const char *Dir);
    +  static const char *ResourceDirectory(const char *PluginName = NULL);
       };
     
     class cDll : public cListObject {
    diff -u -b -r2.8 ./vdr.1
    --- ./vdr.1	2012/02/27 11:01:17	2.8
    +++ ./vdr.1	2012/09/01 13:40:49
    @@ -42,6 +42,10 @@
     .BI \-a\  cmd ,\ \-\-audio= cmd
     Send Dolby Digital audio to stdin of command \fIcmd\fR.
     .TP
    +.BI \-\-cachedir= dir
    +save cache files in \fIdir\fR
    +(default is to save them in the video directory).
    +.TP
     .BI \-c\  dir ,\ \-\-config= dir
     Read config files from directory \fIdir\fR
     (default is to read them from the video directory).
    @@ -157,6 +161,10 @@
     Call \fIcmd\fR before and after a recording. See the file \fIINSTALL\fR for
     more information.
     .TP
    +.BI \-\-resdir= dir
    +read resource files from \fIdir\fR
    +(default is to read them from the config directory).
    +.TP
     .BI \-s\  cmd ,\ \-\-shutdown= cmd
     Call \fIcmd\fR to shutdown the computer. See the file \fIINSTALL\fR for more
     information.
    diff -u -b -r2.37 ./vdr.c
    --- ./vdr.c	2012/06/13 11:28:41	2.37
    +++ ./vdr.c	2012/09/01 13:30:19
    @@ -178,10 +178,15 @@
     
       // Command line options:
     
    +#define dd(a, b) (*a ? a : b)
     #define DEFAULTSVDRPPORT 6419
     #define DEFAULTWATCHDOG     0 // seconds
    -#define DEFAULTCONFDIR CONFDIR
    +#define DEFAULTVIDEODIR VIDEODIR
    +#define DEFAULTCONFDIR dd(CONFDIR, VideoDirectory)
    +#define DEFAULTCACHEDIR dd(CACHEDIR, VideoDirectory)
    +#define DEFAULTRESDIR dd(RESDIR, ConfigDirectory)
     #define DEFAULTPLUGINDIR PLUGINDIR
    +#define DEFAULTLOCDIR LOCDIR
     #define DEFAULTEPGDATAFILENAME "epg.data"
     
       bool StartedAsRoot = false;
    @@ -189,7 +194,11 @@
       bool UserDump = false;
       int SVDRPport = DEFAULTSVDRPPORT;
       const char *AudioCommand = NULL;
    +  const char *VideoDirectory = DEFAULTVIDEODIR;
       const char *ConfigDirectory = NULL;
    +  const char *CacheDirectory = NULL;
    +  const char *ResourceDirectory = NULL;
    +  const char *LocaleDirectory = DEFAULTLOCDIR;
       const char *EpgDataFileName = DEFAULTEPGDATAFILENAME;
       bool DisplayHelp = false;
       bool DisplayVersion = false;
    @@ -198,7 +207,6 @@
       bool MuteAudio = false;
       int WatchdogTimeout = DEFAULTWATCHDOG;
       const char *Terminal = NULL;
    -  const char *LocaleDir = NULL;
     
       bool UseKbd = true;
       const char *LircDevice = NULL;
    @@ -216,6 +224,7 @@
     
       static struct option long_options[] = {
           { "audio",    required_argument, NULL, 'a' },
    +      { "cachedir", required_argument, NULL, 'c' | 0x100 },
           { "config",   required_argument, NULL, 'c' },
           { "daemon",   no_argument,       NULL, 'd' },
           { "device",   required_argument, NULL, 'D' },
    @@ -235,6 +244,7 @@
           { "plugin",   required_argument, NULL, 'P' },
           { "port",     required_argument, NULL, 'p' },
           { "record",   required_argument, NULL, 'r' },
    +      { "resdir",   required_argument, NULL, 'r' | 0x100 },
           { "shutdown", required_argument, NULL, 's' },
           { "split",    no_argument,       NULL, 's' | 0x100 },
           { "terminal", required_argument, NULL, 't' },
    @@ -252,6 +262,9 @@
             switch (c) {
               case 'a': AudioCommand = optarg;
                         break;
    +          case 'c' | 0x100:
    +                    CacheDirectory = optarg;
    +                    break;
               case 'c': ConfigDirectory = optarg;
                         break;
               case 'd': DaemonMode = true; break;
    @@ -327,7 +340,7 @@
                         break;
               case 'l' | 0x200:
                         if (access(optarg, R_OK | X_OK) == 0)
    -                       LocaleDir = optarg;
    +                       LocaleDirectory = optarg;
                         else {
                            fprintf(stderr, "vdr: can't access locale directory: %s\n", optarg);
                            return 2;
    @@ -349,6 +362,9 @@
                         break;
               case 'r': cRecordingUserCommand::SetCommand(optarg);
                         break;
    +          case 'r' | 0x100:
    +                    ResourceDirectory = optarg;
    +                    break;
               case 's': ShutdownHandler.SetShutdownCommand(optarg);
                         break;
               case 's' | 0x100:
    @@ -414,6 +430,7 @@
          if (DisplayHelp) {
             printf("Usage: vdr [OPTIONS]\n\n"          // for easier orientation, this is column 80|
                    "  -a CMD,   --audio=CMD    send Dolby Digital audio to stdin of command CMD\n"
    +               "            --cachedir=DIR save cache files in DIR (default: %s)\n"
                    "  -c DIR,   --config=DIR   read config files from DIR (default: %s)\n"
                    "  -d,       --daemon       run in daemon mode\n"
                    "  -D NUM,   --device=NUM   use only the given DVB device (NUM = 0, 1, 2...)\n"
    @@ -450,6 +467,7 @@
                    "                           0 turns off SVDRP\n"
                    "  -P OPT,   --plugin=OPT   load a plugin defined by the given options\n"
                    "  -r CMD,   --record=CMD   call CMD before and after a recording\n"
    +               "            --resdir=DIR   read resource files from DIR (default: %s)\n"
                    "  -s CMD,   --shutdown=CMD call CMD to shutdown the computer\n"
                    "            --split        split edited files at the editing marks (only\n"
                    "                           useful in conjunction with --edit)\n"
    @@ -464,14 +482,16 @@
                    "  -w SEC,   --watchdog=SEC activate the watchdog timer with a timeout of SEC\n"
                    "                           seconds (default: %d); '0' disables the watchdog\n"
                    "\n",
    +               DEFAULTCACHEDIR,
                    DEFAULTCONFDIR,
                    DEFAULTEPGDATAFILENAME,
                    MAXVIDEOFILESIZEDEFAULT,
                    DEFAULTPLUGINDIR,
                    LIRC_DEVICE,
    -               LOCDIR,
    +               DEFAULTLOCDIR,
                    DEFAULTSVDRPPORT,
    -               VideoDirectory,
    +               DEFAULTRESDIR,
    +               DEFAULTVIDEODIR,
                    DEFAULTWATCHDOG
                    );
             }
    @@ -555,7 +575,7 @@
     
       // Initialize internationalization:
     
    -  I18nInitialize(LocaleDir);
    +  I18nInitialize(LocaleDirectory);
     
       // Main program loop variables - need to be here to have them initialized before any EXIT():
     
    @@ -577,14 +597,22 @@
       if (!PluginManager.LoadPlugins(true))
          EXIT(2);
     
    -  // Configuration data:
    +  // Directories:
     
    +  SetVideoDirectory(VideoDirectory);
       if (!ConfigDirectory)
          ConfigDirectory = DEFAULTCONFDIR;
    -
       cPlugin::SetConfigDirectory(ConfigDirectory);
    +  if (!CacheDirectory)
    +     CacheDirectory = DEFAULTCACHEDIR;
    +  cPlugin::SetCacheDirectory(CacheDirectory);
    +  if (!ResourceDirectory)
    +     ResourceDirectory = DEFAULTRESDIR;
    +  cPlugin::SetResourceDirectory(ResourceDirectory);
       cThemes::SetThemesDirectory(AddDirectory(ConfigDirectory, "themes"));
     
    +  // Configuration data:
    +
       Setup.Load(AddDirectory(ConfigDirectory, "setup.conf"));
       Sources.Load(AddDirectory(ConfigDirectory, "sources.conf"), true, true);
       Diseqcs.Load(AddDirectory(ConfigDirectory, "diseqc.conf"), true, Setup.DiSEqC);
    @@ -618,7 +646,7 @@
             EpgDataFileName = DEFAULTEPGDATAFILENAME;
             }
          else if (*EpgDataFileName != '/' && *EpgDataFileName != '.')
    -        EpgDirectory = VideoDirectory;
    +        EpgDirectory = CacheDirectory;
          if (EpgDirectory)
             cSchedules::SetEpgDataFileName(AddDirectory(EpgDirectory, EpgDataFileName));
          else
    diff -u -b -r2.2 ./videodir.c
    --- ./videodir.c	2012/06/10 13:45:21	2.2
    +++ ./videodir.c	2012/09/01 10:57:44
    @@ -21,6 +21,11 @@
     
     const char *VideoDirectory = VIDEODIR;
     
    +void SetVideoDirectory(const char *Directory)
    +{
    +  VideoDirectory = strdup(Directory);
    +}
    +
     class cVideoDirectory {
     private:
       char *name, *stored, *adjusted;
    diff -u -b -r2.1 ./videodir.h
    --- ./videodir.h	2012/04/22 15:07:56	2.1
    +++ ./videodir.h	2012/09/01 10:57:07
    @@ -15,6 +15,7 @@
     
     extern const char *VideoDirectory;
     
    +void SetVideoDirectory(const char *Directory);
     cUnbufferedFile *OpenVideoFile(const char *FileName, int Flags);
     int CloseVideoFile(cUnbufferedFile *File);
     bool RenameVideoFile(const char *OldName, const char *NewName);