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