MythTV  master
mytharchive.cpp
Go to the documentation of this file.
1 /*
2  main.cpp
3 
4  MythArchive - mythtv plugin
5 
6  Starting point for the MythArchive module
7 */
8 #include <csignal>
9 #include <cstdlib>
10 #include <iostream>
11 #ifdef _WIN32
12 #include <processthreadsapi.h>
13 #endif
14 
15 // Qt
16 #include <QApplication>
17 #include <QDir>
18 #include <QTimer>
19 
20 // mythtv
24 #include <libmythbase/mythplugin.h>
27 #include <libmythbase/mythversion.h>
31 #include <libmythui/mythuihelper.h>
32 
33 // mytharchive
34 #include "archivedbcheck.h"
35 #include "archivesettings.h"
36 #include "archiveutil.h"
37 #include "exportnative.h"
38 #include "fileselector.h"
39 #include "importnative.h"
40 #include "logviewer.h"
41 #include "mythburn.h"
42 #include "recordingselector.h"
43 #include "selectdestination.h"
44 #include "videoselector.h"
45 
46 // return true if the process belonging to the lock file is still running
47 static bool checkProcess(const QString &lockFile)
48 {
49  // read the PID from the lock file
50  QFile file(lockFile);
51 
52  bool bOK = file.open(QIODevice::ReadOnly);
53 
54  if (!bOK)
55  {
56  LOG(VB_GENERAL, LOG_ERR,
57  QString("Unable to open file %1").arg(lockFile));
58 
59  return true;
60  }
61 
62  QString line(file.readLine(100));
63 
64  pid_t pid = line.toInt(&bOK);
65 
66  if (!bOK)
67  {
68  LOG(VB_GENERAL, LOG_ERR,
69  QString("Got bad PID '%1' from lock file").arg(pid));
70  return true;
71  }
72 
73  LOG(VB_GENERAL, LOG_NOTICE,
74  QString("Checking if PID %1 is still running").arg(pid));
75 
76 #ifdef _WIN32
77  HANDLE handy = OpenProcess(SYNCHRONIZE|PROCESS_TERMINATE, TRUE, pid);
78  return TerminateProcess(handy,0) == 0;
79 #else
80  if (kill(pid, 0) == -1)
81  {
82  if (errno == ESRCH)
83  return false;
84  }
85 #endif
86 
87  return true;
88 }
89 
90 // return true if a lock file is found and the owning process is still running
91 static bool checkLockFile(const QString &lockFile)
92 {
93  QFile file(lockFile);
94 
95  //is a job already running?
96  if (file.exists())
97  {
98  // Is the process that created the lock still alive?
99  if (!checkProcess(lockFile))
100  {
101  showWarningDialog(QCoreApplication::translate("(MythArchiveMain)",
102  "Found a lock file but the owning process isn't running!\n"
103  "Removing stale lock file."));
104  if (!file.remove())
105  {
106  LOG(VB_GENERAL, LOG_ERR,
107  QString("Failed to remove stale lock file - %1")
108  .arg(lockFile));
109  }
110  }
111  else
112  {
113  return true;
114  }
115  }
116 
117  return false;
118 }
119 
120 static void runCreateDVD(void)
121 {
122  QString tempDir = getTempDirectory(true);
124 
125  if (tempDir == "")
126  return;
127 
128  QString logDir = tempDir + "logs";
129 
131 
132  if (checkLockFile(logDir + "/mythburn.lck"))
133  {
134  // a job is already running so just show the log viewer
135  showLogViewer();
136  return;
137  }
138 
139  // show the select destination dialog
140  auto *dest = new SelectDestination(mainStack, false, "SelectDestination");
141 
142  if (dest->Create())
143  mainStack->AddScreen(dest);
144 }
145 
146 static void runCreateArchive(void)
147 {
148  QString tempDir = getTempDirectory(true);
150 
151  if (tempDir == "")
152  return;
153 
154  QString logDir = tempDir + "logs";
155 
157 
158  if (checkLockFile(logDir + "/mythburn.lck"))
159  {
160  // a job is already running so just show the log viewer
161  showLogViewer();
162  return;
163  }
164 
165  // show the select destination dialog
166  auto *dest = new SelectDestination(mainStack, true, "SelectDestination");
167 
168  if (dest->Create())
169  mainStack->AddScreen(dest);
170 }
171 
172 static void runEncodeVideo(void)
173 {
174 
175 }
176 
177 static void runImportVideo(void)
178 {
179  QString tempDir = getTempDirectory(true);
180 
181  if (tempDir == "")
182  return;
183 
184  QString logDir = tempDir + "logs";
185 
187 
188  if (checkLockFile(logDir + "/mythburn.lck"))
189  {
190  // a job is already running so just show the log viewer
191  showLogViewer();
192  return;
193  }
194 
195  // show the find archive screen
197  auto *selector = new ArchiveFileSelector(mainStack);
198 
199  if (selector->Create())
200  mainStack->AddScreen(selector);
201 }
202 
203 static void runShowLog(void)
204 {
205  showLogViewer();
206 }
207 
208 static void runTestDVD(void)
209 {
210  if (!gCoreContext->GetSetting("MythArchiveLastRunType").startsWith("DVD"))
211  {
212  showWarningDialog(QCoreApplication::translate("(MythArchiveMain)",
213  "Last run did not create a playable DVD."));
214  return;
215  }
216 
217  if (!gCoreContext->GetSetting("MythArchiveLastRunStatus").startsWith("Success"))
218  {
219  showWarningDialog(QCoreApplication::translate("(MythArchiveMain)",
220  "Last run failed to create a DVD."));
221  return;
222  }
223 
224  QString tempDir = getTempDirectory(true);
225 
226  if (tempDir == "")
227  return;
228 
229  QString filename = tempDir + "work/dvd";
230  QString command = gCoreContext->GetSetting("MythArchiveDVDPlayerCmd", "");
231 
232  if ((command.indexOf("internal", 0, Qt::CaseInsensitive) > -1) ||
233  (command.length() < 1))
234  {
235  filename = QString("dvd:/") + filename;
236  command = "Internal";
238  return;
239  }
240 
241  if (command.contains("%f"))
242  command = command.replace("%f", filename);
243  myth_system(command);
244 }
245 
246 static void runBurnDVD(void)
247 {
248  auto *menu = new BurnMenu();
249  menu->start();
250 }
251 
252 // these point to the the mainmenu callback if found
253 static void (*m_callback)(void *, QString &) = nullptr;
254 static void *m_callbackdata = nullptr;
255 
256 static void ArchiveCallback([[maybe_unused]] void *data, QString &selection)
257 {
258  QString sel = selection.toLower();
259 
260  if (sel == "archive_create_dvd")
261  runCreateDVD();
262  else if (sel == "archive_create_archive")
264  else if (sel == "archive_encode_video")
265  runEncodeVideo();
266  else if (sel == "archive_import_video")
267  runImportVideo();
268  else if (sel == "archive_last_log")
269  runShowLog();
270  else if (sel == "archive_test_dvd")
271  runTestDVD();
272  else if (sel == "archive_burn_dvd")
273  runBurnDVD();
274  else
275  {
276  // if we have found the mainmenu callback
277  // pass the selection on to it
278  if (m_callback && m_callbackdata)
279  m_callback(m_callbackdata, selection);
280  }
281 }
282 
283 static int runMenu(const QString& which_menu)
284 {
285  // find the 'mainmenu' MythThemedMenu so we can use the callback from it
286  MythThemedMenu *mainMenu = nullptr;
287  QObject *parentObject = GetMythMainWindow()->GetMainStack()->GetTopScreen();
288 
289  while (parentObject)
290  {
291  mainMenu = qobject_cast<MythThemedMenu *>(parentObject);
292 
293  if (mainMenu && mainMenu->objectName() == "mainmenu")
294  break;
295 
296  parentObject = parentObject->parent();
297  }
298 
299  QString themedir = GetMythUI()->GetThemeDir();
300  auto *diag = new MythThemedMenu(themedir, which_menu,
301  GetMythMainWindow()->GetMainStack(),
302  "archive menu");
303 
304  // save the callback from the main menu
305  if (mainMenu)
306  mainMenu->getCallback(&m_callback, &m_callbackdata);
307  else
308  {
309  m_callback = nullptr;
310  m_callbackdata = nullptr;
311  }
312 
313  diag->setCallback(ArchiveCallback, nullptr);
314  diag->setKillable();
315 
316  if (diag->foundTheme())
317  {
319  return 0;
320  }
321 
322  LOG(VB_GENERAL, LOG_ERR, QString("Couldn't find menu %1 or theme %2")
323  .arg(which_menu, themedir));
324  delete diag;
325  return -1;
326 }
327 
328 static void initKeys(void)
329 {
330  REG_KEY("Archive", "TOGGLECUT", QT_TRANSLATE_NOOP("MythControls",
331  "Toggle use cut list state for selected program"), "C");
332 
333  REG_JUMP(QT_TRANSLATE_NOOP("MythControls", "Create DVD"),
334  "", "", runCreateDVD);
335  REG_JUMP(QT_TRANSLATE_NOOP("MythControls", "Create Archive"),
336  "", "", runCreateArchive);
337  REG_JUMP(QT_TRANSLATE_NOOP("MythControls", "Import Archive"),
338  "", "", runImportVideo);
339  REG_JUMP(QT_TRANSLATE_NOOP("MythControls", "View Archive Log"),
340  "", "", runShowLog);
341  REG_JUMP(QT_TRANSLATE_NOOP("MythControls", "Play Created DVD"),
342  "", "", runTestDVD);
343  REG_JUMP(QT_TRANSLATE_NOOP("MythControls", "Burn DVD"),
344  "", "", runBurnDVD);
345 }
346 
347 int mythplugin_init(const char *libversion)
348 {
349  if (!MythCoreContext::TestPluginVersion("mytharchive", libversion,
350  MYTH_BINARY_VERSION))
351  {
352  LOG(VB_GENERAL, LOG_ERR, "Test Popup Version Failed");
353  return -1;
354  }
355 
358  {
359  LOG(VB_GENERAL, LOG_ERR,
360  "Couldn't upgrade database to new schema, exiting.");
361  return -1;
362  }
364 
365  ArchiveSettings settings;
366  settings.Load();
367  settings.Save();
368 
369  initKeys();
370 
371  return 0;
372 }
373 
374 int mythplugin_run(void)
375 {
376  return runMenu("archivemenu.xml");
377 }
378 
380 {
382  auto *ssd = new StandardSettingDialog(mainStack, "archivesettings",
383  new ArchiveSettings());
384 
385  if (ssd->Create())
386  {
387  mainStack->AddScreen(ssd);
388  }
389  else
390  {
391  delete ssd;
392  }
393 
394  return 0;
395 }
themedir
static QString themedir
Definition: mythdirs.cpp:23
MythMainWindow::GetMainStack
MythScreenStack * GetMainStack()
Definition: mythmainwindow.cpp:317
build_compdb.dest
dest
Definition: build_compdb.py:9
archivesettings.h
exportnative.h
REG_KEY
static void REG_KEY(const QString &Context, const QString &Action, const QString &Description, const QString &Key)
Definition: mythmainwindow.h:175
runTestDVD
static void runTestDVD(void)
Definition: mytharchive.cpp:208
fileselector.h
checkProcess
static bool checkProcess(const QString &lockFile)
Definition: mytharchive.cpp:47
mythplugin.h
runMenu
static int runMenu(const QString &which_menu)
Definition: mytharchive.cpp:283
mythcoreutil.h
mythdialogbox.h
MythScreenStack
Definition: mythscreenstack.h:16
logviewer.h
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
MythCoreContext::TestPluginVersion
static bool TestPluginVersion(const QString &name, const QString &libversion, const QString &pluginversion)
Definition: mythcorecontext.cpp:2089
build_compdb.file
file
Definition: build_compdb.py:55
checkLockFile
static bool checkLockFile(const QString &lockFile)
Definition: mytharchive.cpp:91
myth_system
uint myth_system(const QString &command, uint flags, std::chrono::seconds timeout)
Definition: mythsystemlegacy.cpp:506
getTempDirectory
QString getTempDirectory(bool showError)
Definition: archiveutil.cpp:46
runCreateDVD
static void runCreateDVD(void)
Definition: mytharchive.cpp:120
mythplugin_config
int mythplugin_config(void)
Definition: mytharchive.cpp:379
initKeys
static void initKeys(void)
Definition: mytharchive.cpp:328
MythMainWindow::HandleMedia
bool HandleMedia(const QString &Handler, const QString &Mrl, const QString &Plot="", const QString &Title="", const QString &Subtitle="", const QString &Director="", int Season=0, int Episode=0, const QString &Inetref="", std::chrono::minutes LenMins=2h, const QString &Year="1895", const QString &Id="", bool UseBookmarks=false)
Definition: mythmainwindow.cpp:1496
m_callback
static void(* m_callback)(void *, QString &)
Definition: mytharchive.cpp:253
selectdestination.h
mythsystemlegacy.h
runImportVideo
static void runImportVideo(void)
Definition: mytharchive.cpp:177
showWarningDialog
void showWarningDialog(const QString &msg)
Definition: archiveutil.cpp:274
recordingselector.h
StandardSettingDialog
Definition: standardsettings.h:468
mythlogging.h
archiveutil.h
menu
static MythThemedMenu * menu
Definition: mythtv-setup.cpp:58
MythUIThemeHelper::GetThemeDir
QString GetThemeDir()
Definition: mythuithemehelper.cpp:141
ArchiveFileSelector
Definition: importnative.h:47
StandardSetting::Load
virtual void Load(void)
Definition: standardsettings.cpp:213
videoselector.h
mythplugin_run
int mythplugin_run(void)
Definition: mytharchive.cpp:374
runCreateArchive
static void runCreateArchive(void)
Definition: mytharchive.cpp:146
m_callbackdata
static void * m_callbackdata
Definition: mytharchive.cpp:254
showLogViewer
void showLogViewer(void)
Definition: logviewer.cpp:26
StandardSetting::Save
virtual void Save(void)
Definition: standardsettings.cpp:232
checkTempDirectory
void checkTempDirectory()
Definition: archiveutil.cpp:70
gCoreContext
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
Definition: mythcorecontext.cpp:57
SelectDestination
Definition: selectdestination.h:20
mythplugin_init
int mythplugin_init(const char *libversion)
Definition: mytharchive.cpp:347
mythpluginapi.h
ArchiveSettings
Definition: archivesettings.h:15
runEncodeVideo
static void runEncodeVideo(void)
Definition: mytharchive.cpp:172
mythuihelper.h
BurnMenu
Definition: mythburn.h:136
runShowLog
static void runShowLog(void)
Definition: mytharchive.cpp:203
MythThemedMenu::getCallback
void getCallback(void(**lcallback)(void *, QString &), void **data)
Get the themed menus callback function and data for that function.
Definition: myththemedmenu.cpp:151
mythburn.h
mythcorecontext.h
archivedbcheck.h
REG_JUMP
static void REG_JUMP(const QString &Destination, const QString &Description, const QString &Key, void(*Callback)(void))
Definition: mythmainwindow.h:188
GetMythMainWindow
MythMainWindow * GetMythMainWindow(void)
Definition: mythmainwindow.cpp:104
UpgradeArchiveDatabaseSchema
bool UpgradeArchiveDatabaseSchema(void)
Definition: archivedbcheck.cpp:19
MythCoreContext::ActivateSettingsCache
void ActivateSettingsCache(bool activate=true)
Definition: mythcorecontext.cpp:839
importnative.h
MythThemedMenu
Themed menu class, used for main menus in MythTV frontend.
Definition: myththemedmenu.h:57
myththemedmenu.h
GetMythUI
MythUIHelper * GetMythUI()
Definition: mythuihelper.cpp:64
build_compdb.filename
filename
Definition: build_compdb.py:21
mythmainwindow.h
MythScreenStack::AddScreen
virtual void AddScreen(MythScreenType *screen, bool allowFade=true)
Definition: mythscreenstack.cpp:52
ArchiveCallback
static void ArchiveCallback([[maybe_unused]] void *data, QString &selection)
Definition: mytharchive.cpp:256
MythCoreContext::GetSetting
QString GetSetting(const QString &key, const QString &defaultval="")
Definition: mythcorecontext.cpp:904
MythScreenStack::GetTopScreen
virtual MythScreenType * GetTopScreen(void) const
Definition: mythscreenstack.cpp:182
runBurnDVD
static void runBurnDVD(void)
Definition: mytharchive.cpp:246