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  ProgramInfo *p;
74  std::vector<ProgramInfo *> *recordingList = RemoteGetRecordedList(-1);
75  std::vector<ProgramInfo *> missingRecordings;
76  std::vector<ProgramInfo *> zeroByteRecordings;
77  std::vector<ProgramInfo *> noSeektableRecordings;
78 
79  if (!recordingList)
80  {
81  cout << "ERROR - failed to get recording list from backend" << endl;
82  return GENERIC_EXIT_NOT_OK;
83  }
84 
85  bool fixSeektable = cmdline.toBool("fixseektable");
86 
87  cout << "Fix seektable is: " << fixSeektable << endl;
88 
89  if (!recordingList->empty())
90  {
91  vector<ProgramInfo *>::iterator i = recordingList->begin();
92  for ( ; i != recordingList->end(); ++i)
93  {
94  p = *i;
95  // ignore live tv and deleted recordings
96  if (p->GetRecordingGroup() == "LiveTV" ||
97  p->GetRecordingGroup() == "Deleted")
98  {
99  i = recordingList->erase(i);
100  --i;
101  continue;
102  }
103 
104  cout << "Checking: " << qPrintable(CreateProgramInfoString(*p)) << endl;
105  bool foundFile = true;
106 
107  QString url = p->GetPlaybackURL();
108 
109  if (url.startsWith('/'))
110  {
111  QFileInfo fi(url);
112  if (!fi.exists())
113  {
114  cout << "File not found" << endl;
115  missingRecordings.push_back(p);
116  foundFile = false;
117  }
118  else
119  {
120  if (fi.size() == 0)
121  {
122  cout << "File was found but has zero length" << endl;
123  zeroByteRecordings.push_back(p);
124  }
125  }
126  }
127  else if (url.startsWith("myth:"))
128  {
129  if (!RemoteFile::Exists(url))
130  {
131  cout << "File not found" << endl;
132  missingRecordings.push_back(p);
133  foundFile = false;
134  }
135  else
136  {
137  RemoteFile rf(url);
138  if (rf.GetFileSize() == 0)
139  {
140  cout << "File was found but has zero length" << endl;
141  zeroByteRecordings.push_back(p);
142  }
143  }
144  }
145 
146  frm_pos_map_t posMap;
148  if (posMap.isEmpty())
149  p->QueryPositionMap(posMap, MARK_GOP_START);
150  if (posMap.isEmpty())
151  p->QueryPositionMap(posMap, MARK_KEYFRAME);
152 
153  if (posMap.isEmpty())
154  {
155  cout << "No seektable found" << endl;
156 
157  noSeektableRecordings.push_back(p);
158 
159  if (foundFile && fixSeektable)
160  {
161  QString command = GetAppBinDir() + "mythcommflag " +
162  QString("--rebuild --chanid %1 --starttime %2")
163  .arg(p->GetChanID())
165  cout << "Running - " << qPrintable(command) << endl;
166  QScopedPointer<MythSystem> cmd(MythSystem::Create(command));
167  cmd->Wait(0);
168  if (cmd.data()->GetExitCode() != GENERIC_EXIT_OK)
169  {
170  cout << "ERROR - mythcommflag exited with result: " << cmd.data()->GetExitCode() << endl;
171  }
172  }
173  }
174 
175  cout << "-------------------------------------------------------------------" << endl;
176  }
177  }
178 
179  if (!missingRecordings.empty())
180  {
181  cout << endl << endl;
182  cout << "MISSING RECORDINGS" << endl;
183  cout << "------------------" << endl;
184  vector<ProgramInfo *>::iterator i = missingRecordings.begin();
185  for ( ; i != missingRecordings.end(); ++i)
186  {
187  p = *i;
188  cout << qPrintable(CreateProgramInfoString(*p)) << endl;
189  cout << qPrintable(p->GetPlaybackURL()) << endl;
190  cout << "-------------------------------------------------------------------" << endl;
191  }
192  }
193 
194  if (!zeroByteRecordings.empty())
195  {
196  cout << endl << endl;
197  cout << "ZERO BYTE RECORDINGS" << endl;
198  cout << "--------------------" << endl;
199  vector<ProgramInfo *>::iterator i = zeroByteRecordings.begin();
200  for ( ; i != zeroByteRecordings.end(); ++i)
201  {
202  p = *i;
203  cout << qPrintable(CreateProgramInfoString(*p)) << endl;
204  cout << qPrintable(p->GetPlaybackURL()) << endl;
205  cout << "-------------------------------------------------------------------" << endl;
206  }
207  }
208 
209  if (!noSeektableRecordings.empty())
210  {
211  cout << endl << endl;
212  cout << "NO SEEKTABLE RECORDINGS" << endl;
213  cout << "-----------------------" << endl;
214  vector<ProgramInfo *>::iterator i = noSeektableRecordings.begin();
215  for ( ; i != noSeektableRecordings.end(); ++i)
216  {
217  p = *i;
218  cout << qPrintable(CreateProgramInfoString(*p)) << endl;
219  cout << qPrintable(p->GetPlaybackURL()) << endl;
220  cout << "File size is " << qPrintable(formatSize(p->GetFilesize(), 2)) << endl;
221  cout << "-------------------------------------------------------------------" << endl;
222  }
223  }
224 
225  cout << endl << endl << "SUMMARY" << endl;
226  cout << "Recordings : " << recordingList->size() << endl;
227  cout << "Missing Recordings : " << missingRecordings.size() << endl;
228  cout << "Zero byte Recordings : " << zeroByteRecordings.size() << endl;
229  cout << "Missing Seektables : " << noSeektableRecordings.size() << endl;
230 
231  return GENERIC_EXIT_OK;
232 }
233 
235 {
236  utilMap["checkrecordings"] = &CheckRecordings;
237 }
238 
239 /* vim: set expandtab tabstop=4 shiftwidth=4: */
#define GENERIC_EXIT_OK
Exited with no error.
Definition: exitcodes.h:10
virtual uint64_t GetFilesize(void) const
bool toBool(const QString &key) const
Returns stored QVariant as a boolean.
QString GetTitle(void) const
Definition: programinfo.h:353
static MythSystem * Create(const QStringList &args, uint flags=kMSNone, QString startPath=QString(), Priority cpuPriority=kInheritPriority, Priority diskPriority=kInheritPriority)
Definition: mythsystem.cpp:206
static QString CreateProgramInfoString(const ProgramInfo &pginfo)
Holds information on recordings and videos.
Definition: programinfo.h:66
QMap< QString, UtilFunc > UtilMap
Definition: mythutil.h:16
Default local time.
Definition: mythdate.h:19
QString GetAppBinDir(void)
Definition: mythdirs.cpp:221
void registerRecordingUtils(UtilMap &utilMap)
QString GetSubtitle(void) const
Definition: programinfo.h:355
QString GetRecordingGroup(void) const
Definition: programinfo.h:411
Do Today/Yesterday/Tomorrow transform.
Definition: mythdate.h:23
static int CheckRecordings(const MythUtilCommandLineParser &cmdline)
MythCommFlagCommandLineParser cmdline
QString toString(const QDateTime &raw_dt, uint format)
Returns formatted string representing the time.
Definition: mythdate.cpp:101
long long GetFileSize(void) const
GetFileSize: returns the remote file's size at the time it was first opened Will query the server in ...
static QString formatSize(int64_t sizeKB, int prec)
static bool Exists(const QString &url, struct stat *fileinfo)
Definition: remotefile.cpp:461
uint GetChanID(void) const
This is the unique key used in the database to locate tuning information.
Definition: programinfo.h:364
QString GetPlaybackURL(bool checkMaster=false, bool forceCheckLocal=false) const
Returns filename or URL to be used to play back this recording.
Default local time.
Definition: mythdate.h:20
QDateTime GetRecordingStartTime(void) const
Approximate time the recording started.
Definition: programinfo.h:396
QDateTime GetRecordingEndTime(void) const
Approximate time the recording should have ended, did end, or is intended to end.
Definition: programinfo.h:404
QMap< long long, long long > frm_pos_map_t
Frame # -> File offset map.
Definition: programtypes.h:46
void QueryPositionMap(frm_pos_map_t &, MarkTypes type) const
#define GENERIC_EXIT_NOT_OK
Exited with error.
Definition: exitcodes.h:11
vector< ProgramInfo * > * RemoteGetRecordedList(int sort)
Definition: remoteutil.cpp:16
Default UTC.
Definition: mythdate.h:14