MythTV  master
recordingutils.cpp
Go to the documentation of this file.
1 
2 // C++ includes
3 #include <algorithm> // for max
4 #include <iostream> // for cout, endl
5 #include <sys/stat.h>
6 
7 // Qt
8 #include <QFileInfo>
9 #include <QScopedPointer>
10 
11 // libmyth* includes
12 #include "libmythbase/exitcodes.h"
13 #include "libmythbase/mythdirs.h"
15 #include "libmythbase/mythsystem.h"
16 #include "libmythbase/remotefile.h"
17 #include "libmythbase/remoteutil.h"
18 #include "libmythbase/stringutil.h"
19 
20 // Local includes
21 #include "recordingutils.h"
22 
23 static QString CreateProgramInfoString(const ProgramInfo &pginfo)
24 {
25  QDateTime recstartts = pginfo.GetRecordingStartTime();
26  QDateTime recendts = pginfo.GetRecordingEndTime();
27 
28  QString timedate = QString("%1 - %2")
29  .arg(MythDate::toString(
32 
33  QString title = pginfo.GetTitle();
34 
35  QString extra;
36 
37  if (!pginfo.GetSubtitle().isEmpty())
38  {
39  extra = QString(" ~ ") + pginfo.GetSubtitle();
40  int maxll = std::max(static_cast<int>(title.length()), 20);
41  if (extra.length() > maxll)
42  extra = extra.left(maxll - 3) + "...";
43  }
44 
45  return QString("%1%2 - %3").arg(title, extra, timedate);
46 }
47 
49 {
50  std::cout << "Checking Recordings" << std::endl;
51 
52  std::vector<ProgramInfo *> *recordingList = RemoteGetRecordedList(-1);
53  std::vector<ProgramInfo *> missingRecordings;
54  std::vector<ProgramInfo *> zeroByteRecordings;
55  std::vector<ProgramInfo *> noSeektableRecordings;
56 
57  if (!recordingList)
58  {
59  std::cout << "ERROR - failed to get recording list from backend" << std::endl;
60  return GENERIC_EXIT_NOT_OK;
61  }
62 
63  bool fixSeektable = cmdline.toBool("fixseektable");
64 
65  std::cout << "Fix seektable is: " << fixSeektable << std::endl;
66 
67  if (!recordingList->empty())
68  {
69  for (auto i = recordingList->begin(); i != recordingList->end(); ++i)
70  {
71  ProgramInfo *p = *i;
72  // ignore live tv and deleted recordings
73  if (p->GetRecordingGroup() == "LiveTV" ||
74  p->GetRecordingGroup() == "Deleted")
75  {
76  i = recordingList->erase(i);
77  --i;
78  continue;
79  }
80 
81  std::cout << "Checking: " << qPrintable(CreateProgramInfoString(*p)) << std::endl;
82  bool foundFile = true;
83 
84  QString url = p->GetPlaybackURL();
85 
86  if (url.startsWith('/'))
87  {
88  QFileInfo fi(url);
89  if (!fi.exists())
90  {
91  std::cout << "File not found" << std::endl;
92  missingRecordings.push_back(p);
93  foundFile = false;
94  }
95  else
96  {
97  if (fi.size() == 0)
98  {
99  std::cout << "File was found but has zero length" << std::endl;
100  zeroByteRecordings.push_back(p);
101  }
102  }
103  }
104  else if (url.startsWith("myth:"))
105  {
106  if (!RemoteFile::Exists(url))
107  {
108  std::cout << "File not found" << std::endl;
109  missingRecordings.push_back(p);
110  foundFile = false;
111  }
112  else
113  {
114  RemoteFile rf(url);
115  if (rf.GetFileSize() == 0)
116  {
117  std::cout << "File was found but has zero length" << std::endl;
118  zeroByteRecordings.push_back(p);
119  }
120  }
121  }
122 
123  frm_pos_map_t posMap;
124  p->QueryPositionMap(posMap, MARK_GOP_BYFRAME);
125  if (posMap.isEmpty())
126  p->QueryPositionMap(posMap, MARK_GOP_START);
127  if (posMap.isEmpty())
128  p->QueryPositionMap(posMap, MARK_KEYFRAME);
129 
130  if (posMap.isEmpty())
131  {
132  std::cout << "No seektable found" << std::endl;
133 
134  noSeektableRecordings.push_back(p);
135 
136  if (foundFile && fixSeektable)
137  {
138  QString command = GetAppBinDir() + "mythcommflag " +
139  QString("--rebuild --chanid %1 --starttime %2")
140  .arg(p->GetChanID())
141  .arg(p->GetRecordingStartTime(MythDate::ISODate));
142  std::cout << "Running - " << qPrintable(command) << std::endl;
143  QScopedPointer<MythSystem> cmd(MythSystem::Create(command));
144  cmd->Wait(0s);
145  if (cmd.data()->GetExitCode() != GENERIC_EXIT_OK)
146  {
147  std::cout << "ERROR - mythcommflag exited with result: " << cmd.data()->GetExitCode() << std::endl;
148  }
149  }
150  }
151 
152  std::cout << "-------------------------------------------------------------------" << std::endl;
153  }
154  }
155 
156  if (!missingRecordings.empty())
157  {
158  std::cout << std::endl << std::endl;
159  std::cout << "MISSING RECORDINGS" << std::endl;
160  std::cout << "------------------" << std::endl;
161  for (auto *p : missingRecordings)
162  {
163  std::cout << qPrintable(CreateProgramInfoString(*p)) << std::endl;
164  std::cout << qPrintable(p->GetPlaybackURL()) << std::endl;
165  std::cout << "-------------------------------------------------------------------" << std::endl;
166  }
167  }
168 
169  if (!zeroByteRecordings.empty())
170  {
171  std::cout << std::endl << std::endl;
172  std::cout << "ZERO BYTE RECORDINGS" << std::endl;
173  std::cout << "--------------------" << std::endl;
174  for (auto *p : zeroByteRecordings)
175  {
176  std::cout << qPrintable(CreateProgramInfoString(*p)) << std::endl;
177  std::cout << qPrintable(p->GetPlaybackURL()) << std::endl;
178  std::cout << "-------------------------------------------------------------------" << std::endl;
179  }
180  }
181 
182  if (!noSeektableRecordings.empty())
183  {
184  std::cout << std::endl << std::endl;
185  std::cout << "NO SEEKTABLE RECORDINGS" << std::endl;
186  std::cout << "-----------------------" << std::endl;
187  for (auto *p : noSeektableRecordings)
188  {
189  std::cout << qPrintable(CreateProgramInfoString(*p)) << std::endl;
190  std::cout << qPrintable(p->GetPlaybackURL()) << std::endl;
191  std::cout << "File size is " << qPrintable(StringUtil::formatBytes(p->GetFilesize(), 2)) << std::endl;
192  std::cout << "-------------------------------------------------------------------" << std::endl;
193  }
194  }
195 
196  std::cout << std::endl << std::endl << "SUMMARY" << std::endl;
197  std::cout << "Recordings : " << recordingList->size() << std::endl;
198  std::cout << "Missing Recordings : " << missingRecordings.size() << std::endl;
199  std::cout << "Zero byte Recordings : " << zeroByteRecordings.size() << std::endl;
200  std::cout << "Missing Seektables : " << noSeektableRecordings.size() << std::endl;
201 
202  return GENERIC_EXIT_OK;
203 }
204 
206 {
207  utilMap["checkrecordings"] = &CheckRecordings;
208 }
209 
210 /* vim: set expandtab tabstop=4 shiftwidth=4: */
MARK_KEYFRAME
@ MARK_KEYFRAME
Definition: programtypes.h:63
MythDate::toString
QString toString(const QDateTime &raw_dt, uint format)
Returns formatted string representing the time.
Definition: mythdate.cpp:84
RemoteFile::GetFileSize
long long GetFileSize(void) const
GetFileSize: returns the remote file's size at the time it was first opened Will query the server in ...
Definition: remotefile.cpp:1084
cmdline
MythCommFlagCommandLineParser cmdline
Definition: mythcommflag.cpp:72
RemoteFile::Exists
static bool Exists(const QString &url, struct stat *fileinfo)
Definition: remotefile.cpp:454
RemoteFile
Definition: remotefile.h:17
mythdirs.h
ProgramInfo::GetRecordingEndTime
QDateTime GetRecordingEndTime(void) const
Approximate time the recording should have ended, did end, or is intended to end.
Definition: programinfo.h:412
GENERIC_EXIT_OK
@ GENERIC_EXIT_OK
Exited with no error.
Definition: exitcodes.h:11
MythUtilCommandLineParser
Definition: mythutil_commandlineparser.h:8
remoteutil.h
ProgramInfo::GetRecordingStartTime
QDateTime GetRecordingStartTime(void) const
Approximate time the recording started.
Definition: programinfo.h:404
mythsystem.h
mythlogging.h
remotefile.h
hardwareprofile.config.p
p
Definition: config.py:33
MARK_GOP_START
@ MARK_GOP_START
Definition: programtypes.h:62
ProgramInfo::GetTitle
QString GetTitle(void) const
Definition: programinfo.h:361
stringutil.h
GENERIC_EXIT_NOT_OK
@ GENERIC_EXIT_NOT_OK
Exited with error.
Definition: exitcodes.h:12
frm_pos_map_t
QMap< long long, long long > frm_pos_map_t
Frame # -> File offset map.
Definition: programtypes.h:46
MythDate::kSimplify
@ kSimplify
Do Today/Yesterday/Tomorrow transform.
Definition: mythdate.h:26
CreateProgramInfoString
static QString CreateProgramInfoString(const ProgramInfo &pginfo)
Definition: recordingutils.cpp:23
ProgramInfo
Holds information on recordings and videos.
Definition: programinfo.h:67
UtilMap
QMap< QString, UtilFunc > UtilMap
Definition: mythutil.h:15
MythCommandLineParser::toBool
bool toBool(const QString &key) const
Returns stored QVariant as a boolean.
Definition: mythcommandlineparser.cpp:2201
MARK_GOP_BYFRAME
@ MARK_GOP_BYFRAME
Definition: programtypes.h:65
MythDate::ISODate
@ ISODate
Default UTC.
Definition: mythdate.h:17
GetAppBinDir
QString GetAppBinDir(void)
Definition: mythdirs.cpp:221
recordingutils.h
StringUtil::formatBytes
MBASE_PUBLIC QString formatBytes(int64_t sizeB, int prec=1)
Definition: stringutil.cpp:378
MythDate::kDateTimeFull
@ kDateTimeFull
Default local time.
Definition: mythdate.h:23
RemoteGetRecordedList
std::vector< ProgramInfo * > * RemoteGetRecordedList(int sort)
Definition: remoteutil.cpp:19
MythDate::kTime
@ kTime
Default local time.
Definition: mythdate.h:22
exitcodes.h
CheckRecordings
static int CheckRecordings(const MythUtilCommandLineParser &cmdline)
Definition: recordingutils.cpp:48
registerRecordingUtils
void registerRecordingUtils(UtilMap &utilMap)
Definition: recordingutils.cpp:205
MythSystem::Create
static MythSystem * Create(const QStringList &args, uint flags=kMSNone, const QString &startPath=QString(), Priority cpuPriority=kInheritPriority, Priority diskPriority=kInheritPriority)
Definition: mythsystem.cpp:201
ProgramInfo::GetSubtitle
QString GetSubtitle(void) const
Definition: programinfo.h:363