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