MythTV  master
dirscan.cpp
Go to the documentation of this file.
1 #include <map>
2 
3 #include <QDir>
4 #include <QUrl>
5 
6 #include "libmyth/mythcontext.h"
11 
12 #include "dbaccess.h"
13 #include "dirscan.h"
14 #include "videoutils.h"
15 
16 namespace
17 {
18  class ext_lookup
19  {
20  private:
21  using ext_map = std::map<QString, bool>;
24 
25  public:
27  bool list_unknown) : m_listUnknown(list_unknown)
28  {
29  for (const auto & ext : ext_disposition)
30  {
31  m_extensions.insert(ext_map::value_type(ext.first.toLower(),
32  ext.second));
33  }
34  }
35 
36  bool extension_ignored(const QString &extension) const
37  {
38  //NOLINTNEXTLINE(modernize-use-auto)
39  ext_map::const_iterator p = m_extensions.find(extension.toLower());
40  if (p != m_extensions.end())
41  return p->second;
42  return !m_listUnknown;
43  }
44  };
45 
46  bool scan_dir(const QString &start_path, DirectoryHandler *handler,
47  const ext_lookup &ext_settings)
48  {
49  QDir d(start_path);
50 
51  // Return a fail if directory doesn't exist.
52  if (!d.exists())
53  return false;
54 
55  d.setFilter(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot);
56  QFileInfoList list = d.entryInfoList();
57  // An empty directory is fine
58  if (list.isEmpty())
59  return true;
60 
61  QDir dir_tester;
62 
63  for (const auto& entry : std::as_const(list))
64  {
65  if (entry.fileName() == "Thumbs.db")
66  continue;
67 
68  if (!entry.isDir() &&
69  ext_settings.extension_ignored(entry.suffix())) continue;
70 
71  bool add_as_file = true;
72 
73  if (entry.isDir())
74  {
75  add_as_file = false;
76 
77  dir_tester.setPath(entry.absoluteFilePath() + "/VIDEO_TS");
78  QDir bd_dir_tester;
79  bd_dir_tester.setPath(entry.absoluteFilePath() + "/BDMV");
80  if (dir_tester.exists() || bd_dir_tester.exists())
81  {
82  add_as_file = true;
83  }
84  else
85  {
86 #if 0
87  LOG(VB_GENERAL, LOG_DEBUG,
88  QString(" -- Dir : %1").arg(entry.!absoluteFilePath()));
89 #endif
90  DirectoryHandler *dh =
91  handler->newDir(entry.fileName(),
92  entry.absoluteFilePath());
93 
94  // Since we are dealing with a subdirectory failure is fine,
95  // so we'll just ignore the failue and continue
96  (void) scan_dir(entry.absoluteFilePath(), dh, ext_settings);
97  }
98  }
99 
100  if (add_as_file)
101  {
102 #if 0
103  LOG(VB_GENERAL, LOG_DEBUG,
104  QString(" -- File : %1").arg(entry.fileName()));
105 #endif
106  handler->handleFile(entry.fileName(), entry.absoluteFilePath(),
107  entry.suffix(), "");
108  }
109  }
110 
111  return true;
112  }
113 
114  bool scan_sg_dir(const QString &start_path, const QString &host,
115  const QString &base_path, DirectoryHandler *handler,
116  const ext_lookup &ext_settings, bool isMaster = false)
117  {
118  QString path = start_path;
119 
120  if (path.startsWith(base_path))
121  path.remove(0, base_path.length());
122 
123  if (!path.endsWith("/"))
124  path += "/";
125 
126  if (path == "/")
127  path = "";
128 
129  QStringList list;
130  bool ok = false;
131 
132  if (isMaster)
133  {
134  StorageGroup sg("Videos", host);
135  list = sg.GetFileInfoList(start_path);
136  ok = true;
137  }
138  else
139  {
140  ok = RemoteGetFileList(host, start_path, &list, "Videos");
141  }
142 
143  if (!ok || (!list.isEmpty() && list.at(0).startsWith("SLAVE UNREACHABLE")))
144  {
145  LOG(VB_GENERAL, LOG_INFO,
146  QString("Backend : %1 : Is currently Unreachable. Skipping "
147  "this one.") .arg(host));
148  return false;
149  }
150 
151  if (list.isEmpty() || (list.at(0) == "EMPTY LIST"))
152  return true;
153 
154  for (const auto& entry : std::as_const(list))
155  {
156  QStringList fInfo = entry.split("::");
157  const QString& type = fInfo.at(0);
158  QString fileName = fInfo.at(1);
159 
160  if (type == "nop")
161  continue;
162 
163  QFileInfo fi(fileName);
164 
165  if ((type != "dir") &&
166  ext_settings.extension_ignored(fi.suffix())) continue;
167 
168  if (type == "dir" &&
169  !fileName.endsWith("VIDEO_TS") &&
170  !fileName.endsWith("BDMV"))
171  {
172 #if 0
173  LOG(VB_GENERAL, LOG_DEBUG,
174  QString(" -- Dir : %1").arg(fileName));
175 #endif
176  DirectoryHandler *dh =
177  handler->newDir(fileName,
178  start_path);
179 
180  // Same as a normal scan_dir we don't care if we can't read
181  // subdirectories so ignore the results and continue. As long
182  // as we reached it once to make it this far than we know the
183  // SG/Path exists
184  (void) scan_sg_dir(start_path + "/" + fileName, host, base_path,
185  dh, ext_settings, isMaster);
186  }
187  else
188  {
189  QString suffix;
190  QString URL;
191 
192  if (fileName.endsWith("VIDEO_TS") || fileName.endsWith("BDMV"))
193  {
194  if (path.startsWith("/"))
195  path = path.right(path.length() - 1);
196  if (path.endsWith("/"))
197  path = path.left(path.length() - 1);
198  QStringList upDirs = path.split("/");
199  if (upDirs.count() > 1)
200  fileName = upDirs.takeLast();
201  else
202  fileName = path;
203  suffix = "";
204  URL = path;
205  }
206  else
207  {
208  suffix = fi.suffix();
209  URL = QString("%1/%2").arg(path, fileName);
210  }
211 
212  URL.replace("//","/");
213 
214  if (URL.startsWith("/"))
215  URL = URL.right(URL.length() - 1);
216 #if 0
217  LOG(VB_GENERAL, LOG_GENERAL,
218  QString(" -- File Filename: %1 URL: %2 Suffix: %3 Host: %4")
219  .arg(fileName).arg(URL).arg(suffix).arg(QString(host)));
220 #endif
221  handler->handleFile(fileName, URL, fi.suffix(), QString(host));
222  }
223  }
224 
225  return true;
226  }
227 }
228 
229 bool ScanVideoDirectory(const QString &start_path, DirectoryHandler *handler,
230  const FileAssociations::ext_ignore_list &ext_disposition,
231  bool list_unknown_extensions)
232 {
233  ext_lookup extlookup(ext_disposition, list_unknown_extensions);
234 
235  bool pathScanned = true;
236 
237  if (!start_path.startsWith("myth://"))
238  {
239  LOG(VB_GENERAL, LOG_INFO,
240  QString("MythVideo::ScanVideoDirectory Scanning (%1)")
241  .arg(start_path));
242 
243  if (!scan_dir(start_path, handler, extlookup))
244  {
245  LOG(VB_GENERAL, LOG_ERR,
246  QString("MythVideo::ScanVideoDirectory failed to scan %1")
247  .arg(start_path));
248  pathScanned = false;
249  }
250  }
251  else
252  {
253  LOG(VB_GENERAL, LOG_INFO,
254  QString("MythVideo::ScanVideoDirectory Scanning Group (%1)")
255  .arg(start_path));
256  QUrl sgurl = start_path;
257  QString host = sgurl.host();
258  QString path = sgurl.path();
259 
260  if (!scan_sg_dir(path, host, path, handler, extlookup,
261  (gCoreContext->IsMasterHost(host) &&
262  (gCoreContext->GetHostName().toLower() == host.toLower()))))
263  {
264  LOG(VB_GENERAL, LOG_ERR,
265  QString("MythVideo::ScanVideoDirectory failed to scan %1 ")
266  .arg(host));
267  pathScanned = false;
268  }
269  }
270 
271  return pathScanned;
272 }
dirscan.h
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
remoteutil.h
dbaccess.h
anonymous_namespace{dirscan.cpp}::ext_lookup::m_listUnknown
bool m_listUnknown
Definition: dirscan.cpp:23
anonymous_namespace{dirscan.cpp}::ext_lookup
Definition: dirscan.cpp:18
mythlogging.h
hardwareprofile.config.p
p
Definition: config.py:33
FileAssociations::ext_ignore_list
std::vector< std::pair< QString, bool > > ext_ignore_list
Definition: dbaccess.h:155
anonymous_namespace{dirscan.cpp}::scan_sg_dir
bool scan_sg_dir(const QString &start_path, const QString &host, const QString &base_path, DirectoryHandler *handler, const ext_lookup &ext_settings, bool isMaster=false)
Definition: dirscan.cpp:114
anonymous_namespace{dirscan.cpp}::ext_lookup::m_extensions
ext_map m_extensions
Definition: dirscan.cpp:22
storagegroup.h
gCoreContext
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
Definition: mythcorecontext.cpp:55
anonymous_namespace{dirscan.cpp}::ext_lookup::ext_map
std::map< QString, bool > ext_map
Definition: dirscan.cpp:21
mythcorecontext.h
ScanVideoDirectory
bool ScanVideoDirectory(const QString &start_path, DirectoryHandler *handler, const FileAssociations::ext_ignore_list &ext_disposition, bool list_unknown_extensions)
Definition: dirscan.cpp:229
StorageGroup::GetFileInfoList
QStringList GetFileInfoList(const QString &Path)
Definition: storagegroup.cpp:289
mythcontext.h
StorageGroup
Definition: storagegroup.h:11
MythCoreContext::GetHostName
QString GetHostName(void)
Definition: mythcorecontext.cpp:842
MythCoreContext::IsMasterHost
bool IsMasterHost(void)
is this the same host as the master
Definition: mythcorecontext.cpp:663
DirectoryHandler::newDir
virtual DirectoryHandler * newDir(const QString &dir_name, const QString &fq_dir_name)=0
d
static const iso6937table * d
Definition: iso6937tables.cpp:1025
anonymous_namespace{dirscan.cpp}::ext_lookup::ext_lookup
ext_lookup(const FileAssociations::ext_ignore_list &ext_disposition, bool list_unknown)
Definition: dirscan.cpp:26
anonymous_namespace{dirscan.cpp}::ext_lookup::extension_ignored
bool extension_ignored(const QString &extension) const
Definition: dirscan.cpp:36
DirectoryHandler
Definition: dirscan.h:6
videoutils.h
DirectoryHandler::handleFile
virtual void handleFile(const QString &file_name, const QString &fq_file_name, const QString &extension, const QString &host)=0
anonymous_namespace{dirscan.cpp}::scan_dir
bool scan_dir(const QString &start_path, DirectoryHandler *handler, const ext_lookup &ext_settings)
Definition: dirscan.cpp:46
RemoteGetFileList
bool RemoteGetFileList(const QString &host, const QString &path, QStringList *list, QString sgroup, bool fileNamesOnly)
Definition: remoteutil.cpp:429