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  QStringList tokens = message.split(" ", Qt::SkipEmptyParts);
341 
342  LOG(VB_COMMFLAG, LOG_INFO,
343  QString("mythcommflag: Received Event: '%1'") .arg(message));
344 
345  if ((watchingRecording) && (tokens.size() >= 3) &&
346  (tokens[0] == "DONE_RECORDING"))
347  {
348  int cardnum = tokens[1].toInt();
349  int filelen = tokens[2].toInt();
350 
351  message = QString("mythcommflag: Received a "
352  "DONE_RECORDING event for card %1. ")
353  .arg(cardnum);
354 
355  if (recorderNum != -1 && cardnum == recorderNum)
356  {
358  watchingRecording = false;
359  message += "Informed CommDetector that recording has finished.";
360  LOG(VB_COMMFLAG, LOG_INFO, message);
361  }
362  }
363 
364  if ((tokens.size() >= 2) && (tokens[0] == "COMMFLAG_REQUEST"))
365  {
366  uint chanid = 0;
367  QDateTime recstartts;
368  ProgramInfo::ExtractKey(tokens[1], chanid, recstartts);
369 
370  message = QString("mythcommflag: Received a "
371  "COMMFLAG_REQUEST event for chanid %1 @ %2. ")
372  .arg(chanid).arg(recstartts.toString(Qt::ISODate));
373 
374  if ((global_program_info->GetChanID() == chanid) &&
375  (global_program_info->GetRecordingStartTime() == recstartts))
376  {
378  message += "Requested CommDetector to generate new break list.";
379  LOG(VB_COMMFLAG, LOG_INFO, message);
380  }
381  }
382  }
383 }
384 
385 static int DoFlagCommercials(
386  ProgramInfo *program_info,
387  bool showPercentage, bool fullSpeed, int jobid,
388  MythCommFlagPlayer* cfp, SkipType commDetectMethod,
389  const QString &outputfilename, bool useDB)
390 {
392  commDetectMethod, showPercentage,
393  fullSpeed, cfp,
394  program_info->GetChanID(),
395  program_info->GetScheduledStartTime(),
396  program_info->GetScheduledEndTime(),
397  program_info->GetRecordingStartTime(),
398  program_info->GetRecordingEndTime(), useDB);
399 
400  if (jobid > 0)
401  LOG(VB_COMMFLAG, LOG_INFO,
402  QString("mythcommflag processing JobID %1").arg(jobid));
403 
404  if (useDB)
405  program_info->SaveCommFlagged(COMM_FLAG_PROCESSING);
406 
407  auto *cer = new CustomEventRelayer(incomingCustomEvent);
408  auto *a = new SlotRelayer(commDetectorBreathe);
409  auto *b = new SlotRelayer(commDetectorStatusUpdate);
411  QObject::connect(commDetector, &CommDetectorBase::breathe,
412  a, qOverload<>(&SlotRelayer::relay));
413  QObject::connect(commDetector, &CommDetectorBase::statusUpdate,
414  b, qOverload<const QString&>(&SlotRelayer::relay));
416  c, qOverload<>(&SlotRelayer::relay));
417 
418  if (useDB)
419  {
420  LOG(VB_COMMFLAG, LOG_INFO,
421  "mythcommflag sending COMMFLAG_START notification");
422  QString message = "COMMFLAG_START ";
423  message += program_info->MakeUniqueKey();
424  gCoreContext->SendMessage(message);
425  }
426 
427  bool result = commDetector->go();
428  int comms_found = 0;
429 
430  if (result)
431  {
432  cfp->SaveTotalDuration();
433 
434  frm_dir_map_t commBreakList;
435  commDetector->GetCommercialBreakList(commBreakList);
436  comms_found = commBreakList.size() / 2;
437 
438  if (useDB)
439  {
440  program_info->SaveMarkupFlag(MARK_UPDATED_CUT);
441  program_info->SaveCommBreakList(commBreakList);
442  program_info->SaveCommFlagged(COMM_FLAG_DONE);
443  }
444 
446  program_info, commBreakList, cfp->GetTotalFrameCount(),
448  outputfilename);
449  }
450  else
451  {
452  if (useDB)
453  program_info->SaveCommFlagged(COMM_FLAG_NOT_FLAGGED);
454  }
455 
457  commDetector = nullptr;
458  sleep(1);
459  tmp->deleteLater();
460 
461  cer->deleteLater();
462  c->deleteLater();
463  b->deleteLater();
464  a->deleteLater();
465 
466  return comms_found;
467 }
468 
469 static qint64 GetFileSize(ProgramInfo *program_info)
470 {
471  QString filename = get_filename(program_info);
472  qint64 size = -1;
473 
474  if (filename.startsWith("myth://"))
475  {
476  RemoteFile remotefile(filename, false, false, 0s);
477  size = remotefile.GetFileSize();
478  }
479  else
480  {
481  QFile file(filename);
482  if (file.exists())
483  {
484  size = file.size();
485  }
486  }
487 
488  return size;
489 }
490 
491 static bool DoesFileExist(ProgramInfo *program_info)
492 {
493  QString filename = get_filename(program_info);
494  qint64 size = GetFileSize(program_info);
495 
496  if (size < 0)
497  {
498  LOG(VB_GENERAL, LOG_ERR, QString("Couldn't find file %1, aborting.")
499  .arg(filename));
500  return false;
501  }
502 
503  if (size == 0)
504  {
505  LOG(VB_GENERAL, LOG_ERR, QString("File %1 is zero-byte, aborting.")
506  .arg(filename));
507  return false;
508  }
509 
510  return true;
511 }
512 
513 static void UpdateFileSize(ProgramInfo *program_info)
514 {
515  qint64 size = GetFileSize(program_info);
516 
517  if (size != (qint64)program_info->GetFilesize())
518  program_info->SaveFilesize(size);
519 }
520 
521 static bool IsMarked(uint chanid, const QDateTime& starttime)
522 {
523  MSqlQuery mark_query(MSqlQuery::InitCon());
524  mark_query.prepare("SELECT commflagged, count(rm.type) "
525  "FROM recorded r "
526  "LEFT JOIN recordedmarkup rm ON "
527  "( r.chanid = rm.chanid AND "
528  "r.starttime = rm.starttime AND "
529  "type in (:MARK_START,:MARK_END)) "
530  "WHERE r.chanid = :CHANID AND "
531  "r.starttime = :STARTTIME "
532  "GROUP BY COMMFLAGGED;");
533  mark_query.bindValue(":MARK_START", MARK_COMM_START);
534  mark_query.bindValue(":MARK_END", MARK_COMM_END);
535  mark_query.bindValue(":CHANID", chanid);
536  mark_query.bindValue(":STARTTIME", starttime);
537 
538  if (mark_query.exec() && mark_query.isActive() &&
539  mark_query.size() > 0)
540  {
541  if (mark_query.next())
542  {
543  int flagStatus = mark_query.value(0).toInt();
544  int marksFound = mark_query.value(1).toInt();
545 
546  QString flagStatusStr = "UNKNOWN";
547  switch (flagStatus) {
549  flagStatusStr = "Not Flagged";
550  break;
551  case COMM_FLAG_DONE:
552  flagStatusStr = QString("Flagged with %1 breaks")
553  .arg(marksFound / 2);
554  break;
556  flagStatusStr = "Flagging";
557  break;
558  case COMM_FLAG_COMMFREE:
559  flagStatusStr = "Commercial Free";
560  break;
561  }
562 
563  LOG(VB_COMMFLAG, LOG_INFO,
564  QString("Status for chanid %1 @ %2 is '%3'")
565  .arg(QString::number(chanid),
566  starttime.toString(Qt::ISODate),
567  flagStatusStr));
568 
569  if ((flagStatus == COMM_FLAG_NOT_FLAGGED) && (marksFound == 0))
570  return false;
571  }
572  }
573  return true;
574 }
575 
576 static int FlagCommercials(ProgramInfo *program_info, int jobid,
577  const QString &outputfilename, bool useDB, bool fullSpeed)
578 {
579  global_program_info = program_info;
580 
581  int breaksFound = 0;
582 
583  // configure commercial detection method
584  SkipType commDetectMethod = (SkipType)gCoreContext->GetNumSetting(
585  "CommercialSkipMethod", COMM_DETECT_ALL);
586 
587  if (cmdline.toBool("commmethod"))
588  {
589  // pull commercial detection method from command line
590  QString commmethod = cmdline.toString("commmethod");
591 
592  // assume definition as integer value
593  bool ok = true;
594  commDetectMethod = (SkipType) commmethod.toInt(&ok);
595  if (!ok)
596  {
597  // not an integer, attempt comma separated list
598  commDetectMethod = COMM_DETECT_UNINIT;
599 
600  QStringList list = commmethod.split(",", Qt::SkipEmptyParts);
601  for (const auto & it : std::as_const(list))
602  {
603  QString val = it.toLower();
604  if (val == "off")
605  {
606  commDetectMethod = COMM_DETECT_OFF;
607  break;
608  }
609 
610  if (!skipTypes->contains(val))
611  {
612  std::cerr << "Failed to decode --method option '"
613  << val.toLatin1().constData()
614  << "'" << std::endl;
616  }
617 
618  if (commDetectMethod == COMM_DETECT_UNINIT) {
619  commDetectMethod = skipTypes->value(val);
620  } else {
621  commDetectMethod = (SkipType) ((int)commDetectMethod
622  | (int)skipTypes->value(val));
623  }
624  }
625 
626  }
627  if (commDetectMethod == COMM_DETECT_UNINIT)
629  }
630  else if (useDB)
631  {
632  // if not manually specified, and we have a database to access
633  // pull the commflag type from the channel
634  MSqlQuery query(MSqlQuery::InitCon());
635  query.prepare("SELECT commmethod FROM channel "
636  "WHERE chanid = :CHANID;");
637  query.bindValue(":CHANID", program_info->GetChanID());
638 
639  if (!query.exec())
640  {
641  // if the query fails, return with an error
642  commDetectMethod = COMM_DETECT_UNINIT;
643  MythDB::DBError("FlagCommercials", query);
644  }
645  else if (query.next())
646  {
647  commDetectMethod = (SkipType)query.value(0).toInt();
648  if (commDetectMethod == COMM_DETECT_COMMFREE)
649  {
650  // if the channel is commercial free, drop to the default instead
651  commDetectMethod = (SkipType)gCoreContext->GetNumSetting(
652  "CommercialSkipMethod", COMM_DETECT_ALL);
653  LOG(VB_COMMFLAG, LOG_INFO,
654  QString("Chanid %1 is marked as being Commercial Free, "
655  "we will use the default commercial detection "
656  "method").arg(program_info->GetChanID()));
657  }
658  else if (commDetectMethod == COMM_DETECT_UNINIT)
659  {
660  // no value set, so use the database default
661  commDetectMethod = (SkipType)gCoreContext->GetNumSetting(
662  "CommercialSkipMethod", COMM_DETECT_ALL);
663  }
664  LOG(VB_COMMFLAG, LOG_INFO,
665  QString("Using method: %1 from channel %2")
666  .arg(commDetectMethod).arg(program_info->GetChanID()));
667  }
668 
669  }
670  else if (!useDB)
671  {
672  // default to a cheaper method for debugging purposes
673  commDetectMethod = COMM_DETECT_BLANK;
674  }
675 
676  // if selection has failed, or intentionally disabled, drop out
677  if (commDetectMethod == COMM_DETECT_UNINIT)
678  return GENERIC_EXIT_NOT_OK;
679  if (commDetectMethod == COMM_DETECT_OFF)
680  return GENERIC_EXIT_OK;
681 
682  recorder = nullptr;
683 
684 /*
685  * is there a purpose to this not fulfilled by --getskiplist?
686  if (onlyDumpDBCommercialBreakList)
687  {
688  frm_dir_map_t commBreakList;
689  program_info->QueryCommBreakList(commBreakList);
690 
691  print_comm_flag_output(program_info, commBreakList,
692  0, nullptr, outputfilename);
693 
694  global_program_info = nullptr;
695  return GENERIC_EXIT_OK;
696  }
697 */
698 
699  if (!DoesFileExist(program_info))
700  {
701  LOG(VB_GENERAL, LOG_ERR,
702  "Unable to find file in defined storage paths.");
704  }
705 
706  QString filename = get_filename(program_info);
707 
709  if (!tmprbuf)
710  {
711  LOG(VB_GENERAL, LOG_ERR,
712  QString("Unable to create RingBuffer for %1").arg(filename));
713  global_program_info = nullptr;
715  }
716 
717  if (useDB)
718  {
720  {
721  LOG(VB_GENERAL, LOG_ERR, "Unable to open commflag DB connection");
722  delete tmprbuf;
723  global_program_info = nullptr;
724  return GENERIC_EXIT_DB_ERROR;
725  }
726  }
727 
728  auto flags = static_cast<PlayerFlags>(kAudioMuted | kVideoIsNull | kNoITV);
729 
730  int flagfast = gCoreContext->GetNumSetting("CommFlagFast", 0);
731  if (flagfast)
732  {
733  // Note: These additional flags replicate the intent of the original
734  // commit that enabled lowres support - but I'm not sure why it requires
735  // single threaded decoding - which surely slows everything down? Though
736  // there is probably no profile to enable multi-threaded decoding anyway.
737  LOG(VB_GENERAL, LOG_INFO, "Enabling experimental flagging speedup (low resolution)");
738  flags = static_cast<PlayerFlags>(flags | kDecodeLowRes | kDecodeSingleThreaded | kDecodeNoLoopFilter);
739  }
740 
741  // blank detector needs to be only sample center for this optimization.
742  if (flagfast && ((COMM_DETECT_BLANKS == commDetectMethod) ||
743  (COMM_DETECT_2_BLANK == commDetectMethod)))
744  {
745  flags = static_cast<PlayerFlags>(flags | kDecodeFewBlocks);
746  }
747 
748  auto *ctx = new PlayerContext(kFlaggerInUseID);
749  auto *cfp = new MythCommFlagPlayer(ctx, flags);
750  ctx->SetPlayingInfo(program_info);
751  ctx->SetRingBuffer(tmprbuf);
752  ctx->SetPlayer(cfp);
753 
754  if (useDB)
755  {
756  if (program_info->GetRecordingEndTime() > MythDate::current())
757  {
759 
760  recorder = RemoteGetExistingRecorder(program_info);
761  if (recorder && (recorder->GetRecorderNumber() != -1))
762  {
764  watchingRecording = true;
765  ctx->SetRecorder(recorder);
766 
767  LOG(VB_COMMFLAG, LOG_INFO,
768  QString("mythcommflag will flag recording "
769  "currently in progress on cardid %1")
770  .arg(recorderNum));
771  }
772  else
773  {
774  recorderNum = -1;
775  watchingRecording = false;
776 
777  LOG(VB_GENERAL, LOG_ERR,
778  "Unable to find active recorder for this "
779  "recording, realtime flagging will not be enabled.");
780  }
781  cfp->SetWatchingRecording(watchingRecording);
782  }
783  }
784 
785  // TODO: Add back insertion of job if not in jobqueue
786 
787  breaksFound = DoFlagCommercials(
788  program_info, progress, fullSpeed, jobid,
789  cfp, commDetectMethod, outputfilename, useDB);
790 
791  if (progress)
792  std::cerr << breaksFound << "\n";
793 
794  LOG(VB_GENERAL, LOG_NOTICE, QString("Finished, %1 break(s) found.")
795  .arg(breaksFound));
796 
797  delete ctx;
798  global_program_info = nullptr;
799 
800  return breaksFound;
801 }
802 
803 static int FlagCommercials( uint chanid, const QDateTime &starttime,
804  int jobid, const QString &outputfilename,
805  bool fullSpeed )
806 {
807  QString startstring = MythDate::toString(starttime, MythDate::kFilename);
808  ProgramInfo pginfo(chanid, starttime);
809 
810  if (!pginfo.GetChanID())
811  {
812  LOG(VB_GENERAL, LOG_ERR,
813  QString("No program data exists for channel %1 at %2")
814  .arg(chanid).arg(startstring));
816  }
817 
818  if (!force && JobQueue::IsJobRunning(JOB_COMMFLAG, pginfo))
819  {
820  if (progress)
821  {
822  std::cerr << "IN USE\n";
823  std::cerr << " "
824  "(the program is already being flagged elsewhere)\n";
825  }
826  LOG(VB_GENERAL, LOG_ERR, "Program is already being flagged elsewhere");
827  return GENERIC_EXIT_IN_USE;
828  }
829 
830 
831  if (progress)
832  {
833  std::cerr << "MythTV Commercial Flagger, flagging commercials for:" << std::endl;
834  if (pginfo.GetSubtitle().isEmpty())
835  std::cerr << " " << pginfo.GetTitle().toLocal8Bit().constData() << std::endl;
836  else
837  std::cerr << " " << pginfo.GetTitle().toLocal8Bit().constData() << " - "
838  << pginfo.GetSubtitle().toLocal8Bit().constData() << std::endl;
839  }
840 
841  return FlagCommercials(&pginfo, jobid, outputfilename, true, fullSpeed);
842 }
843 
844 static int FlagCommercials(const QString& filename, int jobid,
845  const QString &outputfilename, bool useDB,
846  bool fullSpeed)
847 {
848 
849  if (progress)
850  {
851  std::cerr << "MythTV Commercial Flagger, flagging commercials for:" << std::endl
852  << " " << filename.toLatin1().constData() << std::endl;
853  }
854 
855  ProgramInfo pginfo(filename);
856  return FlagCommercials(&pginfo, jobid, outputfilename, useDB, fullSpeed);
857 }
858 
859 static int RebuildSeekTable(ProgramInfo *pginfo, int jobid, bool writefile = false)
860 {
861  QString filename = get_filename(pginfo);
862 
863  if (!DoesFileExist(pginfo))
864  {
865  // file not found on local filesystem
866  // assume file is in Video storage group on local backend
867  // and try again
868 
869  filename = QString("myth://Videos@%1/%2")
871  pginfo->SetPathname(filename);
872  if (!DoesFileExist(pginfo))
873  {
874  LOG(VB_GENERAL, LOG_ERR,
875  QString("Unable to find file in defined storage "
876  "paths for JobQueue ID# %1.").arg(jobid));
878  }
879  }
880 
881  // Update the file size since mythcommflag --rebuild is often used in user
882  // scripts after transcoding or other size-changing operations
883  UpdateFileSize(pginfo);
884 
886  if (!tmprbuf)
887  {
888  LOG(VB_GENERAL, LOG_ERR,
889  QString("Unable to create RingBuffer for %1").arg(filename));
891  }
892 
893  auto *ctx = new PlayerContext(kFlaggerInUseID);
894  auto *cfp = new MythCommFlagPlayer(ctx, (PlayerFlags)(kAudioMuted | kVideoIsNull |
896 
897  ctx->SetPlayingInfo(pginfo);
898  ctx->SetRingBuffer(tmprbuf);
899  ctx->SetPlayer(cfp);
900 
901  if (progress)
902  {
903  QString time = QDateTime::currentDateTime().toString(Qt::TextDate);
904  std::cerr << "Rebuild started at " << qPrintable(time) << std::endl;
905  }
906 
907  if (writefile)
909  cfp->RebuildSeekTable(progress);
910  if (writefile)
912 
913  if (progress)
914  {
915  QString time = QDateTime::currentDateTime().toString(Qt::TextDate);
916  std::cerr << "Rebuild completed at " << qPrintable(time) << std::endl;
917  }
918 
919  delete ctx;
920 
921  return GENERIC_EXIT_OK;
922 }
923 
924 static int RebuildSeekTable(const QString& filename, int jobid, bool writefile = false)
925 {
926  if (progress)
927  {
928  std::cerr << "MythTV Commercial Flagger, building seek table for:" << std::endl
929  << " " << filename.toLatin1().constData() << std::endl;
930  }
931  ProgramInfo pginfo(filename);
932  return RebuildSeekTable(&pginfo, jobid, writefile);
933 }
934 
935 static int RebuildSeekTable(uint chanid, const QDateTime& starttime, int jobid, bool writefile = false)
936 {
937  ProgramInfo pginfo(chanid, starttime);
938  if (progress)
939  {
940  std::cerr << "MythTV Commercial Flagger, building seek table for:" << std::endl;
941  if (pginfo.GetSubtitle().isEmpty())
942  std::cerr << " " << pginfo.GetTitle().toLocal8Bit().constData() << std::endl;
943  else
944  std::cerr << " " << pginfo.GetTitle().toLocal8Bit().constData() << " - "
945  << pginfo.GetSubtitle().toLocal8Bit().constData() << std::endl;
946  }
947  return RebuildSeekTable(&pginfo, jobid, writefile);
948 }
949 
950 int main(int argc, char *argv[])
951 {
952  int result = GENERIC_EXIT_OK;
953 
954 // QString allStart = "19700101000000";
955 // QString allEnd = MythDate::current().toString("yyyyMMddhhmmss");
956  int jobType = JOB_NONE;
957 
958  if (!cmdline.Parse(argc, argv))
959  {
960  cmdline.PrintHelp();
962  }
963 
964  if (cmdline.toBool("showhelp"))
965  {
966  cmdline.PrintHelp();
967  return GENERIC_EXIT_OK;
968  }
969 
970  if (cmdline.toBool("showversion"))
971  {
973  return GENERIC_EXIT_OK;
974  }
975 
976  QCoreApplication a(argc, argv);
977  QCoreApplication::setApplicationName(MYTH_APPNAME_MYTHCOMMFLAG);
978  int retval = cmdline.ConfigureLogging("general",
979  !cmdline.toBool("noprogress"));
980  if (retval != GENERIC_EXIT_OK)
981  return retval;
982 
983  CleanupGuard callCleanup(cleanup);
984 
985 #ifndef _WIN32
987 #endif
988 
989  gContext = new MythContext(MYTH_BINARY_VERSION);
990  if (!gContext->Init( false, /*use gui*/
991  false, /*prompt for backend*/
992  false, /*bypass auto discovery*/
993  cmdline.toBool("skipdb"))) /*ignoreDB*/
994  {
995  LOG(VB_GENERAL, LOG_EMERG, "Failed to init MythContext, exiting.");
997  }
999 
1000  MythTranslation::load("mythfrontend");
1001 
1002  if (cmdline.toBool("outputmethod"))
1003  {
1004  QString om = cmdline.toString("outputmethod");
1005  if (outputTypes->contains(om))
1006  outputMethod = outputTypes->value(om);
1007  }
1008 
1009  if (cmdline.toBool("chanid") && cmdline.toBool("starttime"))
1010  {
1011  // operate on a recording in the database
1012  uint chanid = cmdline.toUInt("chanid");
1013  QDateTime starttime = cmdline.toDateTime("starttime");
1014 
1015  // TODO: check for matching jobid
1016  // create temporary id to operate off of if not
1017 
1018  if (cmdline.toBool("queue"))
1019  QueueCommFlagJob(chanid, starttime, cmdline.toBool("rebuild"));
1020  else if (cmdline.toBool("rebuild"))
1021  result = RebuildSeekTable(chanid, starttime, -1);
1022  else
1023  result = FlagCommercials(chanid, starttime, -1,
1024  cmdline.toString("outputfile"), true);
1025  }
1026  else if (cmdline.toBool("jobid"))
1027  {
1028  jobID = cmdline.toInt("jobid");
1029  uint chanid = 0;
1030  QDateTime starttime;
1031 
1032  if (!JobQueue::GetJobInfoFromID(jobID, jobType, chanid, starttime))
1033  {
1034  std::cerr << "mythcommflag: ERROR: Unable to find DB info for "
1035  << "JobQueue ID# " << jobID << std::endl;
1037  }
1038  force = true;
1039  int jobQueueCPU = gCoreContext->GetNumSetting("JobQueueCPU", 0);
1040 
1041  if (jobQueueCPU < 2)
1042  {
1043  myth_nice(17);
1044  myth_ioprio((0 == jobQueueCPU) ? 8 : 7);
1045  }
1046 
1047  progress = false;
1048 
1049  int ret = 0;
1050 
1052  RebuildSeekTable(chanid, starttime, jobID);
1053  else
1054  ret = FlagCommercials(chanid, starttime, jobID, "", jobQueueCPU != 0);
1055 
1056  if (ret > GENERIC_EXIT_NOT_OK)
1057  {
1058  JobQueue::ChangeJobStatus(jobID, JOB_ERRORED,
1059  QCoreApplication::translate("(mythcommflag)",
1060  "Failed with exit status %1",
1061  "Job status").arg(ret));
1062  }
1063  else
1064  {
1065  JobQueue::ChangeJobStatus(jobID, JOB_FINISHED,
1066  QCoreApplication::translate("(mythcommflag)",
1067  "%n commercial break(s)",
1068  "Job status",
1069  ret));
1070  }
1071  }
1072  else if (cmdline.toBool("video"))
1073  {
1074  // build skiplist for video file
1075  return RebuildSeekTable(cmdline.toString("video"), -1);
1076  }
1077  else if (cmdline.toBool("file"))
1078  {
1079  if (cmdline.toBool("skipdb"))
1080  {
1081  if (cmdline.toBool("rebuild"))
1082  {
1083  std::cerr << "The --rebuild parameter builds the seektable for "
1084  "internal MythTV use only. It cannot be used in "
1085  "combination with --skipdb." << std::endl;
1087  }
1088 
1089  if (!cmdline.toBool("outputfile"))
1090  cmdline.SetValue("outputfile", "-");
1091 
1092  // perform commercial flagging on file outside the database
1093  FlagCommercials(cmdline.toString("file"), -1,
1094  cmdline.toString("outputfile"),
1095  !cmdline.toBool("skipdb"),
1096  true);
1097  }
1098  else
1099  {
1100  ProgramInfo pginfo(cmdline.toString("file"));
1101  // pass chanid and starttime
1102  // inefficient, but it lets the other function
1103  // handle sanity checking
1104  if (cmdline.toBool("rebuild"))
1105  {
1106  result = RebuildSeekTable(pginfo.GetChanID(),
1107  pginfo.GetRecordingStartTime(),
1108  -1, cmdline.toBool("writefile"));
1109  }
1110  else
1111  {
1112  result = FlagCommercials(pginfo.GetChanID(),
1113  pginfo.GetRecordingStartTime(),
1114  -1, cmdline.toString("outputfile"),
1115  true);
1116  }
1117  }
1118  }
1119  else if (cmdline.toBool("queue"))
1120  {
1121  // run flagging for all recordings with no skiplist
1122  MSqlQuery query(MSqlQuery::InitCon());
1123  query.prepare("SELECT r.chanid, r.starttime, c.commmethod "
1124  "FROM recorded AS r "
1125  "LEFT JOIN channel AS c ON r.chanid=c.chanid "
1126 // "WHERE startime >= :STARTTIME AND endtime <= :ENDTIME "
1127  "ORDER BY starttime;");
1128  //query.bindValue(":STARTTIME", allStart);
1129  //query.bindValue(":ENDTIME", allEnd);
1130 
1131  if (query.exec() && query.isActive() && query.size() > 0)
1132  {
1133  QDateTime starttime;
1134 
1135  while (query.next())
1136  {
1137  starttime = MythDate::fromString(query.value(1).toString());
1138  uint chanid = query.value(0).toUInt();
1139 
1140  if (!cmdline.toBool("force") && !cmdline.toBool("rebuild"))
1141  {
1142  // recording is already flagged
1143  if (IsMarked(chanid, starttime))
1144  continue;
1145 
1146  // channel is marked as commercial free
1147  if (query.value(2).toInt() == COMM_DETECT_COMMFREE)
1148  continue;
1149 
1150  // recording rule did not enable commflagging
1151 #if 0
1152  RecordingInfo recinfo(chanid, starttime);
1153  if (!(recinfo.GetAutoRunJobs() & JOB_COMMFLAG))
1154  continue;
1155 #endif
1156  }
1157 
1158  QueueCommFlagJob(chanid, starttime, cmdline.toBool("rebuild"));
1159  }
1160  }
1161 
1162  }
1163  else
1164  {
1165  LOG(VB_GENERAL, LOG_ERR,
1166  "No valid combination of command inputs received.");
1167  cmdline.PrintHelp();
1169  }
1170 
1171  return result;
1172 }
1173 
1174 
1175 /* vim: set expandtab tabstop=4 shiftwidth=4: */
CommDetectorFactory.h
JobQueue::GetJobCmd
static enum JobCmds GetJobCmd(int jobID)
Definition: jobqueue.cpp:1450
MSqlQuery::isActive
bool isActive(void) const
Definition: mythdbcon.h:215
COMM_DETECT_2_ALL
@ COMM_DETECT_2_ALL
Definition: programtypes.h:146
MSqlQuery::next
bool next(void)
Wrap QSqlQuery::next() so we can display the query results.
Definition: mythdbcon.cpp:813
MSqlQuery
QSqlQuery wrapper that fetches a DB connection from the connection pool.
Definition: mythdbcon.h:127
FlagCommercials
static int FlagCommercials(ProgramInfo *program_info, int jobid, const QString &outputfilename, bool useDB, bool fullSpeed)
Definition: mythcommflag.cpp:576
ProgramInfo::SaveFilesize
virtual void SaveFilesize(uint64_t fsize)
Sets recording file size in database, and sets "filesize" field.
Definition: programinfo.cpp:6394
COMM_DETECT_SCENE
@ COMM_DETECT_SCENE
Definition: programtypes.h:134
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:1517
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:214
CustomEventRelayer
Definition: CustomEventRelayer.h:14
COMM_FLAG_NOT_FLAGGED
@ COMM_FLAG_NOT_FLAGGED
Definition: programtypes.h:121
COMM_DETECT_ALL
@ COMM_DETECT_ALL
Definition: programtypes.h:137
ProgramInfo::GetFilesize
virtual uint64_t GetFilesize(void) const
Definition: programinfo.cpp:6425
MARK_COMM_END
@ MARK_COMM_END
Definition: programtypes.h:60
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:63
MythEvent::kMythEventMessage
static const Type kMythEventMessage
Definition: mythevent.h:79
MythPlayer::GetTotalFrameCount
uint64_t GetTotalFrameCount(void) const
Definition: mythplayer.h:143
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:505
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:950
cmdline
MythCommFlagCommandLineParser cmdline
Definition: mythcommflag.cpp:72
MythCoreContext::UnregisterFileForWrite
void UnregisterFileForWrite(const QString &file)
Definition: mythcorecontext.cpp:2140
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:357
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:79
MythCoreContext::RegisterFileForWrite
void RegisterFileForWrite(const QString &file, uint64_t size=0LL)
Definition: mythcorecontext.cpp:2122
JOB_PAUSE
@ JOB_PAUSE
Definition: jobqueue.h:52
commDetectorGotNewCommercialBreakList
static void commDetectorGotNewCommercialBreakList(void)
Definition: mythcommflag.cpp:304
COMM_DETECT_BLANK_SCENE
@ COMM_DETECT_BLANK_SCENE
Definition: programtypes.h:136
MSqlQuery::value
QVariant value(int i) const
Definition: mythdbcon.h:204
JOB_RESUME
@ JOB_RESUME
Definition: jobqueue.h:53
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:118
JOB_NONE
@ JOB_NONE
Definition: jobqueue.h:75
JobQueue::GetJobInfoFromID
static bool GetJobInfoFromID(int jobID, int &jobType, uint &chanid, QDateTime &recstartts)
Definition: jobqueue.cpp:656
RemoteFile
Definition: remotefile.h:17
MSqlQuery::exec
bool exec(void)
Wrap QSqlQuery::exec() so we can display SQL.
Definition: mythdbcon.cpp:619
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:131
ProgramInfo::SaveCommFlagged
void SaveCommFlagged(CommFlagStatus flag)
Set "commflagged" field in "recorded" table to "flag".
Definition: programinfo.cpp:3340
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:385
JOB_STOP
@ JOB_STOP
Definition: jobqueue.h:54
PlayerFlags
PlayerFlags
Definition: mythplayer.h:64
build_compdb.file
file
Definition: build_compdb.py:55
skipTypes
QMap< QString, SkipType > * skipTypes
Definition: mythcommflag.cpp:84
kDecodeLowRes
@ kDecodeLowRes
Definition: mythplayer.h:67
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:123
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:1077
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:3543
tmp
static guint32 * tmp
Definition: goom_core.cpp:26
COMM_FLAG_DONE
@ COMM_FLAG_DONE
Definition: programtypes.h:122
COMM_DETECT_2_BLANK
@ COMM_DETECT_2_BLANK
Definition: programtypes.h:142
MythCommandLineParser::Parse
virtual bool Parse(int argc, const char *const *argv)
Loop through argv and populate arguments with values.
Definition: mythcommandlineparser.cpp:1544
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:133
UpdateFileSize
static void UpdateFileSize(ProgramInfo *program_info)
Definition: mythcommflag.cpp:513
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:129
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:1001
MYTH_APPNAME_MYTHCOMMFLAG
static constexpr const char * MYTH_APPNAME_MYTHCOMMFLAG
Definition: mythcorecontext.h:24
signalhandling.h
DoesFileExist
static bool DoesFileExist(ProgramInfo *program_info)
Definition: mythcommflag.cpp:491
MSqlQuery::InitCon
static MSqlQueryInfo InitCon(ConnectionReuse _reuse=kNormalConnection)
Only use this in combination with MSqlQuery constructor.
Definition: mythdbcon.cpp:551
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:469
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:877
IsMarked
static bool IsMarked(uint chanid, const QDateTime &starttime)
Definition: mythcommflag.cpp:521
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:1372
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:2236
MythCommandLineParser::PrintHelp
void PrintHelp(void) const
Print command line option help.
Definition: mythcommandlineparser.cpp:1388
jobqueue.h
GENERIC_EXIT_NOT_OK
@ GENERIC_EXIT_NOT_OK
Exited with error.
Definition: exitcodes.h:12
kNoITV
@ kNoITV
Definition: mythplayer.h:75
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:71
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:2916
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:912
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:68
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:130
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:73
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:859
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:2344
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:2816
MythCommandLineParser::toBool
bool toBool(const QString &key) const
Returns stored QVariant as a boolean.
Definition: mythcommandlineparser.cpp:2187
MARK_UPDATED_CUT
@ MARK_UPDATED_CUT
Definition: programtypes.h:53
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:889
MythDate::ISODate
@ ISODate
Default UTC.
Definition: mythdate.h:17
JobQueue::GetJobFlags
static enum JobFlags GetJobFlags(int jobID)
Definition: jobqueue.cpp:1492
mythcontext.h
commDetectorBreathe
static void commDetectorBreathe()
Definition: mythcommflag.cpp:256
kDecodeNoLoopFilter
@ kDecodeNoLoopFilter
Definition: mythplayer.h:70
kAudioMuted
@ kAudioMuted
Definition: mythplayer.h:74
PlayerContext
Definition: playercontext.h:49
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:128
MythCoreContext::GetHostName
QString GetHostName(void)
Definition: mythcorecontext.cpp:838
ProgramInfo::SaveMarkupFlag
void SaveMarkupFlag(MarkTypes type) const
Clears the specified flag, then if sets it.
Definition: programinfo.cpp:3754
MythPlayer::SaveTotalDuration
void SaveTotalDuration(void)
Definition: mythplayer.cpp:1964
MythCommandLineParser::ConfigureLogging
int ConfigureLogging(const QString &mask="general", bool progress=false)
Read in logging options and initialize the logging interface.
Definition: mythcommandlineparser.cpp:2849
COMM_DETECT_2_SCENE
@ COMM_DETECT_2_SCENE
Definition: programtypes.h:143
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:2209
JobQueue::ChangeJobStatus
static bool ChangeJobStatus(int jobID, int newStatus, const QString &comment="")
Definition: jobqueue.cpp:974
CommDetectorBase.h
COMM_DETECT_LOGO
@ COMM_DETECT_LOGO
Definition: programtypes.h:135
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:59
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:2441
CommDetectorBase::pause
void pause()
Definition: CommDetectorBase.cpp:8
COMM_FLAG_COMMFREE
@ COMM_FLAG_COMMFREE
Definition: programtypes.h:124
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:140
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:141
kDecodeFewBlocks
@ kDecodeFewBlocks
Definition: mythplayer.h:69
CustomEventRelayer.h
MSqlQuery::prepare
bool prepare(const QString &query)
QSqlQuery::prepare() is not thread safe in Qt <= 3.3.2.
Definition: mythdbcon.cpp:838
ProgramInfo::GetSubtitle
QString GetSubtitle(void) const
Definition: programinfo.h:363
COMM_DETECT_BLANK
@ COMM_DETECT_BLANK
Definition: programtypes.h:132
GENERIC_EXIT_DB_ERROR
@ GENERIC_EXIT_DB_ERROR
Database error.
Definition: exitcodes.h:18