MythTV  master
mythtv/programs/mythcommflag/main.cpp
Go to the documentation of this file.
1 
2 #if defined ANDROID && __ANDROID_API__ < 24
3 // ftello and fseeko do not exist in android before api level 24
4 #define ftello ftell
5 #define fseeko fseek
6 #endif
7 
8 // POSIX headers
9 #include <unistd.h>
10 #include <sys/time.h> // for gettimeofday
11 
12 // ANSI C headers
13 #include <cstdlib>
14 #include <cstdio>
15 #include <ctime>
16 #include <cmath>
17 
18 // C++ headers
19 #include <string>
20 #include <iostream>
21 #include <fstream>
22 using namespace std;
23 
24 // Qt headers
25 #include <QCoreApplication>
26 #include <QString>
27 #include <QRegExp>
28 #include <QDir>
29 #include <QEvent>
30 
31 // MythTV headers
32 #include "mythmiscutil.h"
33 #include "mythdate.h"
34 #include "exitcodes.h"
35 #include "mythcontext.h"
36 #include "mythdb.h"
37 #include "mythversion.h"
38 #include "mythcommflagplayer.h"
39 #include "programinfo.h"
40 #include "remoteutil.h"
41 #include "remotefile.h"
42 #include "tvremoteutil.h"
43 #include "jobqueue.h"
44 #include "remoteencoder.h"
45 #include "io/mythmediabuffer.h"
46 #include "commandlineparser.h"
47 #include "mythtranslation.h"
48 #include "loggingserver.h"
49 #include "mythlogging.h"
50 #include "signalhandling.h"
51 #include "cleanupguard.h"
52 
53 // Commercial Flagging headers
54 #include "CommDetectorBase.h"
55 #include "CommDetectorFactory.h"
56 #include "SlotRelayer.h"
57 #include "CustomEventRelayer.h"
58 
59 #define LOC QString("MythCommFlag: ")
60 #define LOC_WARN QString("MythCommFlag, Warning: ")
61 #define LOC_ERR QString("MythCommFlag, Error: ")
62 
63 namespace
64 {
65  void cleanup()
66  {
67  delete gContext;
68  gContext = nullptr;
70  }
71 }
72 
73 int quiet = 0;
74 bool progress = true;
75 bool force = false;
76 
78 
79 bool watchingRecording = false;
83 int recorderNum = -1;
84 
85 int jobID = -1;
86 int lastCmd = -1;
87 
88 static QMap<QString,SkipType> *init_skip_types();
89 QMap<QString,SkipType> *skipTypes = init_skip_types();
90 
91 static QMap<QString,SkipType> *init_skip_types(void)
92 {
93  auto *tmp = new QMap<QString,SkipType>;
94  (*tmp)["commfree"] = COMM_DETECT_COMMFREE;
95  (*tmp)["uninit"] = COMM_DETECT_UNINIT;
96  (*tmp)["off"] = COMM_DETECT_OFF;
97  (*tmp)["blank"] = COMM_DETECT_BLANKS;
98  (*tmp)["blanks"] = COMM_DETECT_BLANKS;
99  (*tmp)["scene"] = COMM_DETECT_SCENE;
100  (*tmp)["blankscene"] = COMM_DETECT_BLANK_SCENE;
101  (*tmp)["blank_scene"] = COMM_DETECT_BLANK_SCENE;
102  (*tmp)["logo"] = COMM_DETECT_LOGO;
103  (*tmp)["all"] = COMM_DETECT_ALL;
104  (*tmp)["d2"] = COMM_DETECT_2;
105  (*tmp)["d2_logo"] = COMM_DETECT_2_LOGO;
106  (*tmp)["d2_blank"] = COMM_DETECT_2_BLANK;
107  (*tmp)["d2_scene"] = COMM_DETECT_2_SCENE;
108  (*tmp)["d2_all"] = COMM_DETECT_2_ALL;
109  return tmp;
110 }
111 
113 {
116 };
118 
119 static QMap<QString,OutputMethod> *init_output_types();
120 QMap<QString,OutputMethod> *outputTypes = init_output_types();
121 
122 static QMap<QString,OutputMethod> *init_output_types(void)
123 {
124  auto *tmp = new QMap<QString,OutputMethod>;
125  (*tmp)["essentials"] = kOutputMethodEssentials;
126  (*tmp)["full"] = kOutputMethodFull;
127  return tmp;
128 }
129 
130 static QString get_filename(ProgramInfo *program_info)
131 {
132  QString filename = program_info->GetPathname();
133  if (!QFile::exists(filename))
134  filename = program_info->GetPlaybackURL(true);
135  return filename;
136 }
137 
138 static int QueueCommFlagJob(uint chanid, const QDateTime& starttime, bool rebuild)
139 {
140  QString startstring = MythDate::toString(starttime, MythDate::kFilename);
141  const ProgramInfo pginfo(chanid, starttime);
142 
143  if (!pginfo.GetChanID())
144  {
145  if (progress)
146  {
147  QString tmp = QString(
148  "Unable to find program info for chanid %1 @ %2")
149  .arg(chanid).arg(startstring);
150  cerr << tmp.toLocal8Bit().constData() << endl;
151  }
153  }
154 
155  if (cmdline.toBool("dryrun"))
156  {
157  QString tmp = QString("Job have been queued for chanid %1 @ %2")
158  .arg(chanid).arg(startstring);
159  cerr << tmp.toLocal8Bit().constData() << endl;
160  return GENERIC_EXIT_OK;
161  }
162 
163  bool result = JobQueue::QueueJob(JOB_COMMFLAG,
164  pginfo.GetChanID(), pginfo.GetRecordingStartTime(), "", "", "",
165  rebuild ? JOB_REBUILD : 0, JOB_QUEUED, QDateTime());
166 
167  if (result)
168  {
169  if (progress)
170  {
171  QString tmp = QString("Job Queued for chanid %1 @ %2")
172  .arg(chanid).arg(startstring);
173  cerr << tmp.toLocal8Bit().constData() << endl;
174  }
175  return GENERIC_EXIT_OK;
176  }
177 
178  if (progress)
179  {
180  QString tmp = QString("Error queueing job for chanid %1 @ %2")
181  .arg(chanid).arg(startstring);
182  cerr << tmp.toLocal8Bit().constData() << endl;
183  }
184  return GENERIC_EXIT_DB_ERROR;
185 }
186 
187 static int CopySkipListToCutList(uint chanid, const QDateTime& starttime)
188 {
189  frm_dir_map_t cutlist;
190  frm_dir_map_t::const_iterator it;
191 
192  QString startstring = MythDate::toString(starttime, MythDate::kFilename);
193  const ProgramInfo pginfo(chanid, starttime);
194 
195  if (!pginfo.GetChanID())
196  {
197  LOG(VB_GENERAL, LOG_ERR,
198  QString("No program data exists for channel %1 at %2")
199  .arg(chanid).arg(startstring));
201  }
202 
203  pginfo.QueryCommBreakList(cutlist);
204  for (it = cutlist.begin(); it != cutlist.end(); ++it)
205  {
206  if (*it == MARK_COMM_START)
207  cutlist[it.key()] = MARK_CUT_START;
208  else
209  cutlist[it.key()] = MARK_CUT_END;
210  }
211  pginfo.SaveCutList(cutlist);
212 
213  return GENERIC_EXIT_OK;
214 }
215 
216 static int ClearSkipList(uint chanid, const QDateTime& starttime)
217 {
218  QString startstring = MythDate::toString(starttime, MythDate::kFilename);
219  const ProgramInfo pginfo(chanid, starttime);
220 
221  if (!pginfo.GetChanID())
222  {
223  LOG(VB_GENERAL, LOG_ERR,
224  QString("No program data exists for channel %1 at %2")
225  .arg(chanid).arg(startstring));
227  }
228 
229  frm_dir_map_t skiplist;
230  pginfo.SaveCommBreakList(skiplist);
231 
232  LOG(VB_GENERAL, LOG_NOTICE, "Commercial skip list cleared");
233 
234  return GENERIC_EXIT_OK;
235 }
236 
237 static int SetCutList(uint chanid, const QDateTime& starttime, QString newCutList)
238 {
239  frm_dir_map_t cutlist;
240 
241  newCutList.replace(QRegExp(" "), "");
242 
243 #if QT_VERSION < QT_VERSION_CHECK(5,14,0)
244  QStringList tokens = newCutList.split(",", QString::SkipEmptyParts);
245 #else
246  QStringList tokens = newCutList.split(",", Qt::SkipEmptyParts);
247 #endif
248 
249  for (int i = 0; i < tokens.size(); i++)
250  {
251 #if QT_VERSION < QT_VERSION_CHECK(5,14,0)
252  QStringList cutpair = tokens[i].split("-", QString::SkipEmptyParts);
253 #else
254  QStringList cutpair = tokens[i].split("-", Qt::SkipEmptyParts);
255 #endif
256  cutlist[cutpair[0].toInt()] = MARK_CUT_START;
257  cutlist[cutpair[1].toInt()] = MARK_CUT_END;
258  }
259 
260  QString startstring = MythDate::toString(starttime, MythDate::kFilename);
261  const ProgramInfo pginfo(chanid, starttime);
262 
263  if (!pginfo.GetChanID())
264  {
265  LOG(VB_GENERAL, LOG_ERR,
266  QString("No program data exists for channel %1 at %2")
267  .arg(chanid).arg(startstring));
269  }
270 
271  pginfo.SaveCutList(cutlist);
272 
273  LOG(VB_GENERAL, LOG_NOTICE, QString("Cutlist set to: %1").arg(newCutList));
274 
275  return GENERIC_EXIT_OK;
276 }
277 
278 static int GetMarkupList(const QString& list, uint chanid, const QDateTime& starttime)
279 {
280  frm_dir_map_t cutlist;
281  frm_dir_map_t::const_iterator it;
282  QString result;
283 
284  QString startstring = MythDate::toString(starttime, MythDate::kFilename);
285  const ProgramInfo pginfo(chanid, starttime);
286 
287  if (!pginfo.GetChanID())
288  {
289  LOG(VB_GENERAL, LOG_ERR,
290  QString("No program data exists for channel %1 at %2")
291  .arg(chanid).arg(startstring));
293  }
294 
295  if (list == "cutlist")
296  pginfo.QueryCutList(cutlist);
297  else
298  pginfo.QueryCommBreakList(cutlist);
299 
300  uint64_t lastStart = 0;
301  for (it = cutlist.begin(); it != cutlist.end(); ++it)
302  {
303  if ((*it == MARK_COMM_START) ||
304  (*it == MARK_CUT_START))
305  {
306  if (!result.isEmpty())
307  result += ",";
308  lastStart = it.key();
309  result += QString("%1-").arg(lastStart);
310  }
311  else
312  {
313  if (result.isEmpty())
314  result += "0-";
315  result += QString("%1").arg(it.key());
316  }
317  }
318 
319  if (result.endsWith('-'))
320  {
321  uint64_t lastFrame = pginfo.QueryLastFrameInPosMap() + 60;
322  if (lastFrame > lastStart)
323  result += QString("%1").arg(lastFrame);
324  }
325 
326  if (list == "cutlist")
327  cout << QString("Cutlist: %1\n").arg(result).toLocal8Bit().constData();
328  else
329  {
330  cout << QString("Commercial Skip List: %1\n")
331  .arg(result).toLocal8Bit().constData();
332  }
333 
334  return GENERIC_EXIT_OK;
335 }
336 
338  ostream &output, const frm_dir_map_t &commercialBreakList)
339 {
340  if (progress)
341  output << "----------------------------" << endl;
342 
343  if (commercialBreakList.empty())
344  {
345  if (progress)
346  output << "No breaks" << endl;
347  }
348  else
349  {
350  frm_dir_map_t::const_iterator it = commercialBreakList.begin();
351  for (; it != commercialBreakList.end(); ++it)
352  {
353  output << "framenum: " << it.key() << "\tmarktype: " << *it
354  << endl;
355  }
356  }
357 
358  if (progress)
359  output << "----------------------------" << endl;
360 }
361 
363  const ProgramInfo *program_info,
364  const frm_dir_map_t &commBreakList,
365  uint64_t frame_count,
366  const CommDetectorBase *commDetect,
367  const QString &output_filename)
368 {
369  if (output_filename.isEmpty())
370  return;
371 
372  ostream *out = &cout;
373  if (output_filename != "-")
374  {
375  QByteArray tmp = output_filename.toLocal8Bit();
376  out = new fstream(tmp.constData(), ios::app | ios::out );
377  }
378 
379  if (progress)
380  {
381  QString tmp = "";
382  if (program_info->GetChanID())
383  {
384  tmp = QString("commercialBreakListFor: %1 on %2 @ %3")
385  .arg(program_info->GetTitle())
386  .arg(program_info->GetChanID())
387  .arg(program_info->GetRecordingStartTime(MythDate::ISODate));
388  }
389  else
390  {
391  tmp = QString("commercialBreakListFor: %1")
392  .arg(program_info->GetPathname());
393  }
394 
395  const QByteArray tmp2 = tmp.toLocal8Bit();
396  *out << tmp2.constData() << endl;
397 
398  if (frame_count)
399  *out << "totalframecount: " << frame_count << endl;
400  }
401 
402  if (commDetect)
403  commDetect->PrintFullMap(*out, &commBreakList, progress);
404  else
405  streamOutCommercialBreakList(*out, commBreakList);
406 
407  if (out != &cout)
408  delete out;
409 }
410 
411 static void commDetectorBreathe()
412 {
413  //this is connected to the commdetectors breathe signal so we get a chance
414  //while its busy to see if the user already told us to stop.
415  qApp->processEvents();
416 
417  if (jobID != -1)
418  {
419  int curCmd = JobQueue::GetJobCmd(jobID);
420  if (curCmd == lastCmd)
421  return;
422 
423  switch (curCmd)
424  {
425  case JOB_STOP:
426  {
427  commDetector->stop();
428  break;
429  }
430  case JOB_PAUSE:
431  {
432  JobQueue::ChangeJobStatus(jobID, JOB_PAUSED,
433  QCoreApplication::translate("(mythcommflag)",
434  "Paused", "Job status"));
435  commDetector->pause();
436  break;
437  }
438  case JOB_RESUME:
439  {
440  JobQueue::ChangeJobStatus(jobID, JOB_RUNNING,
441  QCoreApplication::translate("(mythcommflag)",
442  "Running", "Job status"));
443  commDetector->resume();
444  break;
445  }
446  }
447  }
448 }
449 
450 static void commDetectorStatusUpdate(const QString& status)
451 {
452  if (jobID != -1)
453  {
454  JobQueue::ChangeJobStatus(jobID, JOB_RUNNING, status);
456  }
457 }
458 
460 {
461  frm_dir_map_t newCommercialMap;
462  commDetector->GetCommercialBreakList(newCommercialMap);
463 
464  frm_dir_map_t::Iterator it = newCommercialMap.begin();
465  QString message = "COMMFLAG_UPDATE ";
466  message += global_program_info->MakeUniqueKey();
467 
468  for (it = newCommercialMap.begin();
469  it != newCommercialMap.end(); ++it)
470  {
471  if (it != newCommercialMap.begin())
472  message += ",";
473  else
474  message += " ";
475  message += QString("%1:%2").arg(it.key())
476  .arg(*it);
477  }
478 
479  LOG(VB_COMMFLAG, LOG_INFO,
480  QString("mythcommflag sending update: %1").arg(message));
481 
482  gCoreContext->SendMessage(message);
483 }
484 
485 static void incomingCustomEvent(QEvent* e)
486 {
487  if (e->type() == MythEvent::MythEventMessage)
488  {
489  auto *me = dynamic_cast<MythEvent *>(e);
490  if (me == nullptr)
491  return;
492 
493  QString message = me->Message();
494 
495  message = message.simplified();
496 #if QT_VERSION < QT_VERSION_CHECK(5,14,0)
497  QStringList tokens = message.split(" ", QString::SkipEmptyParts);
498 #else
499  QStringList tokens = message.split(" ", Qt::SkipEmptyParts);
500 #endif
501 
502  LOG(VB_COMMFLAG, LOG_INFO,
503  QString("mythcommflag: Received Event: '%1'") .arg(message));
504 
505  if ((watchingRecording) && (tokens.size() >= 3) &&
506  (tokens[0] == "DONE_RECORDING"))
507  {
508  int cardnum = tokens[1].toInt();
509  int filelen = tokens[2].toInt();
510 
511  message = QString("mythcommflag: Received a "
512  "DONE_RECORDING event for card %1. ")
513  .arg(cardnum);
514 
515  if (recorderNum != -1 && cardnum == recorderNum)
516  {
518  watchingRecording = false;
519  message += "Informed CommDetector that recording has finished.";
520  LOG(VB_COMMFLAG, LOG_INFO, message);
521  }
522  }
523 
524  if ((tokens.size() >= 2) && (tokens[0] == "COMMFLAG_REQUEST"))
525  {
526  uint chanid = 0;
527  QDateTime recstartts;
528  ProgramInfo::ExtractKey(tokens[1], chanid, recstartts);
529 
530  message = QString("mythcommflag: Received a "
531  "COMMFLAG_REQUEST event for chanid %1 @ %2. ")
532  .arg(chanid).arg(recstartts.toString(Qt::ISODate));
533 
534  if ((global_program_info->GetChanID() == chanid) &&
535  (global_program_info->GetRecordingStartTime() == recstartts))
536  {
538  message += "Requested CommDetector to generate new break list.";
539  LOG(VB_COMMFLAG, LOG_INFO, message);
540  }
541  }
542  }
543 }
544 
545 static int DoFlagCommercials(
546  ProgramInfo *program_info,
547  bool showPercentage, bool fullSpeed, int jobid,
548  MythCommFlagPlayer* cfp, SkipType commDetectMethod,
549  const QString &outputfilename, bool useDB)
550 {
552  commDetectMethod, showPercentage,
553  fullSpeed, cfp,
554  program_info->GetChanID(),
555  program_info->GetScheduledStartTime(),
556  program_info->GetScheduledEndTime(),
557  program_info->GetRecordingStartTime(),
558  program_info->GetRecordingEndTime(), useDB);
559 
560  if (jobid > 0)
561  LOG(VB_COMMFLAG, LOG_INFO,
562  QString("mythcommflag processing JobID %1").arg(jobid));
563 
564  if (useDB)
565  program_info->SaveCommFlagged(COMM_FLAG_PROCESSING);
566 
567  auto *cer = new CustomEventRelayer(incomingCustomEvent);
568  auto *a = new SlotRelayer(commDetectorBreathe);
569  auto *b = new SlotRelayer(commDetectorStatusUpdate);
571  QObject::connect(commDetector, SIGNAL(breathe()),
572  a, SLOT(relay()));
573  QObject::connect(commDetector, SIGNAL(statusUpdate(const QString&)),
574  b, SLOT(relay(const QString&)));
575  QObject::connect(commDetector, SIGNAL(gotNewCommercialBreakList()),
576  c, SLOT(relay()));
577 
578  if (useDB)
579  {
580  LOG(VB_COMMFLAG, LOG_INFO,
581  "mythcommflag sending COMMFLAG_START notification");
582  QString message = "COMMFLAG_START ";
583  message += program_info->MakeUniqueKey();
584  gCoreContext->SendMessage(message);
585  }
586 
587  bool result = commDetector->go();
588  int comms_found = 0;
589 
590  if (result)
591  {
592  cfp->SaveTotalDuration();
593 
594  frm_dir_map_t commBreakList;
595  commDetector->GetCommercialBreakList(commBreakList);
596  comms_found = commBreakList.size() / 2;
597 
598  if (useDB)
599  {
600  program_info->SaveMarkupFlag(MARK_UPDATED_CUT);
601  program_info->SaveCommBreakList(commBreakList);
602  program_info->SaveCommFlagged(COMM_FLAG_DONE);
603  }
604 
606  program_info, commBreakList, cfp->GetTotalFrameCount(),
608  outputfilename);
609  }
610  else
611  {
612  if (useDB)
613  program_info->SaveCommFlagged(COMM_FLAG_NOT_FLAGGED);
614  }
615 
617  commDetector = nullptr;
618  sleep(1);
619  tmp->deleteLater();
620 
621  cer->deleteLater();
622  c->deleteLater();
623  b->deleteLater();
624  a->deleteLater();
625 
626  return comms_found;
627 }
628 
629 static qint64 GetFileSize(ProgramInfo *program_info)
630 {
631  QString filename = get_filename(program_info);
632  qint64 size = -1;
633 
634  if (filename.startsWith("myth://"))
635  {
636  RemoteFile remotefile(filename, false, false, 0);
637  size = remotefile.GetFileSize();
638  }
639  else
640  {
641  QFile file(filename);
642  if (file.exists())
643  {
644  size = file.size();
645  }
646  }
647 
648  return size;
649 }
650 
651 static bool DoesFileExist(ProgramInfo *program_info)
652 {
653  QString filename = get_filename(program_info);
654  qint64 size = GetFileSize(program_info);
655 
656  if (size < 0)
657  {
658  LOG(VB_GENERAL, LOG_ERR, QString("Couldn't find file %1, aborting.")
659  .arg(filename));
660  return false;
661  }
662 
663  if (size == 0)
664  {
665  LOG(VB_GENERAL, LOG_ERR, QString("File %1 is zero-byte, aborting.")
666  .arg(filename));
667  return false;
668  }
669 
670  return true;
671 }
672 
673 static void UpdateFileSize(ProgramInfo *program_info)
674 {
675  qint64 size = GetFileSize(program_info);
676 
677  if (size != (qint64)program_info->GetFilesize())
678  program_info->SaveFilesize(size);
679 }
680 
681 static bool IsMarked(uint chanid, const QDateTime& starttime)
682 {
683  MSqlQuery mark_query(MSqlQuery::InitCon());
684  mark_query.prepare("SELECT commflagged, count(rm.type) "
685  "FROM recorded r "
686  "LEFT JOIN recordedmarkup rm ON "
687  "( r.chanid = rm.chanid AND "
688  "r.starttime = rm.starttime AND "
689  "type in (:MARK_START,:MARK_END)) "
690  "WHERE r.chanid = :CHANID AND "
691  "r.starttime = :STARTTIME "
692  "GROUP BY COMMFLAGGED;");
693  mark_query.bindValue(":MARK_START", MARK_COMM_START);
694  mark_query.bindValue(":MARK_END", MARK_COMM_END);
695  mark_query.bindValue(":CHANID", chanid);
696  mark_query.bindValue(":STARTTIME", starttime);
697 
698  if (mark_query.exec() && mark_query.isActive() &&
699  mark_query.size() > 0)
700  {
701  if (mark_query.next())
702  {
703  int flagStatus = mark_query.value(0).toInt();
704  int marksFound = mark_query.value(1).toInt();
705 
706  QString flagStatusStr = "UNKNOWN";
707  switch (flagStatus) {
709  flagStatusStr = "Not Flagged";
710  break;
711  case COMM_FLAG_DONE:
712  flagStatusStr = QString("Flagged with %1 breaks")
713  .arg(marksFound / 2);
714  break;
716  flagStatusStr = "Flagging";
717  break;
718  case COMM_FLAG_COMMFREE:
719  flagStatusStr = "Commercial Free";
720  break;
721  }
722 
723  LOG(VB_COMMFLAG, LOG_INFO,
724  QString("Status for chanid %1 @ %2 is '%3'")
725  .arg(chanid).arg(starttime.toString(Qt::ISODate))
726  .arg(flagStatusStr));
727 
728  if ((flagStatus == COMM_FLAG_NOT_FLAGGED) && (marksFound == 0))
729  return false;
730  }
731  }
732  return true;
733 }
734 
735 static int FlagCommercials(ProgramInfo *program_info, int jobid,
736  const QString &outputfilename, bool useDB, bool fullSpeed)
737 {
738  global_program_info = program_info;
739 
740  int breaksFound = 0;
741 
742  // configure commercial detection method
743  SkipType commDetectMethod = (SkipType)gCoreContext->GetNumSetting(
744  "CommercialSkipMethod", COMM_DETECT_ALL);
745 
746  if (cmdline.toBool("commmethod"))
747  {
748  // pull commercial detection method from command line
749  QString commmethod = cmdline.toString("commmethod");
750 
751  // assume definition as integer value
752  bool ok = true;
753  commDetectMethod = (SkipType) commmethod.toInt(&ok);
754  if (!ok)
755  {
756  // not an integer, attempt comma separated list
757  commDetectMethod = COMM_DETECT_UNINIT;
758 
759 #if QT_VERSION < QT_VERSION_CHECK(5,14,0)
760  QStringList list = commmethod.split(",", QString::SkipEmptyParts);
761 #else
762  QStringList list = commmethod.split(",", Qt::SkipEmptyParts);
763 #endif
764  for (const auto & it : qAsConst(list))
765  {
766  QString val = it.toLower();
767  if (val == "off")
768  {
769  commDetectMethod = COMM_DETECT_OFF;
770  break;
771  }
772 
773  if (!skipTypes->contains(val))
774  {
775  cerr << "Failed to decode --method option '"
776  << val.toLatin1().constData()
777  << "'" << endl;
779  }
780 
781  if (commDetectMethod == COMM_DETECT_UNINIT) {
782  commDetectMethod = skipTypes->value(val);
783  } else {
784  commDetectMethod = (SkipType) ((int)commDetectMethod
785  | (int)skipTypes->value(val));
786  }
787  }
788 
789  }
790  if (commDetectMethod == COMM_DETECT_UNINIT)
792  }
793  else if (useDB)
794  {
795  // if not manually specified, and we have a database to access
796  // pull the commflag type from the channel
798  query.prepare("SELECT commmethod FROM channel "
799  "WHERE chanid = :CHANID;");
800  query.bindValue(":CHANID", program_info->GetChanID());
801 
802  if (!query.exec())
803  {
804  // if the query fails, return with an error
805  commDetectMethod = COMM_DETECT_UNINIT;
806  MythDB::DBError("FlagCommercials", query);
807  }
808  else if (query.next())
809  {
810  commDetectMethod = (SkipType)query.value(0).toInt();
811  if (commDetectMethod == COMM_DETECT_COMMFREE)
812  {
813  // if the channel is commercial free, drop to the default instead
814  commDetectMethod = (SkipType)gCoreContext->GetNumSetting(
815  "CommercialSkipMethod", COMM_DETECT_ALL);
816  LOG(VB_COMMFLAG, LOG_INFO,
817  QString("Chanid %1 is marked as being Commercial Free, "
818  "we will use the default commercial detection "
819  "method").arg(program_info->GetChanID()));
820  }
821  else if (commDetectMethod == COMM_DETECT_UNINIT)
822  {
823  // no value set, so use the database default
824  commDetectMethod = (SkipType)gCoreContext->GetNumSetting(
825  "CommercialSkipMethod", COMM_DETECT_ALL);
826  }
827  LOG(VB_COMMFLAG, LOG_INFO,
828  QString("Using method: %1 from channel %2")
829  .arg(commDetectMethod).arg(program_info->GetChanID()));
830  }
831 
832  }
833  else if (!useDB)
834  {
835  // default to a cheaper method for debugging purposes
836  commDetectMethod = COMM_DETECT_BLANK;
837  }
838 
839  // if selection has failed, or intentionally disabled, drop out
840  if (commDetectMethod == COMM_DETECT_UNINIT)
841  return GENERIC_EXIT_NOT_OK;
842  if (commDetectMethod == COMM_DETECT_OFF)
843  return GENERIC_EXIT_OK;
844 
845  frm_dir_map_t blanks;
846  recorder = nullptr;
847 
848 /*
849  * is there a purpose to this not fulfilled by --getskiplist?
850  if (onlyDumpDBCommercialBreakList)
851  {
852  frm_dir_map_t commBreakList;
853  program_info->QueryCommBreakList(commBreakList);
854 
855  print_comm_flag_output(program_info, commBreakList,
856  0, nullptr, outputfilename);
857 
858  global_program_info = nullptr;
859  return GENERIC_EXIT_OK;
860  }
861 */
862 
863  if (!DoesFileExist(program_info))
864  {
865  LOG(VB_GENERAL, LOG_ERR,
866  "Unable to find file in defined storage paths.");
868  }
869 
870  QString filename = get_filename(program_info);
871 
873  if (!tmprbuf)
874  {
875  LOG(VB_GENERAL, LOG_ERR,
876  QString("Unable to create RingBuffer for %1").arg(filename));
877  global_program_info = nullptr;
879  }
880 
881  if (useDB)
882  {
884  {
885  LOG(VB_GENERAL, LOG_ERR, "Unable to open commflag DB connection");
886  delete tmprbuf;
887  global_program_info = nullptr;
888  return GENERIC_EXIT_DB_ERROR;
889  }
890  }
891 
892  auto flags = static_cast<PlayerFlags>(kAudioMuted | kVideoIsNull | kNoITV);
893 
894  int flagfast = gCoreContext->GetNumSetting("CommFlagFast", 0);
895  if (flagfast)
896  {
897  // Note: These additional flags replicate the intent of the original
898  // commit that enabled lowres support - but I'm not sure why it requires
899  // single threaded decoding - which surely slows everything down? Though
900  // there is probably no profile to enable multi-threaded decoding anyway.
901  LOG(VB_GENERAL, LOG_INFO, "Enabling experimental flagging speedup (low resolution)");
902  flags = static_cast<PlayerFlags>(flags | kDecodeLowRes | kDecodeSingleThreaded | kDecodeNoLoopFilter);
903  }
904 
905  // blank detector needs to be only sample center for this optimization.
906  if (flagfast && ((COMM_DETECT_BLANKS == commDetectMethod) ||
907  (COMM_DETECT_2_BLANK == commDetectMethod)))
908  {
909  flags = static_cast<PlayerFlags>(flags | kDecodeFewBlocks);
910  }
911 
912  auto *cfp = new MythCommFlagPlayer(flags);
913  auto *ctx = new PlayerContext(kFlaggerInUseID);
914  ctx->SetPlayingInfo(program_info);
915  ctx->SetRingBuffer(tmprbuf);
916  ctx->SetPlayer(cfp);
917  cfp->SetPlayerInfo(nullptr, nullptr, ctx);
918 
919  if (useDB)
920  {
921  if (program_info->GetRecordingEndTime() > MythDate::current())
922  {
924 
925  recorder = RemoteGetExistingRecorder(program_info);
926  if (recorder && (recorder->GetRecorderNumber() != -1))
927  {
929  watchingRecording = true;
930  ctx->SetRecorder(recorder);
931 
932  LOG(VB_COMMFLAG, LOG_INFO,
933  QString("mythcommflag will flag recording "
934  "currently in progress on cardid %1")
935  .arg(recorderNum));
936  }
937  else
938  {
939  recorderNum = -1;
940  watchingRecording = false;
941 
942  LOG(VB_GENERAL, LOG_ERR,
943  "Unable to find active recorder for this "
944  "recording, realtime flagging will not be enabled.");
945  }
946  cfp->SetWatchingRecording(watchingRecording);
947  }
948  }
949 
950  // TODO: Add back insertion of job if not in jobqueue
951 
952  breaksFound = DoFlagCommercials(
953  program_info, progress, fullSpeed, jobid,
954  cfp, commDetectMethod, outputfilename, useDB);
955 
956  if (progress)
957  cerr << breaksFound << "\n";
958 
959  LOG(VB_GENERAL, LOG_NOTICE, QString("Finished, %1 break(s) found.")
960  .arg(breaksFound));
961 
962  delete ctx;
963  global_program_info = nullptr;
964 
965  return breaksFound;
966 }
967 
968 static int FlagCommercials( uint chanid, const QDateTime &starttime,
969  int jobid, const QString &outputfilename,
970  bool fullSpeed )
971 {
972  QString startstring = MythDate::toString(starttime, MythDate::kFilename);
973  ProgramInfo pginfo(chanid, starttime);
974 
975  if (!pginfo.GetChanID())
976  {
977  LOG(VB_GENERAL, LOG_ERR,
978  QString("No program data exists for channel %1 at %2")
979  .arg(chanid).arg(startstring));
981  }
982 
983  if (!force && JobQueue::IsJobRunning(JOB_COMMFLAG, pginfo))
984  {
985  if (progress)
986  {
987  cerr << "IN USE\n";
988  cerr << " "
989  "(the program is already being flagged elsewhere)\n";
990  }
991  LOG(VB_GENERAL, LOG_ERR, "Program is already being flagged elsewhere");
992  return GENERIC_EXIT_IN_USE;
993  }
994 
995 
996  if (progress)
997  {
998  cerr << "MythTV Commercial Flagger, flagging commercials for:" << endl;
999  if (pginfo.GetSubtitle().isEmpty())
1000  cerr << " " << pginfo.GetTitle().toLocal8Bit().constData() << endl;
1001  else
1002  cerr << " " << pginfo.GetTitle().toLocal8Bit().constData() << " - "
1003  << pginfo.GetSubtitle().toLocal8Bit().constData() << endl;
1004  }
1005 
1006  return FlagCommercials(&pginfo, jobid, outputfilename, true, fullSpeed);
1007 }
1008 
1009 static int FlagCommercials(const QString& filename, int jobid,
1010  const QString &outputfilename, bool useDB,
1011  bool fullSpeed)
1012 {
1013 
1014  if (progress)
1015  {
1016  cerr << "MythTV Commercial Flagger, flagging commercials for:" << endl
1017  << " " << filename.toLatin1().constData() << endl;
1018  }
1019 
1020  ProgramInfo pginfo(filename);
1021  return FlagCommercials(&pginfo, jobid, outputfilename, useDB, fullSpeed);
1022 }
1023 
1024 static int RebuildSeekTable(ProgramInfo *pginfo, int jobid, bool writefile = false)
1025 {
1026  QString filename = get_filename(pginfo);
1027 
1028  if (!DoesFileExist(pginfo))
1029  {
1030  // file not found on local filesystem
1031  // assume file is in Video storage group on local backend
1032  // and try again
1033 
1034  filename = QString("myth://Videos@%1/%2")
1035  .arg(gCoreContext->GetHostName()).arg(filename);
1036  pginfo->SetPathname(filename);
1037  if (!DoesFileExist(pginfo))
1038  {
1039  LOG(VB_GENERAL, LOG_ERR,
1040  QString("Unable to find file in defined storage "
1041  "paths for JobQueue ID# %1.").arg(jobid));
1043  }
1044  }
1045 
1046  // Update the file size since mythcommflag --rebuild is often used in user
1047  // scripts after transcoding or other size-changing operations
1048  UpdateFileSize(pginfo);
1049 
1051  if (!tmprbuf)
1052  {
1053  LOG(VB_GENERAL, LOG_ERR,
1054  QString("Unable to create RingBuffer for %1").arg(filename));
1056  }
1057 
1059  kDecodeNoDecode | kNoITV));
1060  auto *ctx = new PlayerContext(kFlaggerInUseID);
1061  ctx->SetPlayingInfo(pginfo);
1062  ctx->SetRingBuffer(tmprbuf);
1063  ctx->SetPlayer(cfp);
1064  cfp->SetPlayerInfo(nullptr, nullptr, ctx);
1065 
1066  if (progress)
1067  {
1068  QString time = QDateTime::currentDateTime().toString(Qt::TextDate);
1069  cerr << "Rebuild started at " << qPrintable(time) << endl;
1070  }
1071 
1072  if (writefile)
1074  cfp->RebuildSeekTable(progress);
1075  if (writefile)
1077 
1078  if (progress)
1079  {
1080  QString time = QDateTime::currentDateTime().toString(Qt::TextDate);
1081  cerr << "Rebuild completed at " << qPrintable(time) << endl;
1082  }
1083 
1084  delete ctx;
1085 
1086  return GENERIC_EXIT_OK;
1087 }
1088 
1089 static int RebuildSeekTable(const QString& filename, int jobid, bool writefile = false)
1090 {
1091  if (progress)
1092  {
1093  cerr << "MythTV Commercial Flagger, building seek table for:" << endl
1094  << " " << filename.toLatin1().constData() << endl;
1095  }
1096  ProgramInfo pginfo(filename);
1097  return RebuildSeekTable(&pginfo, jobid, writefile);
1098 }
1099 
1100 static int RebuildSeekTable(uint chanid, const QDateTime& starttime, int jobid, bool writefile = false)
1101 {
1102  ProgramInfo pginfo(chanid, starttime);
1103  if (progress)
1104  {
1105  cerr << "MythTV Commercial Flagger, building seek table for:" << endl;
1106  if (pginfo.GetSubtitle().isEmpty())
1107  cerr << " " << pginfo.GetTitle().toLocal8Bit().constData() << endl;
1108  else
1109  cerr << " " << pginfo.GetTitle().toLocal8Bit().constData() << " - "
1110  << pginfo.GetSubtitle().toLocal8Bit().constData() << endl;
1111  }
1112  return RebuildSeekTable(&pginfo, jobid, writefile);
1113 }
1114 
1115 int main(int argc, char *argv[])
1116 {
1117  int result = GENERIC_EXIT_OK;
1118 
1119 // QString allStart = "19700101000000";
1120 // QString allEnd = MythDate::current().toString("yyyyMMddhhmmss");
1121  int jobType = JOB_NONE;
1122 
1123  if (!cmdline.Parse(argc, argv))
1124  {
1125  cmdline.PrintHelp();
1127  }
1128 
1129  if (cmdline.toBool("showhelp"))
1130  {
1131  cmdline.PrintHelp();
1132  return GENERIC_EXIT_OK;
1133  }
1134 
1135  if (cmdline.toBool("showversion"))
1136  {
1138  return GENERIC_EXIT_OK;
1139  }
1140 
1141  QCoreApplication a(argc, argv);
1142  QCoreApplication::setApplicationName(MYTH_APPNAME_MYTHCOMMFLAG);
1143  int retval = cmdline.ConfigureLogging("general",
1144  !cmdline.toBool("noprogress"));
1145  if (retval != GENERIC_EXIT_OK)
1146  return retval;
1147 
1148  CleanupGuard callCleanup(cleanup);
1149 
1150 #ifndef _WIN32
1151  QList<int> signallist;
1152  signallist << SIGINT << SIGTERM << SIGSEGV << SIGABRT << SIGBUS << SIGFPE
1153  << SIGILL;
1154 #if ! CONFIG_DARWIN
1155  signallist << SIGRTMIN;
1156 #endif
1157  SignalHandler::Init(signallist);
1158  SignalHandler::SetHandler(SIGHUP, logSigHup);
1159 #endif
1160 
1162  if (!gContext->Init( false, /*use gui*/
1163  false, /*prompt for backend*/
1164  false, /*bypass auto discovery*/
1165  cmdline.toBool("skipdb"))) /*ignoreDB*/
1166  {
1167  LOG(VB_GENERAL, LOG_EMERG, "Failed to init MythContext, exiting.");
1169  }
1171 
1172  MythTranslation::load("mythfrontend");
1173 
1174  if (cmdline.toBool("outputmethod"))
1175  {
1176  QString om = cmdline.toString("outputmethod");
1177  if (outputTypes->contains(om))
1178  outputMethod = outputTypes->value(om);
1179  }
1180 
1181  if (cmdline.toBool("chanid") && cmdline.toBool("starttime"))
1182  {
1183  // operate on a recording in the database
1184  uint chanid = cmdline.toUInt("chanid");
1185  QDateTime starttime = cmdline.toDateTime("starttime");
1186 
1187  if (cmdline.toBool("clearskiplist"))
1188  return ClearSkipList(chanid, starttime);
1189  if (cmdline.toBool("gencutlist"))
1190  return CopySkipListToCutList(chanid, starttime);
1191  if (cmdline.toBool("clearcutlist"))
1192  return SetCutList(chanid, starttime, "");
1193  if (cmdline.toBool("setcutlist"))
1194  return SetCutList(chanid, starttime, cmdline.toString("setcutlist"));
1195  if (cmdline.toBool("getcutlist"))
1196  return GetMarkupList("cutlist", chanid, starttime);
1197  if (cmdline.toBool("getskiplist"))
1198  return GetMarkupList("commflag", chanid, starttime);
1199 
1200  // TODO: check for matching jobid
1201  // create temporary id to operate off of if not
1202 
1203  if (cmdline.toBool("queue"))
1204  QueueCommFlagJob(chanid, starttime, cmdline.toBool("rebuild"));
1205  else if (cmdline.toBool("rebuild"))
1206  result = RebuildSeekTable(chanid, starttime, -1);
1207  else
1208  result = FlagCommercials(chanid, starttime, -1,
1209  cmdline.toString("outputfile"), true);
1210  }
1211  else if (cmdline.toBool("jobid"))
1212  {
1213  jobID = cmdline.toInt("jobid");
1214  uint chanid = 0;
1215  QDateTime starttime;
1216 
1217  if (!JobQueue::GetJobInfoFromID(jobID, jobType, chanid, starttime))
1218  {
1219  cerr << "mythcommflag: ERROR: Unable to find DB info for "
1220  << "JobQueue ID# " << jobID << endl;
1222  }
1223  force = true;
1224  int jobQueueCPU = gCoreContext->GetNumSetting("JobQueueCPU", 0);
1225 
1226  if (jobQueueCPU < 2)
1227  {
1228  myth_nice(17);
1229  myth_ioprio((0 == jobQueueCPU) ? 8 : 7);
1230  }
1231 
1232  progress = false;
1233 
1234  int ret = 0;
1235 
1237  RebuildSeekTable(chanid, starttime, jobID);
1238  else
1239  ret = FlagCommercials(chanid, starttime, jobID, "", jobQueueCPU != 0);
1240 
1241  if (ret > GENERIC_EXIT_NOT_OK)
1242  {
1243  JobQueue::ChangeJobStatus(jobID, JOB_ERRORED,
1244  QCoreApplication::translate("(mythcommflag)",
1245  "Failed with exit status %1",
1246  "Job status").arg(ret));
1247  }
1248  else
1249  {
1250  JobQueue::ChangeJobStatus(jobID, JOB_FINISHED,
1251  QCoreApplication::translate("(mythcommflag)",
1252  "%n commercial break(s)",
1253  "Job status",
1254  ret));
1255  }
1256  }
1257  else if (cmdline.toBool("video"))
1258  {
1259  // build skiplist for video file
1260  return RebuildSeekTable(cmdline.toString("video"), -1);
1261  }
1262  else if (cmdline.toBool("file"))
1263  {
1264  if (cmdline.toBool("skipdb"))
1265  {
1266  if (cmdline.toBool("rebuild"))
1267  {
1268  cerr << "The --rebuild parameter builds the seektable for "
1269  "internal MythTV use only. It cannot be used in "
1270  "combination with --skipdb." << endl;
1272  }
1273 
1274  if (!cmdline.toBool("outputfile"))
1275  cmdline.SetValue("outputfile", "-");
1276 
1277  // perform commercial flagging on file outside the database
1278  FlagCommercials(cmdline.toString("file"), -1,
1279  cmdline.toString("outputfile"),
1280  !cmdline.toBool("skipdb"),
1281  true);
1282  }
1283  else
1284  {
1285  ProgramInfo pginfo(cmdline.toString("file"));
1286  // pass chanid and starttime
1287  // inefficient, but it lets the other function
1288  // handle sanity checking
1289  if (cmdline.toBool("rebuild"))
1290  {
1291  result = RebuildSeekTable(pginfo.GetChanID(),
1292  pginfo.GetRecordingStartTime(),
1293  -1, cmdline.toBool("writefile"));
1294  }
1295  else
1296  {
1297  result = FlagCommercials(pginfo.GetChanID(),
1298  pginfo.GetRecordingStartTime(),
1299  -1, cmdline.toString("outputfile"),
1300  true);
1301  }
1302  }
1303  }
1304  else if (cmdline.toBool("queue"))
1305  {
1306  // run flagging for all recordings with no skiplist
1308  query.prepare("SELECT r.chanid, r.starttime, c.commmethod "
1309  "FROM recorded AS r "
1310  "LEFT JOIN channel AS c ON r.chanid=c.chanid "
1311 // "WHERE startime >= :STARTTIME AND endtime <= :ENDTIME "
1312  "ORDER BY starttime;");
1313  //query.bindValue(":STARTTIME", allStart);
1314  //query.bindValue(":ENDTIME", allEnd);
1315 
1316  if (query.exec() && query.isActive() && query.size() > 0)
1317  {
1318  QDateTime starttime;
1319 
1320  while (query.next())
1321  {
1322  starttime = MythDate::fromString(query.value(1).toString());
1323  uint chanid = query.value(0).toUInt();
1324 
1325  if (!cmdline.toBool("force") && !cmdline.toBool("rebuild"))
1326  {
1327  // recording is already flagged
1328  if (IsMarked(chanid, starttime))
1329  continue;
1330 
1331  // channel is marked as commercial free
1332  if (query.value(2).toInt() == COMM_DETECT_COMMFREE)
1333  continue;
1334 
1335  // recording rule did not enable commflagging
1336 #if 0
1337  RecordingInfo recinfo(chanid, starttime);
1338  if (!(recinfo.GetAutoRunJobs() & JOB_COMMFLAG))
1339  continue;
1340 #endif
1341  }
1342 
1343  QueueCommFlagJob(chanid, starttime, cmdline.toBool("rebuild"));
1344  }
1345  }
1346 
1347  }
1348  else
1349  {
1350  LOG(VB_GENERAL, LOG_ERR,
1351  "No valid combination of command inputs received.");
1352  cmdline.PrintHelp();
1354  }
1355 
1356  return result;
1357 }
1358 
1359 
1360 /* vim: set expandtab tabstop=4 shiftwidth=4: */
force
bool force
Definition: mythtv/programs/mythcommflag/main.cpp:75
CommDetectorFactory.h
JobQueue::GetJobCmd
static enum JobCmds GetJobCmd(int jobID)
Definition: jobqueue.cpp:1463
MSqlQuery::isActive
bool isActive(void) const
Definition: mythdbcon.h:204
COMM_DETECT_2_ALL
@ COMM_DETECT_2_ALL
Definition: programtypes.h:110
MSqlQuery::next
bool next(void)
Wrap QSqlQuery::next() so we can display the query results.
Definition: mythdbcon.cpp:783
commandlineparser.h
MSqlQuery
QSqlQuery wrapper that fetches a DB connection from the connection pool.
Definition: mythdbcon.h:126
ProgramInfo::SaveFilesize
virtual void SaveFilesize(uint64_t fsize)
Sets recording file size in database, and sets "filesize" field.
Definition: programinfo.cpp:6130
COMM_DETECT_SCENE
@ COMM_DETECT_SCENE
Definition: programtypes.h:98
e
QDomElement e
Definition: mythplugins/mytharchive/mytharchivehelper/main.cpp:1417
ProgramInfo::MakeUniqueKey
QString MakeUniqueKey(void) const
Creates a unique string that can be used to identify an existing recording.
Definition: programinfo.h:334
MythCoreContext::SendMessage
void SendMessage(const QString &message)
Definition: mythcorecontext.cpp:1526
MythDate::toString
QString toString(const QDateTime &raw_dt, uint format)
Returns formatted string representing the time.
Definition: mythdate.cpp:80
MSqlQuery::size
int size(void) const
Definition: mythdbcon.h:203
CustomEventRelayer
Definition: CustomEventRelayer.h:15
CommDetectorFactory::makeCommDetector
static CommDetectorBase * makeCommDetector(SkipType commDetectMethod, bool showProgress, bool fullSpeed, MythPlayer *player, int chanid, const QDateTime &startedAt, const QDateTime &stopsAt, const QDateTime &recordingStartedAt, const QDateTime &recordingStopsAt, bool useDB)
Definition: CommDetectorFactory.cpp:10
COMM_FLAG_NOT_FLAGGED
@ COMM_FLAG_NOT_FLAGGED
Definition: programtypes.h:85
MythEvent::MythEventMessage
static Type MythEventMessage
Definition: mythevent.h:73
DoesFileExist
static bool DoesFileExist(ProgramInfo *program_info)
Definition: mythtv/programs/mythcommflag/main.cpp:651
GENERIC_EXIT_OK
#define GENERIC_EXIT_OK
Exited with no error.
Definition: exitcodes.h:10
COMM_DETECT_ALL
@ COMM_DETECT_ALL
Definition: programtypes.h:101
ProgramInfo::GetFilesize
virtual uint64_t GetFilesize(void) const
Definition: programinfo.cpp:6161
MARK_COMM_END
@ MARK_COMM_END
Definition: programtypes.h:60
RemoteGetExistingRecorder
RemoteEncoder * RemoteGetExistingRecorder(const ProgramInfo *pginfo)
Definition: tvremoteutil.cpp:313
CommDetectorBase
Abstract base class for all CommDetectors. Please use the CommDetectFactory to make actual instances.
Definition: CommDetectorBase.h:28
JOB_REBUILD
@ JOB_REBUILD
Definition: jobqueue.h:59
ClearSkipList
static int ClearSkipList(uint chanid, const QDateTime &starttime)
Definition: mythtv/programs/mythcommflag/main.cpp:216
MythPlayer::GetTotalFrameCount
uint64_t GetTotalFrameCount(void) const
Definition: mythplayer.h:236
RemoteEncoder::GetRecorderNumber
int GetRecorderNumber(void) const
Definition: remoteencoder.cpp:63
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
kFlaggerInUseID
const char * kFlaggerInUseID
Definition: programtypes.cpp:20
mythdb.h
JobQueue::QueueJob
static bool QueueJob(int jobType, uint chanid, const QDateTime &recstartts, const QString &args="", const QString &comment="", QString host="", int flags=0, int status=JOB_QUEUED, QDateTime schedruntime=QDateTime())
Definition: jobqueue.cpp:521
commDetector
CommDetectorBase * commDetector
Definition: mythtv/programs/mythcommflag/main.cpp:80
myth_ioprio
bool myth_ioprio(int)
Allows setting the I/O priority of the current process/thread.
Definition: mythmiscutil.cpp:803
DoFlagCommercials
static int DoFlagCommercials(ProgramInfo *program_info, bool showPercentage, bool fullSpeed, int jobid, MythCommFlagPlayer *cfp, SkipType commDetectMethod, const QString &outputfilename, bool useDB)
Definition: mythtv/programs/mythcommflag/main.cpp:545
MythCoreContext::UnregisterFileForWrite
void UnregisterFileForWrite(const QString &file)
Definition: mythcorecontext.cpp:2122
mythcommflagplayer.h
MythCoreContext::ConnectToMasterServer
bool ConnectToMasterServer(bool blockingClient=true, bool openEventSocket=true)
Definition: mythcorecontext.cpp:374
OutputMethod
OutputMethod
Definition: mythtv/programs/mythcommflag/main.cpp:113
CommDetectorBase::PrintFullMap
virtual void PrintFullMap(ostream &out, const frm_dir_map_t *comm_breaks, bool verbose) const =0
RecordingInfo
Holds information on a TV Program one might wish to record.
Definition: recordinginfo.h:35
lastCmd
int lastCmd
Definition: mythtv/programs/mythcommflag/main.cpp:86
MARK_CUT_END
@ MARK_CUT_END
Definition: programtypes.h:55
MythMediaBuffer::Create
static MythMediaBuffer * Create(const QString &Filename, bool Write, bool UseReadAhead=true, int Timeout=kDefaultOpenTimeout, bool StreamOnly=false)
Creates a RingBuffer instance.
Definition: mythmediabuffer.cpp:104
MythContext
Startup context for MythTV.
Definition: mythcontext.h:43
kOutputMethodFull
@ kOutputMethodFull
Definition: mythtv/programs/mythcommflag/main.cpp:115
progress
bool progress
Definition: mythtv/programs/mythcommflag/main.cpp:74
MythEvent
This class is used as a container for messages.
Definition: mythevent.h:17
incomingCustomEvent
static void incomingCustomEvent(QEvent *e)
Definition: mythtv/programs/mythcommflag/main.cpp:485
JOB_COMMFLAG
@ JOB_COMMFLAG
Definition: jobqueue.h:75
MythCoreContext::RegisterFileForWrite
void RegisterFileForWrite(const QString &file, uint64_t size=0LL)
Definition: mythcorecontext.cpp:2104
JOB_PAUSE
@ JOB_PAUSE
Definition: jobqueue.h:48
COMM_DETECT_BLANK_SCENE
@ COMM_DETECT_BLANK_SCENE
Definition: programtypes.h:100
MSqlQuery::value
QVariant value(int i) const
Definition: mythdbcon.h:198
init_output_types
static QMap< QString, OutputMethod > * init_output_types()
Definition: mythtv/programs/mythcommflag/main.cpp:122
arg
arg(title).arg(filename).arg(doDelete))
JOB_RESUME
@ JOB_RESUME
Definition: jobqueue.h:49
frm_dir_map_t
QMap< uint64_t, MarkTypes > frm_dir_map_t
Frame # -> Mark map.
Definition: programtypes.h:82
JOB_NONE
@ JOB_NONE
Definition: jobqueue.h:71
JobQueue::GetJobInfoFromID
static bool GetJobInfoFromID(int jobID, int &jobType, uint &chanid, QDateTime &recstartts)
Definition: jobqueue.cpp:672
RemoteFile
Definition: remotefile.h:18
MSqlQuery::exec
bool exec(void)
Wrap QSqlQuery::exec() so we can display SQL.
Definition: mythdbcon.cpp:603
ProgramInfo::ExtractKey
static bool ExtractKey(const QString &uniquekey, uint &chanid, QDateTime &recstartts)
Extracts chanid and recstartts from a unique key generated by MakeUniqueKey().
Definition: programinfo.cpp:1169
COMM_DETECT_OFF
@ COMM_DETECT_OFF
Definition: programtypes.h:95
kOutputMethodEssentials
@ kOutputMethodEssentials
Definition: mythtv/programs/mythcommflag/main.cpp:114
ProgramInfo::SaveCommFlagged
void SaveCommFlagged(CommFlagStatus flag)
Set "commflagged" field in "recorded" table to "flag".
Definition: programinfo.cpp:3164
MythMediaBuffer
Definition: mythmediabuffer.h:50
ProgramInfo::GetScheduledEndTime
QDateTime GetScheduledEndTime(void) const
The scheduled end time of the program.
Definition: programinfo.h:392
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:23
CommDetectorBase::go
virtual bool go()=0
JOB_STOP
@ JOB_STOP
Definition: jobqueue.h:50
PlayerFlags
PlayerFlags
Definition: mythplayer.h:88
build_compdb.file
file
Definition: build_compdb.py:55
kDecodeLowRes
@ kDecodeLowRes
Definition: mythplayer.h:90
main
int main(int argc, char *argv[])
Definition: mythtv/programs/mythcommflag/main.cpp:1115
GENERIC_EXIT_INVALID_CMDLINE
#define GENERIC_EXIT_INVALID_CMDLINE
Command line parse error.
Definition: exitcodes.h:15
ProgramInfo::GetRecordingEndTime
QDateTime GetRecordingEndTime(void) const
Approximate time the recording should have ended, did end, or is intended to end.
Definition: programinfo.h:407
UpdateFileSize
static void UpdateFileSize(ProgramInfo *program_info)
Definition: mythtv/programs/mythcommflag/main.cpp:673
remoteutil.h
COMM_FLAG_PROCESSING
@ COMM_FLAG_PROCESSING
Definition: programtypes.h:87
MythDate::current
QDateTime current(bool stripped)
Returns current Date and Time in UTC.
Definition: mythdate.cpp:10
MythEvent::Message
const QString & Message() const
Definition: mythevent.h:65
JobQueue::IsJobRunning
static bool IsJobRunning(int jobType, uint chanid, const QDateTime &recstartts)
Definition: jobqueue.cpp:1093
ProgramInfo::GetRecordingStartTime
QDateTime GetRecordingStartTime(void) const
Approximate time the recording started.
Definition: programinfo.h:399
ProgramInfo::GetPathname
QString GetPathname(void) const
Definition: programinfo.h:338
CopySkipListToCutList
static int CopySkipListToCutList(uint chanid, const QDateTime &starttime)
Definition: mythtv/programs/mythcommflag/main.cpp:187
RemoteEncoder
Definition: remoteencoder.h:26
ProgramInfo::SaveCommBreakList
void SaveCommBreakList(frm_dir_map_t &frames) const
Definition: programinfo.cpp:3370
commDetectorStatusUpdate
static void commDetectorStatusUpdate(const QString &status)
Definition: mythtv/programs/mythcommflag/main.cpp:450
tmp
static guint32 * tmp
Definition: goom_core.cpp:30
mythversion.h
CommDetectorBase::recordingFinished
virtual void recordingFinished(long long totalFileSize)
Definition: CommDetectorBase.h:40
COMM_FLAG_DONE
@ COMM_FLAG_DONE
Definition: programtypes.h:86
COMM_DETECT_2_BLANK
@ COMM_DETECT_2_BLANK
Definition: programtypes.h:106
sleep
unsigned sleep(unsigned int x)
Definition: compat.h:159
MythCommandLineParser::Parse
virtual bool Parse(int argc, const char *const *argv)
Loop through argv and populate arguments with values.
Definition: mythcommandlineparser.cpp:1441
global_program_info
ProgramInfo * global_program_info
Definition: mythtv/programs/mythcommflag/main.cpp:82
get_filename
static QString get_filename(ProgramInfo *program_info)
Definition: mythtv/programs/mythcommflag/main.cpp:130
mythdate.h
ProgramInfo::SetPathname
void SetPathname(const QString &pn)
Definition: programinfo.cpp:2332
COMM_DETECT_BLANKS
@ COMM_DETECT_BLANKS
Definition: programtypes.h:97
outputTypes
QMap< QString, OutputMethod > * outputTypes
Definition: mythtv/programs/mythcommflag/main.cpp:120
programinfo.h
COMM_DETECT_COMMFREE
@ COMM_DETECT_COMMFREE
Definition: programtypes.h:93
ProgramInfo::GetScheduledStartTime
QDateTime GetScheduledStartTime(void) const
The scheduled start time of program.
Definition: programinfo.h:385
outputMethod
OutputMethod outputMethod
Definition: mythtv/programs/mythcommflag/main.cpp:117
mythlogging.h
skipTypes
QMap< QString, SkipType > * skipTypes
Definition: mythtv/programs/mythcommflag/main.cpp:89
remotefile.h
MythDate::kFilename
@ kFilename
Default UTC, "yyyyMMddhhmmss".
Definition: mythdate.h:15
JobQueue::ChangeJobComment
static bool ChangeJobComment(int jobID, const QString &comment="")
Definition: jobqueue.cpp:1017
signalhandling.h
RebuildSeekTable
static int RebuildSeekTable(ProgramInfo *pginfo, int jobid, bool writefile=false)
Definition: mythtv/programs/mythcommflag/main.cpp:1024
commDetectorBreathe
static void commDetectorBreathe()
Definition: mythtv/programs/mythcommflag/main.cpp:411
MSqlQuery::InitCon
static MSqlQueryInfo InitCon(ConnectionReuse _reuse=kNormalConnection)
Only use this in combination with MSqlQuery constructor.
Definition: mythdbcon.cpp:535
ProgramInfo::GetTitle
QString GetTitle(void) const
Definition: programinfo.h:356
CleanupGuard
Definition: cleanupguard.h:7
MythDB::DBError
static void DBError(const QString &where, const MSqlQuery &query)
Definition: mythdb.cpp:179
MSqlQuery::testDBConnection
static bool testDBConnection()
Checks DB connection + login (login info via Mythcontext)
Definition: mythdbcon.cpp:852
RecordingInfo::GetAutoRunJobs
int GetAutoRunJobs(void) const
Returns a bitmap of which jobs are attached to this RecordingInfo.
Definition: recordinginfo.cpp:500
GENERIC_EXIT_NO_RECORDING_DATA
#define GENERIC_EXIT_NO_RECORDING_DATA
No program/recording data.
Definition: exitcodes.h:29
ProgramInfo::QueryCutList
bool QueryCutList(frm_dir_map_t &delMap, bool loadAutosave=false) const
Definition: programinfo.cpp:3291
SIGHUP
#define SIGHUP
Definition: compat.h:213
recorder
RemoteEncoder * recorder
Definition: mythtv/programs/mythcommflag/main.cpp:81
SlotRelayer.h
MythCommandLineParser::PrintVersion
static void PrintVersion(void)
Print application version information.
Definition: mythcommandlineparser.cpp:1268
filename
QString filename
Definition: mythplugins/mytharchive/mytharchivehelper/main.cpp:634
mythtranslation.h
MythCommFlagPlayer
Definition: mythcommflagplayer.h:7
MythCommandLineParser::toUInt
uint toUInt(const QString &key) const
Returns stored QVariant as an unsigned integer, falling to default if not provided.
Definition: mythcommandlineparser.cpp:2000
MythCommandLineParser::PrintHelp
void PrintHelp(void) const
Print command line option help.
Definition: mythcommandlineparser.cpp:1284
jobqueue.h
quiet
int quiet
Definition: mythtv/programs/mythcommflag/main.cpp:73
streamOutCommercialBreakList
static void streamOutCommercialBreakList(ostream &output, const frm_dir_map_t &commercialBreakList)
Definition: mythtv/programs/mythcommflag/main.cpp:337
kNoITV
@ kNoITV
Definition: mythplayer.h:100
CommDetectorBase::GetCommercialBreakList
virtual void GetCommercialBreakList(frm_dir_map_t &comms)=0
uint
unsigned int uint
Definition: compat.h:140
kDecodeNoDecode
@ kDecodeNoDecode
Definition: mythplayer.h:94
gCoreContext
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
Definition: mythcorecontext.cpp:57
GENERIC_EXIT_PERMISSIONS_ERROR
#define GENERIC_EXIT_PERMISSIONS_ERROR
File permissions error.
Definition: exitcodes.h:19
FlagCommercials
static int FlagCommercials(ProgramInfo *program_info, int jobid, const QString &outputfilename, bool useDB, bool fullSpeed)
Definition: mythtv/programs/mythcommflag/main.cpp:735
MythCommandLineParser::ApplySettingsOverride
void ApplySettingsOverride(void)
Apply all overrides to the global context.
Definition: mythcommandlineparser.cpp:2652
MythCoreContext::GetNumSetting
int GetNumSetting(const QString &key, int defaultval=0)
Definition: mythcorecontext.cpp:930
commDetectorGotNewCommercialBreakList
static void commDetectorGotNewCommercialBreakList(void)
Definition: mythtv/programs/mythcommflag/main.cpp:459
cleanup
static QString cleanup(const QString &str)
Definition: remoteencoder.cpp:674
SlotRelayer
Definition: SlotRelayer.h:17
mythmediabuffer.h
tvremoteutil.h
kDecodeSingleThreaded
@ kDecodeSingleThreaded
Definition: mythplayer.h:91
MythDate::fromString
QDateTime fromString(const QString &dtstr)
Converts kFilename && kISODate formats to QDateTime.
Definition: mythdate.cpp:30
COMM_DETECT_UNINIT
@ COMM_DETECT_UNINIT
Definition: programtypes.h:94
MARK_CUT_START
@ MARK_CUT_START
Definition: programtypes.h:56
MYTH_BINARY_VERSION
#define MYTH_BINARY_VERSION
Update this whenever the plug-in ABI changes.
Definition: mythversion.h:15
ProgramInfo::GetChanID
uint GetChanID(void) const
This is the unique key used in the database to locate tuning information.
Definition: programinfo.h:367
GENERIC_EXIT_DB_ERROR
#define GENERIC_EXIT_DB_ERROR
Database error.
Definition: exitcodes.h:17
MythCommFlagCommandLineParser
Definition: mythcommflag/commandlineparser.h:7
kVideoIsNull
@ kVideoIsNull
Definition: mythplayer.h:98
cmdline
MythCommFlagCommandLineParser cmdline
Definition: mythtv/programs/mythcommflag/main.cpp:77
ProgramInfo
Holds information on recordings and videos.
Definition: programinfo.h:68
mythmiscutil.h
CommDetectorBase::resume
void resume()
Definition: CommDetectorBase.cpp:13
QueueCommFlagJob
static int QueueCommFlagJob(uint chanid, const QDateTime &starttime, bool rebuild)
Definition: mythtv/programs/mythcommflag/main.cpp:138
recorderNum
int recorderNum
Definition: mythtv/programs/mythcommflag/main.cpp:83
MythCommandLineParser::toString
QString toString(const QString &key) const
Returns stored QVariant as a QString, falling to default if not provided.
Definition: mythcommandlineparser.cpp:2100
GENERIC_EXIT_IN_USE
#define GENERIC_EXIT_IN_USE
Recording in use, can't flag.
Definition: exitcodes.h:34
ProgramInfo::QueryLastFrameInPosMap
uint64_t QueryLastFrameInPosMap(void) const
Returns last frame in position map or 0.
Definition: programinfo.cpp:1796
GENERIC_EXIT_NOT_OK
#define GENERIC_EXIT_NOT_OK
Exited with error.
Definition: exitcodes.h:11
MythCommandLineParser::SetValue
bool SetValue(const QString &key, const QVariant &value)
Set a new stored value for an existing argument definition, or spawn a new definition store value in.
Definition: mythcommandlineparser.cpp:2560
MythCommandLineParser::toBool
bool toBool(const QString &key) const
Returns stored QVariant as a boolean.
Definition: mythcommandlineparser.cpp:1955
MARK_UPDATED_CUT
@ MARK_UPDATED_CUT
Definition: programtypes.h:53
cleanupguard.h
CommDetectorBase::stop
void stop()
Definition: CommDetectorBase.cpp:3
init_skip_types
static QMap< QString, SkipType > * init_skip_types()
Definition: mythtv/programs/mythcommflag/main.cpp:91
ProgramInfo::GetPlaybackURL
QString GetPlaybackURL(bool checkMaster=false, bool forceCheckLocal=false)
Returns filename or URL to be used to play back this recording.
Definition: programinfo.cpp:2440
MSqlQuery::bindValue
void bindValue(const QString &placeholder, const QVariant &val)
Add a single binding.
Definition: mythdbcon.cpp:864
MythDate::ISODate
@ ISODate
Default UTC.
Definition: mythdate.h:14
JobQueue::GetJobFlags
static enum JobFlags GetJobFlags(int jobID)
Definition: jobqueue.cpp:1505
print_comm_flag_output
static void print_comm_flag_output(const ProgramInfo *program_info, const frm_dir_map_t &commBreakList, uint64_t frame_count, const CommDetectorBase *commDetect, const QString &output_filename)
Definition: mythtv/programs/mythcommflag/main.cpp:362
GetFileSize
static qint64 GetFileSize(ProgramInfo *program_info)
Definition: mythtv/programs/mythcommflag/main.cpp:629
mythcontext.h
kDecodeNoLoopFilter
@ kDecodeNoLoopFilter
Definition: mythplayer.h:93
SetCutList
static int SetCutList(uint chanid, const QDateTime &starttime, QString newCutList)
Definition: mythtv/programs/mythcommflag/main.cpp:237
ProgramInfo::SaveCutList
void SaveCutList(frm_dir_map_t &delMap, bool isAutoSave=false) const
Definition: programinfo.cpp:3323
GENERIC_EXIT_NO_MYTHCONTEXT
#define GENERIC_EXIT_NO_MYTHCONTEXT
No MythContext available.
Definition: exitcodes.h:13
SignalHandler::SetHandler
static void SetHandler(int signum, SigHandlerFunc handler)
Definition: signalhandling.cpp:150
MYTH_APPNAME_MYTHCOMMFLAG
#define MYTH_APPNAME_MYTHCOMMFLAG
Definition: mythcorecontext.h:23
kAudioMuted
@ kAudioMuted
Definition: mythplayer.h:99
PlayerContext
Definition: playercontext.h:49
IsMarked
static bool IsMarked(uint chanid, const QDateTime &starttime)
Definition: mythtv/programs/mythcommflag/main.cpp:681
remoteencoder.h
GetMarkupList
static int GetMarkupList(const QString &list, uint chanid, const QDateTime &starttime)
Definition: mythtv/programs/mythcommflag/main.cpp:278
SkipType
SkipType
This is used as a bitmask.
Definition: programtypes.h:92
ProgramInfo::QueryCommBreakList
void QueryCommBreakList(frm_dir_map_t &frames) const
Definition: programinfo.cpp:3377
MythCoreContext::GetHostName
QString GetHostName(void)
Definition: mythcorecontext.cpp:856
ProgramInfo::SaveMarkupFlag
void SaveMarkupFlag(MarkTypes type) const
Clears the specified flag, then if sets it.
Definition: programinfo.cpp:3582
MythPlayer::SaveTotalDuration
void SaveTotalDuration(void)
Definition: mythplayer.cpp:5552
watchingRecording
bool watchingRecording
Definition: mythtv/programs/mythcommflag/main.cpp:79
MythCommandLineParser::ConfigureLogging
int ConfigureLogging(const QString &mask="general", bool progress=false)
Read in logging options and initialize the logging interface.
Definition: mythcommandlineparser.cpp:2583
COMM_DETECT_2_SCENE
@ COMM_DETECT_2_SCENE
Definition: programtypes.h:107
myth_nice
bool myth_nice(int val)
Definition: mythmiscutil.cpp:701
CommDetectorBase::requestCommBreakMapUpdate
virtual void requestCommBreakMapUpdate(void)
Definition: CommDetectorBase.h:42
MythTranslation::load
static void load(const QString &module_name)
Load a QTranslator for the user's preferred language.
Definition: mythtranslation.cpp:37
exitcodes.h
MythCommandLineParser::toInt
int toInt(const QString &key) const
Returns stored QVariant as an integer, falling to default if not provided.
Definition: mythcommandlineparser.cpp:1975
jobID
int jobID
Definition: mythtv/programs/mythcommflag/main.cpp:85
JobQueue::ChangeJobStatus
static bool ChangeJobStatus(int jobID, int newStatus, const QString &comment="")
Definition: jobqueue.cpp:990
CommDetectorBase.h
COMM_DETECT_LOGO
@ COMM_DETECT_LOGO
Definition: programtypes.h:99
loggingserver.h
MARK_COMM_START
@ MARK_COMM_START
Definition: programtypes.h:59
query
MSqlQuery query(MSqlQuery::InitCon())
output
#define output
Definition: synaesthesia.cpp:221
MythCommandLineParser::toDateTime
QDateTime toDateTime(const QString &key) const
Returns stored QVariant as a QDateTime, falling to default if not provided.
Definition: mythcommandlineparser.cpp:2192
CommDetectorBase::pause
void pause()
Definition: CommDetectorBase.cpp:8
COMM_FLAG_COMMFREE
@ COMM_FLAG_COMMFREE
Definition: programtypes.h:88
gContext
MythContext * gContext
This global variable contains the MythContext instance for the application.
Definition: mythcontext.cpp:61
COMM_DETECT_2
@ COMM_DETECT_2
Definition: programtypes.h:104
MythContext::Init
bool Init(bool gui=true, bool promptForBackend=false, bool disableAutoDiscovery=false, bool ignoreDB=false)
Definition: mythcontext.cpp:1566
SignalHandler::Done
static void Done(void)
Definition: signalhandling.cpp:143
COMM_DETECT_2_LOGO
@ COMM_DETECT_2_LOGO
Definition: programtypes.h:105
kDecodeFewBlocks
@ kDecodeFewBlocks
Definition: mythplayer.h:92
CustomEventRelayer.h
MSqlQuery::prepare
bool prepare(const QString &query)
QSqlQuery::prepare() is not thread safe in Qt <= 3.3.2.
Definition: mythdbcon.cpp:808
ProgramInfo::GetSubtitle
QString GetSubtitle(void) const
Definition: programinfo.h:358
COMM_DETECT_BLANK
@ COMM_DETECT_BLANK
Definition: programtypes.h:96
SignalHandler::Init
static void Init(QList< int > &signallist, QObject *parent=nullptr)
Definition: signalhandling.cpp:136