18 #include <QCoreApplication> 38 #include "ringbuffer.h" 52 #define LOC QString("MythCommFlag: ") 53 #define LOC_WARN QString("MythCommFlag, Warning: ") 54 #define LOC_ERR QString("MythCommFlag, Error: ") 86 QMap<QString,SkipTypes> *
tmp =
new QMap<QString,SkipTypes>;
117 QMap<QString,OutputMethod> *
tmp =
new QMap<QString,OutputMethod>;
126 if (!QFile::exists(filename))
140 QString
tmp = QString(
141 "Unable to find program info for chanid %1 @ %2")
142 .arg(chanid).arg(startstring);
143 cerr <<
tmp.toLocal8Bit().constData() << endl;
150 QString
tmp = QString(
"Job have been queued for chanid %1 @ %2")
151 .arg(chanid).arg(startstring);
152 cerr <<
tmp.toLocal8Bit().constData() << endl;
158 rebuild ?
JOB_REBUILD : 0, JOB_QUEUED, QDateTime());
164 QString
tmp = QString(
"Job Queued for chanid %1 @ %2")
165 .arg(chanid).arg(startstring);
166 cerr <<
tmp.toLocal8Bit().constData() << endl;
174 QString
tmp = QString(
"Error queueing job for chanid %1 @ %2")
175 .arg(chanid).arg(startstring);
176 cerr <<
tmp.toLocal8Bit().constData() << endl;
187 frm_dir_map_t::const_iterator it;
194 LOG(VB_GENERAL, LOG_ERR,
195 QString(
"No program data exists for channel %1 at %2")
196 .arg(chanid).arg(startstring));
201 for (it = cutlist.begin(); it != cutlist.end(); ++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");
236 newCutList.replace(QRegExp(
" "),
"");
238 QStringList tokens = newCutList.split(
",", QString::SkipEmptyParts);
240 for (
int i = 0; i < tokens.size(); i++)
242 QStringList cutpair = tokens[i].split(
"-", QString::SkipEmptyParts);
252 LOG(VB_GENERAL, LOG_ERR,
253 QString(
"No program data exists for channel %1 at %2")
254 .arg(chanid).arg(startstring));
260 LOG(VB_GENERAL, LOG_NOTICE, QString(
"Cutlist set to: %1").arg(newCutList));
268 frm_dir_map_t::const_iterator it;
276 LOG(VB_GENERAL, LOG_ERR,
277 QString(
"No program data exists for channel %1 at %2")
278 .arg(chanid).arg(startstring));
282 if (list ==
"cutlist")
287 uint64_t lastStart = 0;
288 for (it = cutlist.begin(); it != cutlist.end(); ++it)
293 if (!result.isEmpty())
295 lastStart = it.key();
296 result += QString(
"%1-").arg(lastStart);
300 if (result.isEmpty())
302 result += QString(
"%1").arg(it.key());
306 if (result.endsWith(
'-'))
309 if (lastFrame > lastStart)
310 result += QString(
"%1").arg(lastFrame);
313 if (list ==
"cutlist")
314 cout << QString(
"Cutlist: %1\n").arg(result).toLocal8Bit().constData();
317 cout << QString(
"Commercial Skip List: %1\n")
318 .arg(result).toLocal8Bit().constData();
328 output <<
"----------------------------" << endl;
330 if (commercialBreakList.empty())
333 output <<
"No breaks" << endl;
337 frm_dir_map_t::const_iterator it = commercialBreakList.begin();
338 for (; it != commercialBreakList.end(); ++it)
340 output <<
"framenum: " << it.key() <<
"\tmarktype: " << *it
346 output <<
"----------------------------" << endl;
352 uint64_t frame_count,
354 const QString &output_filename)
356 if (output_filename.isEmpty())
359 ostream *out = &cout;
360 if (output_filename !=
"-")
362 QByteArray
tmp = output_filename.toLocal8Bit();
363 out =
new fstream(
tmp.constData(), ios::app | ios::out );
371 tmp = QString(
"commercialBreakListFor: %1 on %2 @ %3")
378 tmp = QString(
"commercialBreakListFor: %1")
382 const QByteArray tmp2 =
tmp.toLocal8Bit();
383 *out << tmp2.constData() << endl;
386 *out <<
"totalframecount: " << frame_count << endl;
394 if (output_filename !=
"-")
402 qApp->processEvents();
420 QCoreApplication::translate(
"(mythcommflag)",
421 "Paused",
"Job status"));
428 QCoreApplication::translate(
"(mythcommflag)",
429 "Running",
"Job status"));
451 frm_dir_map_t::Iterator it = newCommercialMap.begin();
452 QString message =
"COMMFLAG_UPDATE ";
455 for (it = newCommercialMap.begin();
456 it != newCommercialMap.end(); ++it)
458 if (it != newCommercialMap.begin())
462 message += QString(
"%1:%2").arg(it.key())
466 LOG(VB_COMMFLAG, LOG_INFO,
467 QString(
"mythcommflag sending update: %1").arg(message));
476 MythEvent *me = static_cast<MythEvent *>(e);
477 QString message = me->
Message();
479 message = message.simplified();
480 QStringList tokens = message.split(
" ", QString::SkipEmptyParts);
482 LOG(VB_COMMFLAG, LOG_INFO,
483 QString(
"mythcommflag: Received Event: '%1'") .arg(message));
486 (tokens[0] ==
"DONE_RECORDING"))
488 int cardnum = tokens[1].toInt();
489 int filelen = tokens[2].toInt();
491 message = QString(
"mythcommflag: Received a " 492 "DONE_RECORDING event for card %1. ")
499 message +=
"Informed CommDetector that recording has finished.";
500 LOG(VB_COMMFLAG, LOG_INFO, message);
504 if ((tokens.size() >= 2) && (tokens[0] ==
"COMMFLAG_REQUEST"))
507 QDateTime recstartts;
510 message = QString(
"mythcommflag: Received a " 511 "COMMFLAG_REQUEST event for chanid %1 @ %2. ")
512 .arg(chanid).arg(recstartts.toString(
Qt::ISODate));
518 message +=
"Requested CommDetector to generate new break list.";
519 LOG(VB_COMMFLAG, LOG_INFO, message);
527 bool showPercentage,
bool fullSpeed,
int jobid,
529 const QString &outputfilename,
bool useDB)
533 commDetectMethod, showPercentage,
542 LOG(VB_COMMFLAG, LOG_INFO,
543 QString(
"mythcommflag processing JobID %1").arg(jobid));
554 QObject::connect(
commDetector, SIGNAL(statusUpdate(
const QString&)),
555 b, SLOT(relay(
const QString&)));
556 QObject::connect(
commDetector, SIGNAL(gotNewCommercialBreakList()),
561 LOG(VB_COMMFLAG, LOG_INFO,
562 "mythcommflag sending COMMFLAG_START notification");
563 QString message =
"COMMFLAG_START ";
577 comms_found = commBreakList.size() / 2;
615 if (filename.startsWith(
"myth://"))
617 RemoteFile remotefile(filename,
false,
false, 0);
622 QFile file(filename);
639 LOG(VB_GENERAL, LOG_ERR, QString(
"Couldn't find file %1, aborting.")
646 LOG(VB_GENERAL, LOG_ERR, QString(
"File %1 is zero-byte, aborting.")
665 mark_query.
prepare(
"SELECT commflagged, count(rm.type) " 667 "LEFT JOIN recordedmarkup rm ON " 668 "( r.chanid = rm.chanid AND " 669 "r.starttime = rm.starttime AND " 670 "type in (:MARK_START,:MARK_END)) " 671 "WHERE r.chanid = :CHANID AND " 672 "r.starttime = :STARTTIME " 673 "GROUP BY COMMFLAGGED;");
677 mark_query.
bindValue(
":STARTTIME", starttime);
680 mark_query.
size() > 0)
682 if (mark_query.
next())
684 int flagStatus = mark_query.
value(0).toInt();
685 int marksFound = mark_query.
value(1).toInt();
687 QString flagStatusStr =
"UNKNOWN";
688 switch (flagStatus) {
690 flagStatusStr =
"Not Flagged";
693 flagStatusStr = QString(
"Flagged with %1 breaks")
694 .arg(marksFound / 2);
697 flagStatusStr =
"Flagging";
700 flagStatusStr =
"Commercial Free";
704 LOG(VB_COMMFLAG, LOG_INFO,
705 QString(
"Status for chanid %1 @ %2 is '%3'")
707 .arg(flagStatusStr));
717 const QString &outputfilename,
bool useDB,
bool fullSpeed)
734 commDetectMethod = (
SkipTypes) commmethod.toInt(&ok);
740 QStringList list = commmethod.split(
",", QString::SkipEmptyParts);
741 QStringList::const_iterator it = list.begin();
742 for (; it != list.end(); ++it)
744 QString val = (*it).toLower();
753 cerr <<
"Failed to decode --method option '" 754 << val.toLatin1().constData()
760 commDetectMethod =
skipTypes->value(val);
762 commDetectMethod = (
SkipTypes) ((
int)commDetectMethod
776 query.
prepare(
"SELECT commmethod FROM channel " 777 "WHERE chanid = :CHANID;");
786 else if (query.
next())
795 LOG(VB_COMMFLAG, LOG_INFO,
796 QString(
"Chanid %1 is marked as being Commercial Free, " 797 "we will use the default commercial detection " 798 "method").arg(program_info->
GetChanID()));
805 LOG(VB_COMMFLAG, LOG_INFO,
806 QString(
"Using method: %1 from channel %2")
807 .arg(commDetectMethod).arg(program_info->
GetChanID()));
843 LOG(VB_GENERAL, LOG_ERR,
844 "Unable to find file in defined storage paths.");
853 LOG(VB_GENERAL, LOG_ERR,
854 QString(
"Unable to create RingBuffer for %1").arg(filename));
863 LOG(VB_GENERAL, LOG_ERR,
"Unable to open commflag DB connection");
903 LOG(VB_COMMFLAG, LOG_INFO,
904 QString(
"mythcommflag will flag recording " 905 "currently in progress on cardid %1")
913 LOG(VB_GENERAL, LOG_ERR,
914 "Unable to find active recorder for this " 915 "recording, realtime flagging will not be enabled.");
924 program_info,
progress, fullSpeed, jobid,
925 cfp, commDetectMethod, outputfilename, useDB);
928 cerr << breaksFound <<
"\n";
930 LOG(VB_GENERAL, LOG_NOTICE, QString(
"Finished, %1 break(s) found.")
940 int jobid,
const QString &outputfilename,
948 LOG(VB_GENERAL, LOG_ERR,
949 QString(
"No program data exists for channel %1 at %2")
950 .arg(chanid).arg(startstring));
960 "(the program is already being flagged elsewhere)\n";
962 LOG(VB_GENERAL, LOG_ERR,
"Program is already being flagged elsewhere");
969 cerr <<
"MythTV Commercial Flagger, flagging commercials for:" << endl;
971 cerr <<
" " << pginfo.
GetTitle().toLocal8Bit().constData() << endl;
973 cerr <<
" " << pginfo.
GetTitle().toLocal8Bit().constData() <<
" - " 974 << pginfo.
GetSubtitle().toLocal8Bit().constData() << endl;
977 return FlagCommercials(&pginfo, jobid, outputfilename,
true, fullSpeed);
981 const QString &outputfilename,
bool useDB,
987 cerr <<
"MythTV Commercial Flagger, flagging commercials for:" << endl
988 <<
" " << filename.toLatin1().constData() << endl;
992 return FlagCommercials(&pginfo, jobid, outputfilename, useDB, fullSpeed);
1005 filename = QString(
"myth://Videos@%1/%2")
1010 LOG(VB_GENERAL, LOG_ERR,
1011 QString(
"Unable to find file in defined storage " 1012 "paths for JobQueue ID# %1.").arg(jobid));
1024 LOG(VB_GENERAL, LOG_ERR,
1025 QString(
"Unable to create RingBuffer for %1").arg(filename));
1040 QString time = QDateTime::currentDateTime().toString(Qt::TextDate);
1041 cerr <<
"Rebuild started at " << qPrintable(time) << endl;
1052 QString time = QDateTime::currentDateTime().toString(Qt::TextDate);
1053 cerr <<
"Rebuild completed at " << qPrintable(time) << endl;
1065 cerr <<
"MythTV Commercial Flagger, building seek table for:" << endl
1066 <<
" " << filename.toLatin1().constData() << endl;
1077 cerr <<
"MythTV Commercial Flagger, building seek table for:" << endl;
1079 cerr <<
" " << pginfo.
GetTitle().toLocal8Bit().constData() << endl;
1081 cerr <<
" " << pginfo.
GetTitle().toLocal8Bit().constData() <<
" - " 1082 << pginfo.
GetSubtitle().toLocal8Bit().constData() << endl;
1113 QCoreApplication a(argc, argv);
1123 QList<int> signallist;
1124 signallist << SIGINT << SIGTERM << SIGSEGV << SIGABRT << SIGBUS << SIGFPE
1127 signallist << SIGRTMIN;
1139 LOG(VB_GENERAL, LOG_EMERG,
"Failed to init MythContext, exiting.");
1187 QDateTime starttime;
1191 cerr <<
"mythcommflag: ERROR: Unable to find DB info for " 1192 <<
"JobQueue ID# " <<
jobID << endl;
1198 if (jobQueueCPU < 2)
1215 QCoreApplication::translate(
"(mythcommflag)",
1216 "Failed with exit status %1",
1217 "Job status").arg(ret));
1220 QCoreApplication::translate(
"(mythcommflag)",
1221 "%n commercial break(s)",
1236 cerr <<
"The --rebuild parameter builds the seektable for " 1237 "internal MythTV use only. It cannot be used in " 1238 "combination with --skipdb." << endl;
1259 pginfo.GetRecordingStartTime(),
1263 pginfo.GetRecordingStartTime(),
1272 query.
prepare(
"SELECT r.chanid, r.starttime, c.commmethod " 1273 "FROM recorded AS r " 1274 "LEFT JOIN channel AS c ON r.chanid=c.chanid " 1276 "ORDER BY starttime;");
1282 QDateTime starttime;
1284 while (query.
next())
1314 LOG(VB_GENERAL, LOG_ERR,
1315 "No valid combination of command inputs received.");
#define GENERIC_EXIT_DB_ERROR
Database error.
bool next(void)
Wrap QSqlQuery::next() so we can display the query results.
SkipTypes
This is used as a bitmask.
Startup context for MythTV.
static int SetCutList(uint chanid, QDateTime starttime, QString newCutList)
static int GetMarkupList(QString list, uint chanid, QDateTime starttime)
void bindValue(const QString &placeholder, const QVariant &val)
static int FlagCommercials(ProgramInfo *program_info, int jobid, const QString &outputfilename, bool useDB, bool fullSpeed)
static void commDetectorGotNewCommercialBreakList(void)
#define GENERIC_EXIT_OK
Exited with no error.
virtual uint64_t GetFilesize(void) const
void RegisterFileForWrite(const QString &file, uint64_t size=0LL)
#define GENERIC_EXIT_PERMISSIONS_ERROR
File permissions error.
void SetPathname(const QString &) const
static void incomingCustomEvent(QEvent *e)
static Type MythEventMessage
void SaveCommFlagged(CommFlagStatus flag)
Set "commflagged" field in "recorded" table to "flag".
QSqlQuery wrapper that fetches a DB connection from the connection pool.
bool myth_ioprio(int)
Allows setting the I/O priority of the current process/thread.
void PrintHelp(void) const
Print command line option help.
void SaveMarkupFlag(MarkTypes type) const
Clears the specified flag, then if sets it.
bool QueryCutList(frm_dir_map_t &, bool loadAutosave=false) const
QString GetTitle(void) const
Default UTC, "yyyyMMddhhmmss".
bool ConnectToMasterServer(bool blockingClient=true, bool openEventSocket=true)
static void Init(QList< int > &signallist, QObject *parent=nullptr)
static bool ChangeJobStatus(int jobID, int newStatus, QString comment="")
void SetPlayer(MythPlayer *new_player)
static enum JobCmds GetJobCmd(int jobID)
Holds information on a TV Program one might wish to record.
void SetRingBuffer(RingBuffer *buf)
const char * kFlaggerInUseID
virtual void GetCommercialBreakList(frm_dir_map_t &comms)=0
static void UpdateFileSize(ProgramInfo *program_info)
void QueryCommBreakList(frm_dir_map_t &) const
QMap< uint64_t, MarkTypes > frm_dir_map_t
Frame # -> Mark map.
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
static RingBuffer * Create(const QString &xfilename, bool write, bool usereadahead=true, int timeout_ms=kDefaultOpenTimeout, bool stream_only=false)
Creates a RingBuffer instance.
virtual void requestCommBreakMapUpdate(void)
void SaveCommBreakList(frm_dir_map_t &) const
static void streamOutCommercialBreakList(ostream &output, const frm_dir_map_t &commercialBreakList)
void SetRecorder(RemoteEncoder *rec)
bool toBool(QString key) const
Returns stored QVariant as a boolean.
MythContext * gContext
This global variable contains the MythContext instance for the application.
uint64_t QueryLastFrameInPosMap(void) const
Returns last frame in position map or 0.
bool SetValue(const QString &key, QVariant value)
Set a new stored value for an existing argument definition, or spawn a new definition store value in.
#define GENERIC_EXIT_IN_USE
Recording in use, can't flag.
static bool IsMarked(uint chanid, QDateTime starttime)
int main(int argc, char *argv[])
unsigned sleep(unsigned int x)
QMap< QString, OutputMethod > * outputTypes
void SendMessage(const QString &message)
int GetAutoRunJobs(void) const
Returns a bitmap of which jobs are attached to this RecordingInfo.
QDateTime GetScheduledStartTime(void) const
The scheduled start time of program.
QVariant value(int i) const
static QString get_filename(ProgramInfo *program_info)
QString MakeUniqueKey(void) const
Creates a unique string that can be used to identify an existing recording.
void ApplySettingsOverride(void)
Apply all overrides to the global context.
Holds information on recordings and videos.
static void commDetectorBreathe()
void SetPlayingInfo(const ProgramInfo *info)
assign programinfo to the context
bool Init(const bool gui=true, const bool promptForBackend=false, const bool bypassAutoDiscovery=false, const bool ignoreDB=false)
virtual void SaveFilesize(uint64_t fsize)
Sets recording file size in database, and sets "filesize" field.
This class is used as a container for messages.
bool RebuildSeekTable(bool showPercentage=true, StatusCallback cb=nullptr, void *cbData=nullptr)
static bool QueueJob(int jobType, uint chanid, const QDateTime &recstartts, QString args="", QString comment="", QString host="", int flags=0, int status=JOB_QUEUED, QDateTime schedruntime=QDateTime())
static bool GetJobInfoFromID(int jobID, int &jobType, uint &chanid, QDateTime &recstartts)
#define GENERIC_EXIT_NO_RECORDING_DATA
No program/recording data.
static int DoFlagCommercials(ProgramInfo *program_info, bool showPercentage, bool fullSpeed, int jobid, MythCommFlagPlayer *cfp, enum SkipTypes commDetectMethod, const QString &outputfilename, bool useDB)
static bool ExtractKey(const QString &uniquekey, uint &chanid, QDateTime &recstartts)
Extracts chanid and recstartts from a unique key generated by MakeUniqueKey().
QDateTime current(bool stripped)
Returns current Date and Time in UTC.
QString GetSubtitle(void) const
bool isActive(void) const
CommDetectorBase * commDetector
static void load(const QString &module_name)
Load a QTranslator for the user's preferred language.
Abstract base class for all CommDetectors.
static bool ChangeJobComment(int jobID, QString comment="")
static bool testDBConnection()
Checks DB connection + login (login info via Mythcontext)
static int RebuildSeekTable(ProgramInfo *pginfo, int jobid, bool writefile=false)
static QMap< QString, OutputMethod > * init_output_types()
QString toString(QString key) const
Returns stored QVariant as a QString, falling to default if not provided.
static MSqlQueryInfo InitCon(ConnectionReuse=kNormalConnection)
Only use this in combination with MSqlQuery constructor.
QDateTime GetScheduledEndTime(void) const
The scheduled end time of the program.
void SaveTotalDuration(void)
MythCommFlagCommandLineParser cmdline
QString toString(const QDateTime &raw_dt, uint format)
Returns formatted string representing the time.
QDateTime toDateTime(QString key) const
Returns stored QVariant as a QDateTime, falling to default if not provided.
static bool IsJobRunning(int jobType, uint chanid, const QDateTime &recstartts)
long long GetFileSize(void) const
GetFileSize: returns the remote file's size at the time it was first opened Will query the server in ...
#define MYTH_APPNAME_MYTHCOMMFLAG
void UnregisterFileForWrite(const QString &file)
void SetPlayerInfo(TV *tv, QWidget *widget, PlayerContext *ctx)
void SaveCutList(frm_dir_map_t &, bool isAutoSave=false) const
int GetNumSetting(const QString &key, int defaultval=0)
bool prepare(const QString &query)
QSqlQuery::prepare() is not thread safe in Qt <= 3.3.2.
ProgramInfo * global_program_info
#define LOG(_MASK_, _LEVEL_, _STRING_)
QMap< QString, SkipTypes > * skipTypes
virtual void recordingFinished(long long totalFileSize)
virtual void PrintFullMap(ostream &out, const frm_dir_map_t *comm_breaks, bool verbose) const =0
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)
static int QueueCommFlagJob(uint chanid, QDateTime starttime, bool rebuild)
virtual bool Parse(int argc, const char *const *argv)
Loop through argv and populate arguments with values.
static bool DoesFileExist(ProgramInfo *program_info)
uint GetChanID(void) const
This is the unique key used in the database to locate tuning information.
OutputMethod outputMethod
static void cleanup(VideoFilter *filter)
int GetRecorderNumber(void) const
QString GetPlaybackURL(bool checkMaster=false, bool forceCheckLocal=false) const
Returns filename or URL to be used to play back this recording.
uint64_t GetTotalFrameCount(void) const
static void commDetectorStatusUpdate(const QString &status)
static int CopySkipListToCutList(uint chanid, QDateTime starttime)
#define MYTH_BINARY_VERSION
Update this whenever the plug-in ABI changes.
static enum JobFlags GetJobFlags(int jobID)
QDateTime GetRecordingStartTime(void) const
Approximate time the recording started.
QDateTime GetRecordingEndTime(void) const
Approximate time the recording should have ended, did end, or is intended to end.
int toInt(QString key) const
Returns stored QVariant as an integer, falling to default if not provided.
bool exec(void)
Wrap QSqlQuery::exec() so we can display SQL.
Implements a file/stream reader/writer.
int ConfigureLogging(QString mask="general", unsigned int progress=0)
Read in logging options and initialize the logging interface.
#define GENERIC_EXIT_NO_MYTHCONTEXT
No MythContext available.
static void SetHandler(int signal, SigHandlerFunc handler)
static void DBError(const QString &where, const MSqlQuery &query)
#define GENERIC_EXIT_INVALID_CMDLINE
Command line parse error.
static qint64 GetFileSize(ProgramInfo *program_info)
const QString & Message() const
#define GENERIC_EXIT_NOT_OK
Exited with error.
QString GetHostName(void)
QDateTime fromString(const QString &dtstr)
Converts kFilename && kISODate formats to QDateTime.
QString GetPathname(void) const
CommDetectorBase * makeCommDetector(SkipType commDetectMethod, bool showProgress, bool fullSpeed, MythPlayer *player, int chanid, const QDateTime &startedAt, const QDateTime &stopsAt, const QDateTime &recordingStartedAt, const QDateTime &recordingStopsAt, bool useDB)
void SetWatchingRecording(bool mode)
virtual void deleteLater(void)
static QMap< QString, SkipTypes > * init_skip_types()
void PrintVersion(void) const
Print application version information.
uint toUInt(QString key) const
Returns stored QVariant as an unsigned integer, falling to default if not provided.
RemoteEncoder * RemoteGetExistingRecorder(const ProgramInfo *pginfo)
static int ClearSkipList(uint chanid, QDateTime starttime)