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 using namespace std;
6 #include <sys/stat.h>
7 
8 // Qt
9 #include <QFileInfo>
10 #include <QScopedPointer>
11 
12 // libmyth* includes
13 #include "exitcodes.h"
14 #include "mythlogging.h"
15 #include "remoteutil.h"
16 #include "remotefile.h"
17 #include "mythsystem.h"
18 #include "mythdirs.h"
19 
20 // Local includes
21 #include "recordingutils.h"
22 
23 static QString formatSize(int64_t sizeKB, int prec)
24 {
25  if (sizeKB>1024*1024*1024) // Terabytes
26  {
27  double sizeGB = sizeKB/(1024*1024*1024.0);
28  return QString("%1 TB").arg(sizeGB, 0, 'f', (sizeGB>10)?0:prec);
29  }
30  if (sizeKB>1024*1024) // Gigabytes
31  {
32  double sizeGB = sizeKB/(1024*1024.0);
33  return QString("%1 GB").arg(sizeGB, 0, 'f', (sizeGB>10)?0:prec);
34  }
35  if (sizeKB>1024) // Megabytes
36  {
37  double sizeMB = sizeKB/1024.0;
38  return QString("%1 MB").arg(sizeMB, 0, 'f', (sizeMB>10)?0:prec);
39  }
40  // Kilobytes
41  return QString("%1 KB").arg(sizeKB);
42 }
43 
44 static QString CreateProgramInfoString(const ProgramInfo &pginfo)
45 {
46  QDateTime recstartts = pginfo.GetRecordingStartTime();
47  QDateTime recendts = pginfo.GetRecordingEndTime();
48 
49  QString timedate = QString("%1 - %2")
50  .arg(MythDate::toString(
52  .arg(MythDate::toString(recendts, MythDate::kTime));
53 
54  QString title = pginfo.GetTitle();
55 
56  QString extra;
57 
58  if (!pginfo.GetSubtitle().isEmpty())
59  {
60  extra = QString(" ~ ") + pginfo.GetSubtitle();
61  int maxll = max(title.length(), 20);
62  if (extra.length() > maxll)
63  extra = extra.left(maxll - 3) + "...";
64  }
65 
66  return QString("%1%2 - %3").arg(title).arg(extra).arg(timedate);
67 }
68 
70 {
71  cout << "Checking Recordings" << endl;
72 
73  std::vector<ProgramInfo *> *recordingList = RemoteGetRecordedList(-1);
74  std::vector<ProgramInfo *> missingRecordings;
75  std::vector<ProgramInfo *> zeroByteRecordings;
76  std::vector<ProgramInfo *> noSeektableRecordings;
77 
78  if (!recordingList)
79  {
80  cout << "ERROR - failed to get recording list from backend" << endl;
81  return GENERIC_EXIT_NOT_OK;
82  }
83 
84  bool fixSeektable = cmdline.toBool("fixseektable");
85 
86  cout << "Fix seektable is: " << fixSeektable << endl;
87 
88  if (!recordingList->empty())
89  {
90  for (auto i = recordingList->begin(); i != recordingList->end(); ++i)
91  {
92  ProgramInfo *p = *i;
93  // ignore live tv and deleted recordings
94  if (p->GetRecordingGroup() == "LiveTV" ||
95  p->GetRecordingGroup() == "Deleted")
96  {
97  i = recordingList->erase(i);
98  --i;
99  continue;
100  }
101 
102  cout << "Checking: " << qPrintable(CreateProgramInfoString(*p)) << endl;
103  bool foundFile = true;
104 
105  QString url = p->GetPlaybackURL();
106 
107  if (url.startsWith('/'))
108  {
109  QFileInfo fi(url);
110  if (!fi.exists())
111  {
112  cout << "File not found" << endl;
113  missingRecordings.push_back(p);
114  foundFile = false;
115  }
116  else
117  {
118  if (fi.size() == 0)
119  {
120  cout << "File was found but has zero length" << endl;
121  zeroByteRecordings.push_back(p);
122  }
123  }
124  }
125  else if (url.startsWith("myth:"))
126  {
127  if (!RemoteFile::Exists(url))
128  {
129  cout << "File not found" << endl;
130  missingRecordings.push_back(p);
131  foundFile = false;
132  }
133  else
134  {
135  RemoteFile rf(url);
136  if (rf.GetFileSize() == 0)
137  {
138  cout << "File was found but has zero length" << endl;
139  zeroByteRecordings.push_back(p);
140  }
141  }
142  }
143 
144  frm_pos_map_t posMap;
145  p->QueryPositionMap(posMap, MARK_GOP_BYFRAME);
146  if (posMap.isEmpty())
147  p->QueryPositionMap(posMap, MARK_GOP_START);
148  if (posMap.isEmpty())
149  p->QueryPositionMap(posMap, MARK_KEYFRAME);
150 
151  if (posMap.isEmpty())
152  {
153  cout << "No seektable found" << endl;
154 
155  noSeektableRecordings.push_back(p);
156 
157  if (foundFile && fixSeektable)
158  {
159  QString command = GetAppBinDir() + "mythcommflag " +
160  QString("--rebuild --chanid %1 --starttime %2")
161  .arg(p->GetChanID())
162  .arg(p->GetRecordingStartTime(MythDate::ISODate));
163  cout << "Running - " << qPrintable(command) << endl;
164  QScopedPointer<MythSystem> cmd(MythSystem::Create(command));
165  cmd->Wait(0);
166  if (cmd.data()->GetExitCode() != GENERIC_EXIT_OK)
167  {
168  cout << "ERROR - mythcommflag exited with result: " << cmd.data()->GetExitCode() << endl;
169  }
170  }
171  }
172 
173  cout << "-------------------------------------------------------------------" << endl;
174  }
175  }
176 
177  if (!missingRecordings.empty())
178  {
179  cout << endl << endl;
180  cout << "MISSING RECORDINGS" << endl;
181  cout << "------------------" << endl;
182  for (auto *p : missingRecordings)
183  {
184  cout << qPrintable(CreateProgramInfoString(*p)) << endl;
185  cout << qPrintable(p->GetPlaybackURL()) << endl;
186  cout << "-------------------------------------------------------------------" << endl;
187  }
188  }
189 
190  if (!zeroByteRecordings.empty())
191  {
192  cout << endl << endl;
193  cout << "ZERO BYTE RECORDINGS" << endl;
194  cout << "--------------------" << endl;
195  for (auto *p : zeroByteRecordings)
196  {
197  cout << qPrintable(CreateProgramInfoString(*p)) << endl;
198  cout << qPrintable(p->GetPlaybackURL()) << endl;
199  cout << "-------------------------------------------------------------------" << endl;
200  }
201  }
202 
203  if (!noSeektableRecordings.empty())
204  {
205  cout << endl << endl;
206  cout << "NO SEEKTABLE RECORDINGS" << endl;
207  cout << "-----------------------" << endl;
208  for (auto *p : noSeektableRecordings)
209  {
210  cout << qPrintable(CreateProgramInfoString(*p)) << endl;
211  cout << qPrintable(p->GetPlaybackURL()) << endl;
212  cout << "File size is " << qPrintable(formatSize(p->GetFilesize(), 2)) << endl;
213  cout << "-------------------------------------------------------------------" << endl;
214  }
215  }
216 
217  cout << endl << endl << "SUMMARY" << endl;
218  cout << "Recordings : " << recordingList->size() << endl;
219  cout << "Missing Recordings : " << missingRecordings.size() << endl;
220  cout << "Zero byte Recordings : " << zeroByteRecordings.size() << endl;
221  cout << "Missing Seektables : " << noSeektableRecordings.size() << endl;
222 
223  return GENERIC_EXIT_OK;
224 }
225 
227 {
228  utilMap["checkrecordings"] = &CheckRecordings;
229 }
230 
231 /* vim: set expandtab tabstop=4 shiftwidth=4: */
MARK_KEYFRAME
@ MARK_KEYFRAME
Definition: programtypes.h:62
MythDate::toString
QString toString(const QDateTime &raw_dt, uint format)
Returns formatted string representing the time.
Definition: mythdate.cpp:80
GENERIC_EXIT_OK
#define GENERIC_EXIT_OK
Exited with no error.
Definition: exitcodes.h:10
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:1092
RemoteFile::Exists
static bool Exists(const QString &url, struct stat *fileinfo)
Definition: remotefile.cpp:462
title
QString title
Definition: mythplugins/mytharchive/mytharchivehelper/main.cpp:633
RemoteFile
Definition: remotefile.h:18
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:407
MythUtilCommandLineParser
Definition: mythutil/commandlineparser.h:9
remoteutil.h
ProgramInfo::GetRecordingStartTime
QDateTime GetRecordingStartTime(void) const
Approximate time the recording started.
Definition: programinfo.h:399
mythsystem.h
mythlogging.h
remotefile.h
hardwareprofile.config.p
p
Definition: config.py:33
MARK_GOP_START
@ MARK_GOP_START
Definition: programtypes.h:61
RemoteGetRecordedList
vector< ProgramInfo * > * RemoteGetRecordedList(int sort)
Definition: remoteutil.cpp:16
ProgramInfo::GetTitle
QString GetTitle(void) const
Definition: programinfo.h:356
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:23
CreateProgramInfoString
static QString CreateProgramInfoString(const ProgramInfo &pginfo)
Definition: recordingutils.cpp:44
cmdline
MythCommFlagCommandLineParser cmdline
Definition: mythtv/programs/mythcommflag/main.cpp:77
ProgramInfo
Holds information on recordings and videos.
Definition: programinfo.h:68
UtilMap
QMap< QString, UtilFunc > UtilMap
Definition: mythutil.h:15
GENERIC_EXIT_NOT_OK
#define GENERIC_EXIT_NOT_OK
Exited with error.
Definition: exitcodes.h:11
MythCommandLineParser::toBool
bool toBool(const QString &key) const
Returns stored QVariant as a boolean.
Definition: mythcommandlineparser.cpp:1955
MARK_GOP_BYFRAME
@ MARK_GOP_BYFRAME
Definition: programtypes.h:64
MythDate::ISODate
@ ISODate
Default UTC.
Definition: mythdate.h:14
GetAppBinDir
QString GetAppBinDir(void)
Definition: mythdirs.cpp:221
recordingutils.h
formatSize
static QString formatSize(int64_t sizeKB, int prec)
Definition: recordingutils.cpp:23
MythDate::kDateTimeFull
@ kDateTimeFull
Default local time.
Definition: mythdate.h:20
MythDate::kTime
@ kTime
Default local time.
Definition: mythdate.h:19
exitcodes.h
CheckRecordings
static int CheckRecordings(const MythUtilCommandLineParser &cmdline)
Definition: recordingutils.cpp:69
registerRecordingUtils
void registerRecordingUtils(UtilMap &utilMap)
Definition: recordingutils.cpp:226
MythSystem::Create
static MythSystem * Create(const QStringList &args, uint flags=kMSNone, const QString &startPath=QString(), Priority cpuPriority=kInheritPriority, Priority diskPriority=kInheritPriority)
Definition: mythsystem.cpp:203
ProgramInfo::GetSubtitle
QString GetSubtitle(void) const
Definition: programinfo.h:358