Go to the documentation of this file.
2 #if defined ANDROID && __ANDROID_API__ < 24
21 #include <QCoreApplication>
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;
185 frm_dir_map_t::const_iterator it;
192 LOG(VB_GENERAL, LOG_ERR,
193 QString(
"No program data exists for channel %1 at %2")
194 .arg(chanid).arg(startstring));
199 for (it = cutlist.cbegin(); it != cutlist.cend(); ++it)
218 LOG(VB_GENERAL, LOG_ERR,
219 QString(
"No program data exists for channel %1 at %2")
220 .arg(chanid).arg(startstring));
227 LOG(VB_GENERAL, LOG_NOTICE,
"Commercial skip list cleared");
232 static int SetCutList(
uint chanid,
const QDateTime& starttime, QString newCutList)
236 newCutList.remove(
" ");
238 #if QT_VERSION < QT_VERSION_CHECK(5,14,0)
239 QStringList tokens = newCutList.split(
",", QString::SkipEmptyParts);
241 QStringList tokens = newCutList.split(
",", Qt::SkipEmptyParts);
244 for (
const QString& token : qAsConst(tokens))
246 #if QT_VERSION < QT_VERSION_CHECK(5,14,0)
247 QStringList cutpair = token.split(
"-", QString::SkipEmptyParts);
249 QStringList cutpair = token.split(
"-", Qt::SkipEmptyParts);
260 LOG(VB_GENERAL, LOG_ERR,
261 QString(
"No program data exists for channel %1 at %2")
262 .arg(chanid).arg(startstring));
268 LOG(VB_GENERAL, LOG_NOTICE, QString(
"Cutlist set to: %1").arg(newCutList));
276 frm_dir_map_t::const_iterator it;
284 LOG(VB_GENERAL, LOG_ERR,
285 QString(
"No program data exists for channel %1 at %2")
286 .arg(chanid).arg(startstring));
290 if (list ==
"cutlist")
295 uint64_t lastStart = 0;
296 for (it = cutlist.cbegin(); it != cutlist.cend(); ++it)
301 if (!result.isEmpty())
303 lastStart = it.key();
304 result += QString(
"%1-").arg(lastStart);
308 if (result.isEmpty())
310 result += QString(
"%1").arg(it.key());
314 if (result.endsWith(
'-'))
317 if (lastFrame > lastStart)
318 result += QString(
"%1").arg(lastFrame);
321 if (list ==
"cutlist")
322 std::cout << QString(
"Cutlist: %1\n").arg(result).toLocal8Bit().constData();
325 std::cout << QString(
"Commercial Skip List: %1\n")
326 .arg(result).toLocal8Bit().constData();
336 output <<
"----------------------------" << std::endl;
338 if (commercialBreakList.empty())
341 output <<
"No breaks" << std::endl;
345 frm_dir_map_t::const_iterator it = commercialBreakList.begin();
346 for (; it != commercialBreakList.end(); ++it)
348 output <<
"framenum: " << it.key() <<
"\tmarktype: " << *it
354 output <<
"----------------------------" << std::endl;
360 uint64_t frame_count,
362 const QString &output_filename)
364 if (output_filename.isEmpty())
367 std::ostream *out = &std::cout;
368 if (output_filename !=
"-")
370 QByteArray
tmp = output_filename.toLocal8Bit();
371 out =
new std::fstream(
tmp.constData(), std::ios::app | std::ios::out );
379 tmp = QString(
"commercialBreakListFor: %1 on %2 @ %3")
386 tmp = QString(
"commercialBreakListFor: %1")
390 const QByteArray tmp2 =
tmp.toLocal8Bit();
391 *out << tmp2.constData() << std::endl;
394 *out <<
"totalframecount: " << frame_count << std::endl;
402 if (out != &std::cout)
410 qApp->processEvents();
428 QCoreApplication::translate(
"(mythcommflag)",
429 "Paused",
"Job status"));
436 QCoreApplication::translate(
"(mythcommflag)",
437 "Running",
"Job status"));
459 QString message =
"COMMFLAG_UPDATE ";
462 for (
auto it = newCommercialMap.begin();
463 it != newCommercialMap.end(); ++it)
465 if (it != newCommercialMap.begin())
469 message += QString(
"%1:%2").arg(it.key())
473 LOG(VB_COMMFLAG, LOG_INFO,
474 QString(
"mythcommflag sending update: %1").arg(message));
487 QString message = me->
Message();
489 message = message.simplified();
490 #if QT_VERSION < QT_VERSION_CHECK(5,14,0)
491 QStringList tokens = message.split(
" ", QString::SkipEmptyParts);
493 QStringList tokens = message.split(
" ", Qt::SkipEmptyParts);
496 LOG(VB_COMMFLAG, LOG_INFO,
497 QString(
"mythcommflag: Received Event: '%1'") .arg(message));
500 (tokens[0] ==
"DONE_RECORDING"))
502 int cardnum = tokens[1].toInt();
503 int filelen = tokens[2].toInt();
505 message = QString(
"mythcommflag: Received a "
506 "DONE_RECORDING event for card %1. ")
513 message +=
"Informed CommDetector that recording has finished.";
514 LOG(VB_COMMFLAG, LOG_INFO, message);
518 if ((tokens.size() >= 2) && (tokens[0] ==
"COMMFLAG_REQUEST"))
521 QDateTime recstartts;
524 message = QString(
"mythcommflag: Received a "
525 "COMMFLAG_REQUEST event for chanid %1 @ %2. ")
526 .arg(chanid).arg(recstartts.toString(
Qt::ISODate));
532 message +=
"Requested CommDetector to generate new break list.";
533 LOG(VB_COMMFLAG, LOG_INFO, message);
541 bool showPercentage,
bool fullSpeed,
int jobid,
543 const QString &outputfilename,
bool useDB)
546 commDetectMethod, showPercentage,
555 LOG(VB_COMMFLAG, LOG_INFO,
556 QString(
"mythcommflag processing JobID %1").arg(jobid));
574 LOG(VB_COMMFLAG, LOG_INFO,
575 "mythcommflag sending COMMFLAG_START notification");
576 QString message =
"COMMFLAG_START ";
590 comms_found = commBreakList.size() / 2;
652 LOG(VB_GENERAL, LOG_ERR, QString(
"Couldn't find file %1, aborting.")
659 LOG(VB_GENERAL, LOG_ERR, QString(
"File %1 is zero-byte, aborting.")
678 mark_query.
prepare(
"SELECT commflagged, count(rm.type) "
680 "LEFT JOIN recordedmarkup rm ON "
681 "( r.chanid = rm.chanid AND "
682 "r.starttime = rm.starttime AND "
683 "type in (:MARK_START,:MARK_END)) "
684 "WHERE r.chanid = :CHANID AND "
685 "r.starttime = :STARTTIME "
686 "GROUP BY COMMFLAGGED;");
690 mark_query.
bindValue(
":STARTTIME", starttime);
693 mark_query.
size() > 0)
695 if (mark_query.
next())
697 int flagStatus = mark_query.
value(0).toInt();
698 int marksFound = mark_query.
value(1).toInt();
700 QString flagStatusStr =
"UNKNOWN";
701 switch (flagStatus) {
703 flagStatusStr =
"Not Flagged";
706 flagStatusStr = QString(
"Flagged with %1 breaks")
707 .arg(marksFound / 2);
710 flagStatusStr =
"Flagging";
713 flagStatusStr =
"Commercial Free";
717 LOG(VB_COMMFLAG, LOG_INFO,
718 QString(
"Status for chanid %1 @ %2 is '%3'")
719 .arg(QString::number(chanid),
731 const QString &outputfilename,
bool useDB,
bool fullSpeed)
748 commDetectMethod = (
SkipType) commmethod.toInt(&ok);
754 #if QT_VERSION < QT_VERSION_CHECK(5,14,0)
755 QStringList list = commmethod.split(
",", QString::SkipEmptyParts);
757 QStringList list = commmethod.split(
",", Qt::SkipEmptyParts);
759 for (
const auto & it : qAsConst(list))
761 QString val = it.toLower();
770 std::cerr <<
"Failed to decode --method option '"
771 << val.toLatin1().constData()
777 commDetectMethod =
skipTypes->value(val);
779 commDetectMethod = (
SkipType) ((
int)commDetectMethod
793 query.
prepare(
"SELECT commmethod FROM channel "
794 "WHERE chanid = :CHANID;");
803 else if (query.
next())
811 LOG(VB_COMMFLAG, LOG_INFO,
812 QString(
"Chanid %1 is marked as being Commercial Free, "
813 "we will use the default commercial detection "
814 "method").arg(program_info->
GetChanID()));
822 LOG(VB_COMMFLAG, LOG_INFO,
823 QString(
"Using method: %1 from channel %2")
824 .arg(commDetectMethod).arg(program_info->
GetChanID()));
859 LOG(VB_GENERAL, LOG_ERR,
860 "Unable to find file in defined storage paths.");
869 LOG(VB_GENERAL, LOG_ERR,
870 QString(
"Unable to create RingBuffer for %1").arg(
filename));
879 LOG(VB_GENERAL, LOG_ERR,
"Unable to open commflag DB connection");
895 LOG(VB_GENERAL, LOG_INFO,
"Enabling experimental flagging speedup (low resolution)");
908 ctx->SetPlayingInfo(program_info);
909 ctx->SetRingBuffer(tmprbuf);
925 LOG(VB_COMMFLAG, LOG_INFO,
926 QString(
"mythcommflag will flag recording "
927 "currently in progress on cardid %1")
935 LOG(VB_GENERAL, LOG_ERR,
936 "Unable to find active recorder for this "
937 "recording, realtime flagging will not be enabled.");
946 program_info,
progress, fullSpeed, jobid,
947 cfp, commDetectMethod, outputfilename, useDB);
950 std::cerr << breaksFound <<
"\n";
952 LOG(VB_GENERAL, LOG_NOTICE, QString(
"Finished, %1 break(s) found.")
962 int jobid,
const QString &outputfilename,
970 LOG(VB_GENERAL, LOG_ERR,
971 QString(
"No program data exists for channel %1 at %2")
972 .arg(chanid).arg(startstring));
980 std::cerr <<
"IN USE\n";
982 "(the program is already being flagged elsewhere)\n";
984 LOG(VB_GENERAL, LOG_ERR,
"Program is already being flagged elsewhere");
991 std::cerr <<
"MythTV Commercial Flagger, flagging commercials for:" << std::endl;
993 std::cerr <<
" " << pginfo.
GetTitle().toLocal8Bit().constData() << std::endl;
995 std::cerr <<
" " << pginfo.
GetTitle().toLocal8Bit().constData() <<
" - "
996 << pginfo.
GetSubtitle().toLocal8Bit().constData() << std::endl;
999 return FlagCommercials(&pginfo, jobid, outputfilename,
true, fullSpeed);
1003 const QString &outputfilename,
bool useDB,
1009 std::cerr <<
"MythTV Commercial Flagger, flagging commercials for:" << std::endl
1010 <<
" " <<
filename.toLatin1().constData() << std::endl;
1014 return FlagCommercials(&pginfo, jobid, outputfilename, useDB, fullSpeed);
1027 filename = QString(
"myth://Videos@%1/%2")
1032 LOG(VB_GENERAL, LOG_ERR,
1033 QString(
"Unable to find file in defined storage "
1034 "paths for JobQueue ID# %1.").arg(jobid));
1046 LOG(VB_GENERAL, LOG_ERR,
1047 QString(
"Unable to create RingBuffer for %1").arg(
filename));
1055 ctx->SetPlayingInfo(pginfo);
1056 ctx->SetRingBuffer(tmprbuf);
1057 ctx->SetPlayer(cfp);
1061 QString time = QDateTime::currentDateTime().toString(Qt::TextDate);
1062 std::cerr <<
"Rebuild started at " << qPrintable(time) << std::endl;
1073 QString time = QDateTime::currentDateTime().toString(Qt::TextDate);
1074 std::cerr <<
"Rebuild completed at " << qPrintable(time) << std::endl;
1086 std::cerr <<
"MythTV Commercial Flagger, building seek table for:" << std::endl
1087 <<
" " <<
filename.toLatin1().constData() << std::endl;
1098 std::cerr <<
"MythTV Commercial Flagger, building seek table for:" << std::endl;
1100 std::cerr <<
" " << pginfo.
GetTitle().toLocal8Bit().constData() << std::endl;
1102 std::cerr <<
" " << pginfo.
GetTitle().toLocal8Bit().constData() <<
" - "
1103 << pginfo.
GetSubtitle().toLocal8Bit().constData() << std::endl;
1134 QCoreApplication a(argc, argv);
1153 LOG(VB_GENERAL, LOG_EMERG,
"Failed to init MythContext, exiting.");
1201 QDateTime starttime;
1205 std::cerr <<
"mythcommflag: ERROR: Unable to find DB info for "
1206 <<
"JobQueue ID# " <<
jobID << std::endl;
1212 if (jobQueueCPU < 2)
1230 QCoreApplication::translate(
"(mythcommflag)",
1231 "Failed with exit status %1",
1232 "Job status").arg(ret));
1237 QCoreApplication::translate(
"(mythcommflag)",
1238 "%n commercial break(s)",
1254 std::cerr <<
"The --rebuild parameter builds the seektable for "
1255 "internal MythTV use only. It cannot be used in "
1256 "combination with --skipdb." << std::endl;
1294 query.
prepare(
"SELECT r.chanid, r.starttime, c.commmethod "
1295 "FROM recorded AS r "
1296 "LEFT JOIN channel AS c ON r.chanid=c.chanid "
1298 "ORDER BY starttime;");
1304 QDateTime starttime;
1306 while (query.
next())
1336 LOG(VB_GENERAL, LOG_ERR,
1337 "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.
static Type MythEventMessage
#define GENERIC_EXIT_OK
Exited with no error.
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.
uint64_t GetTotalFrameCount(void) const
int GetRecorderNumber(void) const
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 int SetCutList(uint chanid, const QDateTime &starttime, QString newCutList)
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)
@ COMM_DETECT_BLANK_SCENE
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
#define GENERIC_EXIT_INVALID_CMDLINE
Command line parse error.
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
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 void recordingFinished(long long totalFileSize)
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 PrintFullMap(std::ostream &out, const frm_dir_map_t *comm_breaks, bool verbose) const =0
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
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.
#define GENERIC_EXIT_NO_RECORDING_DATA
No program/recording data.
static QMap< QString, SkipType > * init_skip_types()
bool QueryCutList(frm_dir_map_t &delMap, bool loadAutosave=false) const
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.
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.
#define GENERIC_EXIT_PERMISSIONS_ERROR
File permissions error.
static int CopySkipListToCutList(uint chanid, const QDateTime &starttime)
void ApplySettingsOverride(void)
Apply all overrides to the global context.
int GetNumSetting(const QString &key, int defaultval=0)
static QString cleanup(const QString &str)
QDateTime fromString(const QString &dtstr)
Converts kFilename && kISODate formats to QDateTime.
static void streamOutCommercialBreakList(std::ostream &output, const frm_dir_map_t &commercialBreakList)
static void Init(QObject *parent=nullptr)
#define MYTH_BINARY_VERSION
Update this whenever the plug-in ABI changes.
uint GetChanID(void) const
This is the unique key used in the database to locate tuning information.
#define GENERIC_EXIT_DB_ERROR
Database error.
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
#define GENERIC_EXIT_IN_USE
Recording in use, can't flag.
uint64_t QueryLastFrameInPosMap(void) const
Returns last frame in position map or 0.
#define GENERIC_EXIT_NOT_OK
Exited with error.
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.
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()
void SaveCutList(frm_dir_map_t &delMap, bool isAutoSave=false) const
#define GENERIC_EXIT_NO_MYTHCONTEXT
No MythContext available.
static int GetMarkupList(const QString &list, uint chanid, const QDateTime &starttime)
static int ClearSkipList(uint chanid, const QDateTime &starttime)
SkipType
This is used as a bitmask.
void QueryCommBreakList(frm_dir_map_t &frames) const
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)
@ kOutputMethodEssentials
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)
bool prepare(const QString &query)
QSqlQuery::prepare() is not thread safe in Qt <= 3.3.2.
QString GetSubtitle(void) const