Go to the documentation of this file.
2 #if defined ANDROID && __ANDROID_API__ < 24
21 #include <QCoreApplication>
35 #include "libmythbase/mythversion.h"
54 #define LOC QString("MythCommFlag: ")
55 #define LOC_WARN QString("MythCommFlag, Warning: ")
56 #define LOC_ERR QString("MythCommFlag, Error: ")
88 auto *
tmp =
new QMap<QString,SkipType>;
119 auto *
tmp =
new QMap<QString,OutputMethod>;
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;
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;
160 rebuild ?
JOB_REBUILD : 0, JOB_QUEUED, QDateTime());
166 QString
tmp = QString(
"Job Queued for chanid %1 @ %2")
167 .arg(chanid).arg(startstring);
168 std::cerr <<
tmp.toLocal8Bit().constData() << std::endl;
175 QString
tmp = QString(
"Error queueing job for chanid %1 @ %2")
176 .arg(chanid).arg(startstring);
177 std::cerr <<
tmp.toLocal8Bit().constData() << std::endl;
186 output <<
"----------------------------" << std::endl;
188 if (commercialBreakList.empty())
191 output <<
"No breaks" << std::endl;
195 frm_dir_map_t::const_iterator it = commercialBreakList.begin();
196 for (; it != commercialBreakList.end(); ++it)
198 output <<
"framenum: " << it.key() <<
"\tmarktype: " << *it
204 output <<
"----------------------------" << std::endl;
210 uint64_t frame_count,
212 const QString &output_filename)
214 if (output_filename.isEmpty())
217 std::ostream *out = &std::cout;
218 if (output_filename !=
"-")
220 QByteArray
tmp = output_filename.toLocal8Bit();
221 out =
new std::fstream(
tmp.constData(), std::ios::app | std::ios::out );
229 tmp = QString(
"commercialBreakListFor: %1 on %2 @ %3")
236 tmp = QString(
"commercialBreakListFor: %1")
240 const QByteArray tmp2 =
tmp.toLocal8Bit();
241 *out << tmp2.constData() << std::endl;
244 *out <<
"totalframecount: " << frame_count << std::endl;
252 if (out != &std::cout)
260 qApp->processEvents();
278 QCoreApplication::translate(
"(mythcommflag)",
279 "Paused",
"Job status"));
286 QCoreApplication::translate(
"(mythcommflag)",
287 "Running",
"Job status"));
309 QString message =
"COMMFLAG_UPDATE ";
312 for (
auto it = newCommercialMap.begin();
313 it != newCommercialMap.end(); ++it)
315 if (it != newCommercialMap.begin())
319 message += QString(
"%1:%2").arg(it.key())
323 LOG(VB_COMMFLAG, LOG_INFO,
324 QString(
"mythcommflag sending update: %1").arg(message));
337 QString message = me->
Message();
339 message = message.simplified();
340 QStringList tokens = message.split(
" ", Qt::SkipEmptyParts);
342 LOG(VB_COMMFLAG, LOG_INFO,
343 QString(
"mythcommflag: Received Event: '%1'") .arg(message));
346 (tokens[0] ==
"DONE_RECORDING"))
348 int cardnum = tokens[1].toInt();
349 int filelen = tokens[2].toInt();
351 message = QString(
"mythcommflag: Received a "
352 "DONE_RECORDING event for card %1. ")
359 message +=
"Informed CommDetector that recording has finished.";
360 LOG(VB_COMMFLAG, LOG_INFO, message);
364 if ((tokens.size() >= 2) && (tokens[0] ==
"COMMFLAG_REQUEST"))
367 QDateTime recstartts;
370 message = QString(
"mythcommflag: Received a "
371 "COMMFLAG_REQUEST event for chanid %1 @ %2. ")
372 .arg(chanid).arg(recstartts.toString(
Qt::ISODate));
378 message +=
"Requested CommDetector to generate new break list.";
379 LOG(VB_COMMFLAG, LOG_INFO, message);
387 bool showPercentage,
bool fullSpeed,
int jobid,
389 const QString &outputfilename,
bool useDB)
392 commDetectMethod, showPercentage,
401 LOG(VB_COMMFLAG, LOG_INFO,
402 QString(
"mythcommflag processing JobID %1").arg(jobid));
420 LOG(VB_COMMFLAG, LOG_INFO,
421 "mythcommflag sending COMMFLAG_START notification");
422 QString message =
"COMMFLAG_START ";
436 comms_found = commBreakList.size() / 2;
498 LOG(VB_GENERAL, LOG_ERR, QString(
"Couldn't find file %1, aborting.")
505 LOG(VB_GENERAL, LOG_ERR, QString(
"File %1 is zero-byte, aborting.")
524 mark_query.
prepare(
"SELECT commflagged, count(rm.type) "
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;");
536 mark_query.
bindValue(
":STARTTIME", starttime);
539 mark_query.
size() > 0)
541 if (mark_query.
next())
543 int flagStatus = mark_query.
value(0).toInt();
544 int marksFound = mark_query.
value(1).toInt();
546 QString flagStatusStr =
"UNKNOWN";
547 switch (flagStatus) {
549 flagStatusStr =
"Not Flagged";
552 flagStatusStr = QString(
"Flagged with %1 breaks")
553 .arg(marksFound / 2);
556 flagStatusStr =
"Flagging";
559 flagStatusStr =
"Commercial Free";
563 LOG(VB_COMMFLAG, LOG_INFO,
564 QString(
"Status for chanid %1 @ %2 is '%3'")
565 .arg(QString::number(chanid),
577 const QString &outputfilename,
bool useDB,
bool fullSpeed)
594 commDetectMethod = (
SkipType) commmethod.toInt(&ok);
600 QStringList list = commmethod.split(
",", Qt::SkipEmptyParts);
601 for (
const auto & it : std::as_const(list))
603 QString val = it.toLower();
612 std::cerr <<
"Failed to decode --method option '"
613 << val.toLatin1().constData()
619 commDetectMethod =
skipTypes->value(val);
621 commDetectMethod = (
SkipType) ((
int)commDetectMethod
635 query.
prepare(
"SELECT commmethod FROM channel "
636 "WHERE chanid = :CHANID;");
645 else if (query.
next())
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()));
664 LOG(VB_COMMFLAG, LOG_INFO,
665 QString(
"Using method: %1 from channel %2")
666 .arg(commDetectMethod).arg(program_info->
GetChanID()));
701 LOG(VB_GENERAL, LOG_ERR,
702 "Unable to find file in defined storage paths.");
711 LOG(VB_GENERAL, LOG_ERR,
712 QString(
"Unable to create RingBuffer for %1").arg(
filename));
721 LOG(VB_GENERAL, LOG_ERR,
"Unable to open commflag DB connection");
737 LOG(VB_GENERAL, LOG_INFO,
"Enabling experimental flagging speedup (low resolution)");
750 ctx->SetPlayingInfo(program_info);
751 ctx->SetRingBuffer(tmprbuf);
767 LOG(VB_COMMFLAG, LOG_INFO,
768 QString(
"mythcommflag will flag recording "
769 "currently in progress on cardid %1")
777 LOG(VB_GENERAL, LOG_ERR,
778 "Unable to find active recorder for this "
779 "recording, realtime flagging will not be enabled.");
788 program_info,
progress, fullSpeed, jobid,
789 cfp, commDetectMethod, outputfilename, useDB);
792 std::cerr << breaksFound <<
"\n";
794 LOG(VB_GENERAL, LOG_NOTICE, QString(
"Finished, %1 break(s) found.")
804 int jobid,
const QString &outputfilename,
812 LOG(VB_GENERAL, LOG_ERR,
813 QString(
"No program data exists for channel %1 at %2")
814 .arg(chanid).arg(startstring));
822 std::cerr <<
"IN USE\n";
824 "(the program is already being flagged elsewhere)\n";
826 LOG(VB_GENERAL, LOG_ERR,
"Program is already being flagged elsewhere");
833 std::cerr <<
"MythTV Commercial Flagger, flagging commercials for:" << std::endl;
835 std::cerr <<
" " << pginfo.
GetTitle().toLocal8Bit().constData() << std::endl;
837 std::cerr <<
" " << pginfo.
GetTitle().toLocal8Bit().constData() <<
" - "
838 << pginfo.
GetSubtitle().toLocal8Bit().constData() << std::endl;
841 return FlagCommercials(&pginfo, jobid, outputfilename,
true, fullSpeed);
845 const QString &outputfilename,
bool useDB,
851 std::cerr <<
"MythTV Commercial Flagger, flagging commercials for:" << std::endl
852 <<
" " <<
filename.toLatin1().constData() << std::endl;
856 return FlagCommercials(&pginfo, jobid, outputfilename, useDB, fullSpeed);
869 filename = QString(
"myth://Videos@%1/%2")
874 LOG(VB_GENERAL, LOG_ERR,
875 QString(
"Unable to find file in defined storage "
876 "paths for JobQueue ID# %1.").arg(jobid));
888 LOG(VB_GENERAL, LOG_ERR,
889 QString(
"Unable to create RingBuffer for %1").arg(
filename));
897 ctx->SetPlayingInfo(pginfo);
898 ctx->SetRingBuffer(tmprbuf);
903 QString time = QDateTime::currentDateTime().toString(Qt::TextDate);
904 std::cerr <<
"Rebuild started at " << qPrintable(time) << std::endl;
915 QString time = QDateTime::currentDateTime().toString(Qt::TextDate);
916 std::cerr <<
"Rebuild completed at " << qPrintable(time) << std::endl;
928 std::cerr <<
"MythTV Commercial Flagger, building seek table for:" << std::endl
929 <<
" " <<
filename.toLatin1().constData() << std::endl;
940 std::cerr <<
"MythTV Commercial Flagger, building seek table for:" << std::endl;
942 std::cerr <<
" " << pginfo.
GetTitle().toLocal8Bit().constData() << std::endl;
944 std::cerr <<
" " << pginfo.
GetTitle().toLocal8Bit().constData() <<
" - "
945 << pginfo.
GetSubtitle().toLocal8Bit().constData() << std::endl;
950 int main(
int argc,
char *argv[])
976 QCoreApplication a(argc, argv);
995 LOG(VB_GENERAL, LOG_EMERG,
"Failed to init MythContext, exiting.");
1030 QDateTime starttime;
1034 std::cerr <<
"mythcommflag: ERROR: Unable to find DB info for "
1035 <<
"JobQueue ID# " <<
jobID << std::endl;
1041 if (jobQueueCPU < 2)
1059 QCoreApplication::translate(
"(mythcommflag)",
1060 "Failed with exit status %1",
1061 "Job status").arg(ret));
1066 QCoreApplication::translate(
"(mythcommflag)",
1067 "%n commercial break(s)",
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;
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 "
1127 "ORDER BY starttime;");
1133 QDateTime starttime;
1135 while (query.
next())
1165 LOG(VB_GENERAL, LOG_ERR,
1166 "No valid combination of command inputs received.");
static enum JobCmds GetJobCmd(int jobID)
bool isActive(void) const
bool next(void)
Wrap QSqlQuery::next() so we can display the query results.
QSqlQuery wrapper that fetches a DB connection from the connection pool.
static int FlagCommercials(ProgramInfo *program_info, int jobid, const QString &outputfilename, bool useDB, bool fullSpeed)
virtual void SaveFilesize(uint64_t fsize)
Sets recording file size in database, and sets "filesize" field.
static QMap< QString, OutputMethod > * init_output_types()
QString MakeUniqueKey(void) const
Creates a unique string that can be used to identify an existing recording.
void SendMessage(const QString &message)
QString toString(const QDateTime &raw_dt, uint format)
Returns formatted string representing the time.
virtual uint64_t GetFilesize(void) const
RemoteEncoder * RemoteGetExistingRecorder(const ProgramInfo *pginfo)
Abstract base class for all CommDetectors. Please use the CommDetectFactory to make actual instances.
static const Type kMythEventMessage
uint64_t GetTotalFrameCount(void) const
int GetRecorderNumber(void) const
@ COMM_DETECT_BLANK_SCENE
CommDetectorBase * commDetector
long long GetFileSize(void) const
GetFileSize: returns the remote file's size at the time it was first opened Will query the server in ...
static 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())
bool myth_ioprio(int)
Allows setting the I/O priority of the current process/thread.
int main(int argc, char *argv[])
MythCommFlagCommandLineParser cmdline
void UnregisterFileForWrite(const QString &file)
bool ConnectToMasterServer(bool blockingClient=true, bool openEventSocket=true)
Holds information on a TV Program one might wish to record.
OutputMethod outputMethod
void gotNewCommercialBreakList()
Startup context for MythTV.
static int QueueCommFlagJob(uint chanid, const QDateTime &starttime, bool rebuild)
This class is used as a container for messages.
void RegisterFileForWrite(const QString &file, uint64_t size=0LL)
static void commDetectorGotNewCommercialBreakList(void)
QVariant value(int i) const
void statusUpdate(const QString &a)
QMap< uint64_t, MarkTypes > frm_dir_map_t
Frame # -> Mark map.
static bool GetJobInfoFromID(int jobID, int &jobType, uint &chanid, QDateTime &recstartts)
bool exec(void)
Wrap QSqlQuery::exec() so we can display SQL.
static bool ExtractKey(const QString &uniquekey, uint &chanid, QDateTime &recstartts)
Extracts chanid and recstartts from a unique key generated by MakeUniqueKey().
void SaveCommFlagged(CommFlagStatus flag)
Set "commflagged" field in "recorded" table to "flag".
QDateTime GetScheduledEndTime(void) const
The scheduled end time of the program.
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
static int DoFlagCommercials(ProgramInfo *program_info, bool showPercentage, bool fullSpeed, int jobid, MythCommFlagPlayer *cfp, SkipType commDetectMethod, const QString &outputfilename, bool useDB)
QMap< QString, SkipType > * skipTypes
QDateTime GetRecordingEndTime(void) const
Approximate time the recording should have ended, did end, or is intended to end.
QDateTime current(bool stripped)
Returns current Date and Time in UTC.
const QString & Message() const
@ GENERIC_EXIT_NO_RECORDING_DATA
No program/recording data.
static bool IsJobRunning(int jobType, uint chanid, const QDateTime &recstartts)
QDateTime GetRecordingStartTime(void) const
Approximate time the recording started.
QString GetPathname(void) const
void SaveCommBreakList(frm_dir_map_t &frames) const
virtual bool Parse(int argc, const char *const *argv)
Loop through argv and populate arguments with values.
void SetPathname(const QString &pn)
static void UpdateFileSize(ProgramInfo *program_info)
virtual void recordingFinished([[maybe_unused]] long long totalFileSize)
virtual void PrintFullMap(std::ostream &out, const frm_dir_map_t *comm_breaks, bool verbose) const =0
@ GENERIC_EXIT_INVALID_CMDLINE
Command line parse error.
QDateTime GetScheduledStartTime(void) const
The scheduled start time of program.
static void commDetectorStatusUpdate(const QString &status)
@ kFilename
Default UTC, "yyyyMMddhhmmss".
static bool ChangeJobComment(int jobID, const QString &comment="")
static constexpr const char * MYTH_APPNAME_MYTHCOMMFLAG
@ GENERIC_EXIT_OK
Exited with no error.
static bool DoesFileExist(ProgramInfo *program_info)
static MSqlQueryInfo InitCon(ConnectionReuse _reuse=kNormalConnection)
Only use this in combination with MSqlQuery constructor.
QString GetTitle(void) const
static qint64 GetFileSize(ProgramInfo *program_info)
static void DBError(const QString &where, const MSqlQuery &query)
static bool testDBConnection()
Checks DB connection + login (login info via Mythcontext)
static bool IsMarked(uint chanid, const QDateTime &starttime)
int GetAutoRunJobs(void) const
Returns a bitmap of which jobs are attached to this RecordingInfo.
static QMap< QString, SkipType > * init_skip_types()
static void PrintVersion(void)
Print application version information.
uint toUInt(const QString &key) const
Returns stored QVariant as an unsigned integer, falling to default if not provided.
@ GENERIC_EXIT_IN_USE
Recording in use, can't flag.
void PrintHelp(void) const
Print command line option help.
static QString get_filename(ProgramInfo *program_info)
virtual void GetCommercialBreakList(frm_dir_map_t &comms)=0
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
void ApplySettingsOverride(void)
Apply all overrides to the global context.
int GetNumSetting(const QString &key, int defaultval=0)
QDateTime fromString(const QString &dtstr)
Converts kFilename && kISODate formats to QDateTime.
SkipType
This is used as a bitmask.
static void streamOutCommercialBreakList(std::ostream &output, const frm_dir_map_t &commercialBreakList)
static void Init(QObject *parent=nullptr)
uint GetChanID(void) const
This is the unique key used in the database to locate tuning information.
Holds information on recordings and videos.
static int RebuildSeekTable(ProgramInfo *pginfo, int jobid, bool writefile=false)
QString toString(const QString &key) const
Returns stored QVariant as a QString, falling to default if not provided.
ProgramInfo * global_program_info
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.
@ kOutputMethodEssentials
bool toBool(const QString &key) const
Returns stored QVariant as a boolean.
QString GetPlaybackURL(bool checkMaster=false, bool forceCheckLocal=false)
Returns filename or URL to be used to play back this recording.
void bindValue(const QString &placeholder, const QVariant &val)
Add a single binding.
static enum JobFlags GetJobFlags(int jobID)
static void commDetectorBreathe()
@ GENERIC_EXIT_NOT_OK
Exited with error.
@ GENERIC_EXIT_PERMISSIONS_ERROR
File permissions error.
QString GetHostName(void)
void SaveMarkupFlag(MarkTypes type) const
Clears the specified flag, then if sets it.
void SaveTotalDuration(void)
int ConfigureLogging(const QString &mask="general", bool progress=false)
Read in logging options and initialize the logging interface.
QMap< QString, OutputMethod > * outputTypes
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)
virtual void requestCommBreakMapUpdate(void)
const QString kFlaggerInUseID
static void load(const QString &module_name)
Load a QTranslator for the user's preferred language.
int toInt(const QString &key) const
Returns stored QVariant as an integer, falling to default if not provided.
static bool ChangeJobStatus(int jobID, int newStatus, const QString &comment="")
static void incomingCustomEvent(QEvent *e)
QDateTime toDateTime(const QString &key) const
Returns stored QVariant as a QDateTime, falling to default if not provided.
MythContext * gContext
This global variable contains the MythContext instance for the application.
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)
bool Init(bool gui=true, bool promptForBackend=false, bool disableAutoDiscovery=false, bool ignoreDB=false)
@ GENERIC_EXIT_DB_ERROR
Database error.
@ GENERIC_EXIT_NO_MYTHCONTEXT
No MythContext available.
bool prepare(const QString &query)
QSqlQuery::prepare() is not thread safe in Qt <= 3.3.2.
QString GetSubtitle(void) const