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