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