MythTV  master
mythdirs.cpp
Go to the documentation of this file.
1 #include <iostream>
2 #include <cstdlib>
3 
4 #include <QtGlobal>
5 #include <QDir>
6 #include <QCoreApplication>
7 
8 #if defined(Q_OS_ANDROID)
9 #include <QStandardPaths>
10 #include <sys/statfs.h>
11 #elif defined(Q_OS_WIN)
12 #include <QStandardPaths>
13 #endif
14 
15 #include "mythdirs.h"
16 #include "mythlogging.h"
17 
18 static QString installprefix;
19 static QString appbindir;
20 static QString sharedir;
21 static QString libdir;
22 static QString confdir;
23 static QString themedir;
24 static QString pluginsdir;
25 static QString translationsdir;
26 static QString filtersdir;
27 static QString cachedir;
28 static QString remotecachedir;
29 static QString themebasecachedir;
30 static QString thumbnaildir;
31 
33 {
34  installprefix = qgetenv( "MYTHTVDIR" );
35  confdir = qgetenv( "MYTHCONFDIR" );
36 
37  if (!confdir.isEmpty())
38  {
39  LOG(VB_GENERAL, LOG_NOTICE, QString("Read conf dir = %1").arg(confdir));
40  confdir.replace("$HOME", QDir::homePath());
41  }
42 
43 #ifdef _WIN32
44 
45  if (installprefix.isEmpty())
46  installprefix = QDir( qApp->applicationDirPath() )
47  .absolutePath();
48 
49  appbindir = installprefix + "/";
50  libdir = appbindir;
51 
52  // Turn into Canonical Path for consistent compares
53 
54  QDir sDir(qgetenv("ProgramData") + "/mythtv/");
55  if (sDir.exists())
56  sharedir = sDir.canonicalPath() + "/";
57 
58  if(sharedir.isEmpty())
59  {
60  sharedir = appbindir + "data/mythtv/";
61  }
62  if (confdir.isEmpty())
63  {
64  confdir = qgetenv( "LOCALAPPDATA" ) + "/mythtv";
65  confdir = QDir(confdir).canonicalPath() + "/";
66  }
67 
68  #if 0
69  // The following code only works for Qt 5.0 and above, but it may
70  // be a generic solution for both windows & linux.
71  // Re-evalute use oce min Qt == 5.0
72 
73  // QStringList sorted by least public to most.
74  // Assume first is private user data and last is shared program data.
75 
76  qApp->setOrganizationName( "mythtv" );
77 
78  QStringList lstPaths = QStandardPaths::standardLocations(
79  QStandardPaths::AppDataLocation);
80 
81  // Remove AppName from end of path
82 
83  QString sAppName = qApp->applicationName();
84  if (!lstPaths.isEmpty())
85  {
86  for (auto &path : lstPaths)
87  {
88  if (path.endsWith(sAppName))
89  path = path.left(path.length() - sAppName.length());
90  LOG(VB_GENERAL, LOG_DEBUG, QString("app data location: %1 (%2)")
91  .arg(path).arg(QDir(path).exists() ? "exists" : "doesn't exist"));
92  }
93 
94  sharedir = lstPaths.last();
95 
96  if (sharedir.endsWith( sAppName ))
97  sharedir = sharedir.left( sharedir.length() - sAppName.length());
98  }
99 
100  lstPaths = QStandardPaths::standardLocations(
101  QStandardPaths::AppConfigLocation);
102  if (!lstPaths.isEmpty())
103  {
104  for (auto &path : lstPaths)
105  {
106  if (path.endsWith(sAppName))
107  path = path.left(path.length() - sAppName.length());
108  LOG(VB_GENERAL, LOG_DEBUG, QString("app config location: %1 (%2)")
109  .arg(path).arg(QDir(path).exists() ? "exists" : "doesn't exist"));
110  }
111 
112  // Only use if user didn't override with env variable.
113  if (confdir.isEmpty())
114  {
115  confdir = lstPaths.first();
116 
117  if (confdir.endsWith( sAppName ))
118  confdir = confdir.left( confdir.length() - sAppName.length());
119  }
120  }
121 
122  #endif
123 
124  if (sharedir.isEmpty())
125  sharedir = confdir;
126  sharedir = QDir(sharedir).canonicalPath() + "/";
127 
128 #elif defined(Q_OS_ANDROID)
129  if (installprefix.isEmpty())
130  installprefix = QDir( qApp->applicationDirPath() )
131  .absolutePath();
132  QString extdir = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + "/Mythtv";
133  if (!QDir(extdir).exists())
134  QDir(extdir).mkdir(".");
135 
136  if (confdir.isEmpty())
137  confdir = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
138 
139 #if 0
140  // TODO allow choice of base fs or the SD card for data
141  QStringList appLocs = QStandardPaths::standardLocations(QStandardPaths::AppDataLocation);
142  uint64_t maxFreeSpace = 0;
143  for(auto s : appLocs)
144  {
145  struct statfs statFs;
146  memset(&statFs, 0, sizeof(statFs));
147  int ret = statfs(s.toLocal8Bit().data(), &statFs);
148  if (ret == 0 && statFs.f_bavail >= maxFreeSpace)
149  {
150  maxFreeSpace = statFs.f_bavail;
151  confdir = s;
152  }
153  LOG(VB_GENERAL, LOG_NOTICE, QString(" appdatadir = %1 (%2, %3, %4)")
154  .arg(s)
155  .arg(statFs.f_bavail)
156  .arg(statFs.f_bfree)
157  .arg(statFs.f_bsize));
158  }
159  QStringList cacheLocs = QStandardPaths::standardLocations(QStandardPaths::CacheLocation);
160  maxFreeSpace = 0;
161  for(auto s : cacheLocs)
162  {
163  struct statfs statFs;
164  memset(&statFs, 0, sizeof(statFs));
165  int ret = statfs(s.toLocal8Bit().data(), &statFs);
166  if (ret == 0 && statFs.f_bavail >= maxFreeSpace)
167  {
168  maxFreeSpace = statFs.f_bavail;
169  //confdir = s;
170  }
171  LOG(VB_GENERAL, LOG_NOTICE, QString(" cachedir = %1 (%2, %3, %4)")
172  .arg(s)
173  .arg(statFs.f_bavail)
174  .arg(statFs.f_bfree)
175  .arg(statFs.f_bsize));
176  }
177 #endif
178 
179  appbindir = installprefix + "/";
180  sharedir = "assets:/mythtv/";
181  libdir = installprefix + "/";
182 
183 #else
184 
185  if (installprefix.isEmpty())
186  installprefix = QString(RUNPREFIX);
187 
188  #if defined(Q_OS_DARWIN)
189  // Check to see if the RUNPREFIX exists, if it does not, this is
190  // likely an APP bundle and so RUNPREFIX needs to be pointed
191  // internally to the APP Bundle.
192  if (! QDir(installprefix).exists())
193  installprefix = QString("../Resources");
194  #endif
195 
196  QDir prefixDir = qApp->applicationDirPath();
197 
198  if (QDir(installprefix).isRelative())
199  {
200  // If the PREFIX is relative, evaluate it relative to our
201  // executable directory. This can be fragile on Unix, so
202  // use relative PREFIX values with care.
203 
204  LOG(VB_GENERAL, LOG_DEBUG, QString("Relative PREFIX! (%1), appDir=%2")
205  .arg(installprefix, prefixDir.canonicalPath()));
206 
207  if (!prefixDir.cd(installprefix))
208  {
209  LOG(VB_GENERAL, LOG_ERR,
210  QString("Relative PREFIX does not resolve, using %1")
211  .arg(prefixDir.canonicalPath()));
212  }
213  installprefix = prefixDir.canonicalPath();
214  }
215 
216  appbindir = installprefix + "/bin/";
217  sharedir = installprefix + "/share/mythtv/";
218  libdir = installprefix + '/' + QString(LIBDIRNAME) + "/mythtv/";
219 
220 #endif
221 
222  if (confdir.isEmpty())
223  confdir = QDir::homePath() + "/.mythtv";
224  cachedir = confdir + "/cache";
225  remotecachedir = cachedir + "/remotecache";
226  themebasecachedir = cachedir + "/themecache";
227  thumbnaildir = cachedir + "/thumbnails";
228 
229 #if defined(Q_OS_ANDROID)
230  themedir = sharedir + "themes/";
231  pluginsdir = libdir;
232  translationsdir = sharedir + "i18n/";
233  filtersdir = libdir;
234 #else
235  themedir = sharedir + "themes/";
236  pluginsdir = libdir + "plugins/";
237  translationsdir = sharedir + "i18n/";
238  filtersdir = libdir + "filters/";
239 #endif
240 
241  LOG(VB_GENERAL, LOG_NOTICE, "Using runtime prefix = " + installprefix);
242  LOG(VB_GENERAL, LOG_NOTICE, QString("Using configuration directory = %1")
243  .arg(confdir));
244 
245  LOG(VB_GENERAL, LOG_DEBUG, "appbindir = "+ appbindir );
246  LOG(VB_GENERAL, LOG_DEBUG, "sharedir = "+ sharedir );
247  LOG(VB_GENERAL, LOG_DEBUG, "libdir = "+ libdir );
248  LOG(VB_GENERAL, LOG_DEBUG, "themedir = "+ themedir );
249  LOG(VB_GENERAL, LOG_DEBUG, "pluginsdir = "+ pluginsdir );
250  LOG(VB_GENERAL, LOG_DEBUG, "translationsdir = "+ translationsdir );
251  LOG(VB_GENERAL, LOG_DEBUG, "filtersdir = "+ filtersdir );
252  LOG(VB_GENERAL, LOG_DEBUG, "confdir = "+ confdir );
253  LOG(VB_GENERAL, LOG_DEBUG, "cachedir = "+ cachedir );
254  LOG(VB_GENERAL, LOG_DEBUG, "remotecachedir = "+ remotecachedir );
255  LOG(VB_GENERAL, LOG_DEBUG, "themebasecachedir = "+ themebasecachedir);
256  LOG(VB_GENERAL, LOG_DEBUG, "thumbnaildir = "+ thumbnaildir);
257 }
258 
259 QString GetInstallPrefix(void) { return installprefix; }
260 QString GetAppBinDir(void) { return appbindir; }
261 QString GetShareDir(void) { return sharedir; }
262 QString GetLibraryDir(void) { return libdir; }
263 QString GetConfDir(void) { return confdir; }
264 QString GetThemesParentDir(void) { return themedir; }
265 QString GetPluginsDir(void) { return pluginsdir; }
266 QString GetTranslationsDir(void) { return translationsdir; }
267 QString GetFiltersDir(void) { return filtersdir; }
268 
273 QString GetCacheDir(void) { return cachedir; }
274 
280 QString GetRemoteCacheDir(void) { return remotecachedir; }
281 
288 QString GetThumbnailDir(void) { return thumbnaildir; }
289 
296 QString GetThemeBaseCacheDir(void) { return themebasecachedir; }
297 
298 // These defines provide portability for different
299 // plugin file names.
300 #ifdef Q_OS_DARWIN
301 static const QString kPluginLibPrefix = "lib";
302 static const QString kPluginLibSuffix = ".dylib";
303 static const QString kFilterLibPrefix = "lib";
304 static const QString kFilterLibSuffix = ".dylib";
305 #elif defined(_WIN32)
306 static const QString kPluginLibPrefix = "lib";
307 static const QString kPluginLibSuffix = ".dll";
308 static const QString kFilterLibPrefix = "lib";
309 static const QString kFilterLibSuffix = ".dll";
310 #elif defined(Q_OS_ANDROID)
311 static const QString kPluginLibPrefix = "libmythplugin";
312 static const QString kPluginLibSuffix = ".so";
313 static const QString kFilterLibPrefix = "libmythfilter";
314 static const QString kFilterLibSuffix = ".so";
315 #else
316 static const QString kPluginLibPrefix = "lib";
317 static const QString kPluginLibSuffix = ".so";
318 static const QString kFilterLibPrefix = "lib";
319 static const QString kFilterLibSuffix = ".so";
320 #endif
321 
322 QString GetFiltersNameFilter(void)
323 {
324  return kFilterLibPrefix + '*' + kFilterLibSuffix;
325 }
326 
327 QString GetPluginsNameFilter(void)
328 {
329  return kPluginLibPrefix + '*' + kPluginLibSuffix;
330 }
331 
332 QString FindPluginName(const QString &plugname)
333 {
334  return GetPluginsDir() + kPluginLibPrefix + plugname + kPluginLibSuffix;
335 }
336 
338 {
339  return "mythfrontend_*.qm";
340 }
341 
342 QString FindTranslation(const QString &translation)
343 {
344  return GetTranslationsDir()
345  + "mythfrontend_" + translation.toLower() + ".qm";
346 }
347 
348 QString GetFontsDir(void)
349 {
350  return GetShareDir() + "fonts/";
351 }
GetThemesParentDir
QString GetThemesParentDir(void)
Definition: mythdirs.cpp:264
themedir
static QString themedir
Definition: mythdirs.cpp:23
libdir
static QString libdir
Definition: mythdirs.cpp:21
installprefix
static QString installprefix
Definition: mythdirs.cpp:18
kFilterLibSuffix
static const QString kFilterLibSuffix
Definition: mythdirs.cpp:309
GetLibraryDir
QString GetLibraryDir(void)
Definition: mythdirs.cpp:262
xbmcvfs.exists
bool exists(str path)
Definition: xbmcvfs.py:51
GetFontsDir
QString GetFontsDir(void)
Definition: mythdirs.cpp:348
kPluginLibPrefix
static const QString kPluginLibPrefix
Definition: mythdirs.cpp:306
confdir
static QString confdir
Definition: mythdirs.cpp:22
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
GetPluginsDir
QString GetPluginsDir(void)
Definition: mythdirs.cpp:265
GetCacheDir
QString GetCacheDir(void)
Returns the base directory for all cached files.
Definition: mythdirs.cpp:273
mythdirs.h
InitializeMythDirs
void InitializeMythDirs(void)
Definition: mythdirs.cpp:32
GetFiltersNameFilter
QString GetFiltersNameFilter(void)
Definition: mythdirs.cpp:322
GetInstallPrefix
QString GetInstallPrefix(void)
Definition: mythdirs.cpp:259
themebasecachedir
static QString themebasecachedir
Definition: mythdirs.cpp:29
GetPluginsNameFilter
QString GetPluginsNameFilter(void)
Definition: mythdirs.cpp:327
mythlogging.h
GetConfDir
QString GetConfDir(void)
Definition: mythdirs.cpp:263
statfs
int statfs(const char *path, struct statfs *buffer)
Definition: compat.h:105
GetShareDir
QString GetShareDir(void)
Definition: mythdirs.cpp:261
GetThemeBaseCacheDir
QString GetThemeBaseCacheDir(void)
Returns the base directory where all theme related files should be cached.
Definition: mythdirs.cpp:296
translationsdir
static QString translationsdir
Definition: mythdirs.cpp:25
kFilterLibPrefix
static const QString kFilterLibPrefix
Definition: mythdirs.cpp:308
GetThumbnailDir
QString GetThumbnailDir(void)
Returns the directory where all non-theme thumbnail files should be cached.
Definition: mythdirs.cpp:288
GetRemoteCacheDir
QString GetRemoteCacheDir(void)
Returns the directory for all files cached from the backend.
Definition: mythdirs.cpp:280
GetFiltersDir
QString GetFiltersDir(void)
Definition: mythdirs.cpp:267
appbindir
static QString appbindir
Definition: mythdirs.cpp:19
remotecachedir
static QString remotecachedir
Definition: mythdirs.cpp:28
statfs
Definition: compat.h:93
statfs::f_bsize
long f_bsize
Definition: compat.h:95
GetAppBinDir
QString GetAppBinDir(void)
Definition: mythdirs.cpp:260
filtersdir
static QString filtersdir
Definition: mythdirs.cpp:26
statfs::f_bavail
long f_bavail
Definition: compat.h:98
pluginsdir
static QString pluginsdir
Definition: mythdirs.cpp:24
thumbnaildir
static QString thumbnaildir
Definition: mythdirs.cpp:30
kPluginLibSuffix
static const QString kPluginLibSuffix
Definition: mythdirs.cpp:307
GetTranslationsDir
QString GetTranslationsDir(void)
Definition: mythdirs.cpp:266
FindPluginName
QString FindPluginName(const QString &plugname)
Definition: mythdirs.cpp:332
sharedir
static QString sharedir
Definition: mythdirs.cpp:20
GetTranslationsNameFilter
QString GetTranslationsNameFilter(void)
Definition: mythdirs.cpp:337
FindTranslation
QString FindTranslation(const QString &translation)
Definition: mythdirs.cpp:342
cachedir
static QString cachedir
Definition: mythdirs.cpp:27