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