MythTV  master
gamescan.cpp
Go to the documentation of this file.
1 #include <QApplication>
2 #include <QImageReader>
3 #include <QStringList>
4 #include <QThread>
5 #include <QUrl>
6 #include <utility>
7 
8 #include <mythcontext.h>
9 #include <mythmainwindow.h>
10 #include <mythscreenstack.h>
11 #include <mythprogressdialog.h>
12 #include <mythdialogbox.h>
13 #include <mythevent.h>
14 #include <remoteutil.h>
15 #include <mythlogging.h>
16 
17 #include "gamescan.h"
18 #include "gamehandler.h"
19 #include "rominfo.h"
20 
22 
24  MThread("GameScanner"),
25  m_hasGUI(gCoreContext->HasGUI())
26 {
27 }
28 
30 {
31  RunProlog();
32 
33  LOG(VB_GENERAL, LOG_INFO, QString("Beginning Game Scan."));
34 
35  m_files.clear();
36  m_remove.clear();
38 
39  buildFileList();
40  verifyFiles();
41  updateDB();
42 
43  RunEpilog();
44 }
45 
46 
48 {
49  RomInfo *info = RomInfo::GetRomInfoById(id);
50  if (info)
51  {
52  info->DeleteFromDatabase();
53  delete info;
54  info = nullptr;
55  }
56 }
57 
59 {
60  int counter = 0;
61 
62  if (m_hasGUI)
63  SendProgressEvent(counter, (uint)m_dbgames.count(),
64  GameScanner::tr("Verifying game files..."));
65 
66  // For every file we know about, check to see if it still exists.
67  for (const auto *info : qAsConst(m_dbgames))
68  {
69  QString romfile = info->Romname();
70  QString gametype = info->GameType();
71  if (!romfile.isEmpty())
72  {
73  bool found = false;
74  // NOLINTNEXTLINE(modernize-loop-convert)
75  for (auto p2 = m_files.begin(); p2 != m_files.end(); ++p2)
76  {
77  if ((*p2).romfile == romfile &&
78  (*p2).gametype == gametype)
79  {
80  // We're done here, this file matches one in the DB
81  (*p2).indb = true;
82  found = true;
83  continue;
84  }
85  }
86  if (!found)
87  {
88  m_remove.append(info->Id());
89  }
90  }
91  if (m_hasGUI)
92  SendProgressEvent(++counter);
93 
94  delete info;
95  info = nullptr;
96  }
97 }
98 
100 {
101  uint counter = 0;
102  if (m_hasGUI)
103  SendProgressEvent(counter, (uint)(m_files.size() + m_remove.size()),
104  GameScanner::tr("Updating game database..."));
105 
106  for (const auto & file : qAsConst(m_files))
107  {
108  if (!file.indb)
109  {
110  RomInfo add(0, file.romfile, file.system,
111  file.romname, "", "", false, file.rompath,
112  "", "", 0, file.gametype, 0, "", "", "",
113  "", "", "", "", "");
114  add.SaveToDatabase();
115  m_dbDataChanged = true;
116  }
117  if (m_hasGUI)
118  SendProgressEvent(++counter);
119  }
120 
121  for (const uint & p : qAsConst(m_remove))
122  {
123  removeOrphan(p);
124  m_dbDataChanged = true;
125  }
126 }
127 
129 {
130  if (m_handlers.empty())
131  return false;
132 
133  int counter = 0;
134 
135  if (m_hasGUI)
136  SendProgressEvent(counter, (uint)m_handlers.size(),
137  GameScanner::tr("Searching for games..."));
138 
139  for (auto * handler : qAsConst(m_handlers))
140  {
141  QDir dir(handler->SystemRomPath());
142  QStringList extensions = handler->ValidExtensions();
143  QStringList filters;
144  for (const auto & ext : qAsConst(extensions))
145  {
146  filters.append(QString("*.%1").arg(ext));
147  }
148 
149  dir.setNameFilters(filters);
150  dir.setFilter(QDir::Files | QDir::Readable | QDir::NoDotAndDotDot);
151 
152  QStringList files = dir.entryList();
153  for (const auto & file : qAsConst(files))
154  {
155  RomFileInfo info;
156  info.system = handler->SystemName();
157  info.gametype = handler->GameType();
158  info.romfile = file;
159  info.rompath = handler->SystemRomPath();
160  info.romname = QFileInfo(file).baseName();
161  info.indb = false;
162  m_files.append(info);
163  }
164 
165  if (m_hasGUI)
166  SendProgressEvent(++counter);
167  }
168 
169  return true;
170 }
171 
173  QString message)
174 {
175  if (!m_dialog)
176  return;
177 
178  auto *pue = new ProgressUpdateEvent(progress, total, std::move(message));
179  QApplication::postEvent(m_dialog, pue);
180 }
181 
183 {
185 }
186 
188 {
189  if (m_scanThread && m_scanThread->wait())
190  delete m_scanThread;
191 }
192 
193 void GameScanner::doScan(QList<GameHandler*> handlers)
194 {
195  if (m_scanThread->isRunning())
196  return;
197 
198  if (gCoreContext->HasGUI())
199  {
200  MythScreenStack *popupStack = GetMythMainWindow()->GetStack("popup stack");
201 
202  auto *progressDlg = new MythUIProgressDialog("",
203  popupStack, "gamescanprogressdialog");
204 
205  if (progressDlg->Create())
206  {
207  popupStack->AddScreen(progressDlg, false);
208  connect(m_scanThread->qthread(), &QThread::finished,
209  progressDlg, &MythScreenType::Close);
210  connect(m_scanThread->qthread(), &QThread::finished,
212  }
213  else
214  {
215  delete progressDlg;
216  progressDlg = nullptr;
217  }
218  m_scanThread->SetProgressDialog(progressDlg);
219  }
220 
221  m_scanThread->SetHandlers(std::move(handlers));
222  m_scanThread->start();
223 }
224 
226 {
227  QList<GameHandler*> hlist;
228 
230  query.prepare("SELECT DISTINCT playername FROM gameplayers "
231  "WHERE playername <> '';");
232 
233  if (!query.exec())
234  MythDB::DBError("doScanAll - selecting playername", query);
235 
236  while (query.next())
237  {
238  QString name = query.value(0).toString();
240  if (hnd)
241  hlist.append(hnd);
242  }
243 
244  doScan(hlist);
245 }
246 
248 {
250 }
251 
GameScanner::doScanAll
void doScanAll(void)
Definition: gamescan.cpp:225
MSqlQuery::next
bool next(void)
Wrap QSqlQuery::next() so we can display the query results.
Definition: mythdbcon.cpp:783
MSqlQuery
QSqlQuery wrapper that fetches a DB connection from the connection pool.
Definition: mythdbcon.h:126
mythevent.h
GameScannerThread::buildFileList
bool buildFileList()
Definition: gamescan.cpp:128
RomFileInfo
Definition: gamescan.h:21
MThread::start
void start(QThread::Priority p=QThread::InheritPriority)
Tell MThread to start running the thread in the near future.
Definition: mthread.cpp:288
MythScreenType::Close
virtual void Close()
Definition: mythscreentype.cpp:402
mythscreenstack.h
GameScannerThread::getDataChanged
bool getDataChanged() const
Definition: gamescan.h:43
RomFileInfo::gametype
QString gametype
Definition: gamescan.h:23
GameHandler
Definition: gamehandler.h:61
progress
bool progress
Definition: mythtv/programs/mythcommflag/main.cpp:73
GameScannerThread::m_remove
QList< uint > m_remove
Definition: gamescan.h:62
RomFileInfo::romname
QString romname
Definition: gamescan.h:26
mythdialogbox.h
MSqlQuery::value
QVariant value(int i) const
Definition: mythdbcon.h:198
MythScreenStack
Definition: mythscreenstack.h:16
arg
arg(title).arg(filename).arg(doDelete))
MSqlQuery::exec
bool exec(void)
Wrap QSqlQuery::exec() so we can display SQL.
Definition: mythdbcon.cpp:603
RomInfo::GetAllRomInfo
static QList< RomInfo * > GetAllRomInfo()
Definition: rominfo.cpp:317
GameScanner::GameScanner
GameScanner()
Definition: gamescan.cpp:182
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:23
MThread::RunProlog
void RunProlog(void)
Sets up a thread, call this if you reimplement run().
Definition: mthread.cpp:198
GameScannerThread::SetHandlers
void SetHandlers(QList< GameHandler * > handlers)
Definition: gamescan.h:40
build_compdb.file
file
Definition: build_compdb.py:55
remoteutil.h
MythMainWindow::GetStack
MythScreenStack * GetStack(const QString &stackname)
Definition: mythmainwindow.cpp:329
GameScannerThread::m_handlers
QList< GameHandler * > m_handlers
Definition: gamescan.h:59
gamescan.h
mythprogressdialog.h
GameScannerThread::run
void run(void) override
Runs the Qt event loop unless we have a QRunnable, in which case we run the runnable run instead.
Definition: gamescan.cpp:29
MythUIProgressDialog::MythUIProgressDialog
MythUIProgressDialog(QString message, MythScreenStack *parent, const char *name)
Definition: mythprogressdialog.h:63
GameHandler::GetHandlerByName
static GameHandler * GetHandlerByName(const QString &systemname)
Definition: gamehandler.cpp:805
ProgressUpdateEvent
Definition: mythprogressdialog.h:17
mythlogging.h
hardwareprofile.config.p
p
Definition: config.py:33
MythUIProgressDialog
Definition: mythprogressdialog.h:60
MSqlQuery::InitCon
static MSqlQueryInfo InitCon(ConnectionReuse _reuse=kNormalConnection)
Only use this in combination with MSqlQuery constructor.
Definition: mythdbcon.cpp:535
MythDB::DBError
static void DBError(const QString &where, const MSqlQuery &query)
Definition: mythdb.cpp:178
p2
static guint32 * p2
Definition: goom_core.cpp:31
GameScanner::finished
void finished(bool)
GameScannerThread::GameScannerThread
GameScannerThread(void)
Definition: gamescan.cpp:23
MThread::qthread
QThread * qthread(void)
Returns the thread, this will always return the same pointer no matter how often you restart the thre...
Definition: mthread.cpp:238
GameScanner::finishedScan
void finishedScan()
Definition: gamescan.cpp:247
GameScannerThread::SendProgressEvent
void SendProgressEvent(uint progress, uint total=0, QString message=QString())
Definition: gamescan.cpp:172
RomFileInfo::romfile
QString romfile
Definition: gamescan.h:24
MThread::RunEpilog
void RunEpilog(void)
Cleans up a thread's resources, call this if you reimplement run().
Definition: mthread.cpp:211
GameScanner::~GameScanner
~GameScanner() override
Definition: gamescan.cpp:187
rominfo.h
handlers
static QList< GameHandler * > * handlers
Definition: gamehandler.cpp:23
GameScannerThread::m_files
RomFileInfoList m_files
Definition: gamescan.h:61
RomInfo::GetRomInfoById
static RomInfo * GetRomInfoById(int id)
Definition: rominfo.cpp:365
uint
unsigned int uint
Definition: compat.h:141
gCoreContext
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
Definition: mythcorecontext.cpp:60
GameScannerThread::m_dbgames
QList< RomInfo * > m_dbgames
Definition: gamescan.h:63
GameScannerThread::removeOrphan
static void removeOrphan(int id)
Definition: gamescan.cpp:47
RomFileInfo::system
QString system
Definition: gamescan.h:22
RomInfo
Definition: rominfo.h:13
GameScannerThread::SetProgressDialog
void SetProgressDialog(MythUIProgressDialog *dialog)
Definition: gamescan.h:41
GameScannerThread::m_hasGUI
bool m_hasGUI
Definition: gamescan.h:57
dir
QDir dir
Definition: mythplugins/mytharchive/mytharchivehelper/main.cpp:1174
GameScannerThread::updateDB
void updateDB()
Definition: gamescan.cpp:99
GameScannerThread
Definition: gamescan.h:33
GameScannerThread::m_dbDataChanged
bool m_dbDataChanged
Definition: gamescan.h:67
RomInfo::DeleteFromDatabase
void DeleteFromDatabase() const
Definition: rominfo.cpp:94
mythcontext.h
MThread
This is a wrapper around QThread that does several additional things.
Definition: mthread.h:49
GetMythMainWindow
MythMainWindow * GetMythMainWindow(void)
Definition: mythmainwindow.cpp:108
MThread::isRunning
bool isRunning(void) const
Definition: mthread.cpp:268
RomInfo::SaveToDatabase
void SaveToDatabase() const
Definition: rominfo.cpp:17
RomFileInfo::rompath
QString rompath
Definition: gamescan.h:25
MythCoreContext::HasGUI
bool HasGUI(void) const
Definition: mythcorecontext.cpp:1753
GameScannerThread::verifyFiles
void verifyFiles()
Definition: gamescan.cpp:58
MThread::wait
bool wait(unsigned long time=ULONG_MAX)
Wait for the MThread to exit, with a maximum timeout.
Definition: mthread.cpp:305
RomFileInfo::indb
bool indb
Definition: gamescan.h:27
mythmainwindow.h
MythScreenStack::AddScreen
virtual void AddScreen(MythScreenType *screen, bool allowFade=true)
Definition: mythscreenstack.cpp:52
query
MSqlQuery query(MSqlQuery::InitCon())
gamehandler.h
GameScanner::m_scanThread
GameScannerThread * m_scanThread
Definition: gamescan.h:88
GameScanner::doScan
void doScan(QList< GameHandler * > handlers)
Definition: gamescan.cpp:193
MSqlQuery::prepare
bool prepare(const QString &query)
QSqlQuery::prepare() is not thread safe in Qt <= 3.3.2.
Definition: mythdbcon.cpp:808
GameScannerThread::m_dialog
MythUIProgressDialog * m_dialog
Definition: gamescan.h:65