Пример #1
0
static int QueueCommFlagJob(uint chanid, QDateTime starttime, bool rebuild)
{
    QString startstring = MythDate::toString(starttime, MythDate::kFilename);
    const ProgramInfo pginfo(chanid, starttime);

    if (!pginfo.GetChanID())
    {
        if (progress)
        {
            QString tmp = QString(
                "Unable to find program info for chanid %1 @ %2")
                .arg(chanid).arg(startstring);
            cerr << tmp.toLocal8Bit().constData() << endl;
        }
        return GENERIC_EXIT_NO_RECORDING_DATA;
    }

    if (cmdline.toBool("dryrun"))
    {
        QString tmp = QString("Job have been queued for chanid %1 @ %2")
                        .arg(chanid).arg(startstring);
        cerr << tmp.toLocal8Bit().constData() << endl;
        return GENERIC_EXIT_OK;
    }

    bool result = JobQueue::QueueJob(JOB_COMMFLAG,
        pginfo.GetChanID(), pginfo.GetRecordingStartTime(), "", "", "",
        rebuild ? JOB_REBUILD : 0, JOB_QUEUED, QDateTime());

    if (result)
    {
        if (progress)
        {
            QString tmp = QString("Job Queued for chanid %1 @ %2")
                .arg(chanid).arg(startstring);
            cerr << tmp.toLocal8Bit().constData() << endl;
        }
        return GENERIC_EXIT_OK;
    }
    else
    {
        if (progress)
        {
            QString tmp = QString("Error queueing job for chanid %1 @ %2")
                .arg(chanid).arg(startstring);
            cerr << tmp.toLocal8Bit().constData() << endl;
        }
        return GENERIC_EXIT_DB_ERROR;
    }

    return GENERIC_EXIT_OK;
}
Пример #2
0
static int FlagCommercials(ProgramInfo *program_info, int jobid,
            const QString &outputfilename, bool useDB, bool fullSpeed)
{
    global_program_info = program_info;

    int breaksFound = 0;

    // configure commercial detection method
    SkipTypes commDetectMethod = (SkipTypes)gCoreContext->GetNumSetting(
                                    "CommercialSkipMethod", COMM_DETECT_ALL);

    if (cmdline.toBool("commmethod"))
    {
        // pull commercial detection method from command line
        QString commmethod = cmdline.toString("commmethod");

        // assume definition as integer value
        bool ok = true;
        commDetectMethod = (SkipTypes) commmethod.toInt(&ok);
        if (!ok)
        {
            // not an integer, attempt comma separated list
            commDetectMethod = COMM_DETECT_UNINIT;
            QMap<QString, SkipTypes>::const_iterator sit;

            QStringList list = commmethod.split(",", QString::SkipEmptyParts);
            QStringList::const_iterator it = list.begin();
            for (; it != list.end(); ++it)
            {
                QString val = (*it).toLower();
                if (val == "off")
                {
                    commDetectMethod = COMM_DETECT_OFF;
                    break;
                }

                if (!skipTypes->contains(val))
                {
                    cerr << "Failed to decode --method option '"
                         << val.toLatin1().constData()
                         << "'" << endl;
                    return GENERIC_EXIT_INVALID_CMDLINE;
                }

                if (commDetectMethod == COMM_DETECT_UNINIT) {
                    commDetectMethod = (SkipTypes) skipTypes->value(val);
                } else {
                    commDetectMethod = (SkipTypes) ((int)commDetectMethod
                                                  | (int)skipTypes->value(val));
                }
            }

        }
        if (commDetectMethod == COMM_DETECT_UNINIT)
            return GENERIC_EXIT_INVALID_CMDLINE;
    }
    else if (useDB)
    {
        // if not manually specified, and we have a database to access
        // pull the commflag type from the channel
        MSqlQuery query(MSqlQuery::InitCon());
        query.prepare("SELECT commmethod FROM channel "
                        "WHERE chanid = :CHANID;");
        query.bindValue(":CHANID", program_info->GetChanID());

        if (!query.exec())
        {
            // if the query fails, return with an error
            commDetectMethod = COMM_DETECT_UNINIT;
            MythDB::DBError("FlagCommercials", query);
        }
        else if (query.next())
        {
            commDetectMethod = (enum SkipTypes)query.value(0).toInt();
            if (commDetectMethod == COMM_DETECT_COMMFREE)
            {
                // if the channel is commercial free, drop to the default instead
                commDetectMethod =
                        (enum SkipTypes)gCoreContext->GetNumSetting(
                                    "CommercialSkipMethod", COMM_DETECT_ALL);
                LOG(VB_COMMFLAG, LOG_INFO,
                        QString("Chanid %1 is marked as being Commercial Free, "
                                "we will use the default commercial detection "
                                "method").arg(program_info->GetChanID()));
            }
            else if (commDetectMethod == COMM_DETECT_UNINIT)
                // no value set, so use the database default
                commDetectMethod =
                        (enum SkipTypes)gCoreContext->GetNumSetting(
                                     "CommercialSkipMethod", COMM_DETECT_ALL);
            LOG(VB_COMMFLAG, LOG_INFO,
                QString("Using method: %1 from channel %2")
                    .arg(commDetectMethod).arg(program_info->GetChanID()));
        }

    }
    else if (!useDB)
    {
        // default to a cheaper method for debugging purposes
        commDetectMethod = COMM_DETECT_BLANK;
    }

    // if selection has failed, or intentionally disabled, drop out
    if (commDetectMethod == COMM_DETECT_UNINIT)
        return GENERIC_EXIT_NOT_OK;
    else if (commDetectMethod == COMM_DETECT_OFF)
        return GENERIC_EXIT_OK;

    frm_dir_map_t blanks;
    recorder = NULL;

/*
 * is there a purpose to this not fulfilled by --getskiplist?
    if (onlyDumpDBCommercialBreakList)
    {
        frm_dir_map_t commBreakList;
        program_info->QueryCommBreakList(commBreakList);

        print_comm_flag_output(program_info, commBreakList,
                               0, NULL, outputfilename);

        global_program_info = NULL;
        return GENERIC_EXIT_OK;
    }
*/

    if (!DoesFileExist(program_info))
    {
        LOG(VB_GENERAL, LOG_ERR,
            "Unable to find file in defined storage paths.");
        return GENERIC_EXIT_PERMISSIONS_ERROR;
    }

    QString filename = get_filename(program_info);

    RingBuffer *tmprbuf = RingBuffer::Create(filename, false);
    if (!tmprbuf)
    {
        LOG(VB_GENERAL, LOG_ERR,
            QString("Unable to create RingBuffer for %1").arg(filename));
        global_program_info = NULL;
        return GENERIC_EXIT_PERMISSIONS_ERROR;
    }

    if (useDB)
    {
        if (!MSqlQuery::testDBConnection())
        {
            LOG(VB_GENERAL, LOG_ERR, "Unable to open commflag DB connection");
            delete tmprbuf;
            global_program_info = NULL;
            return GENERIC_EXIT_DB_ERROR;
        }
    }

    PlayerFlags flags = (PlayerFlags)(kAudioMuted   |
                                      kVideoIsNull  |
                                      kDecodeLowRes |
                                      kDecodeSingleThreaded |
                                      kDecodeNoLoopFilter |
                                      kNoITV);
    /* blank detector needs to be only sample center for this optimization. */
    if ((COMM_DETECT_BLANKS  == commDetectMethod) ||
        (COMM_DETECT_2_BLANK == commDetectMethod))
    {
        flags = (PlayerFlags) (flags | kDecodeFewBlocks);
    }

    MythCommFlagPlayer *cfp = new MythCommFlagPlayer(flags);
    PlayerContext *ctx = new PlayerContext(kFlaggerInUseID);
    ctx->SetPlayingInfo(program_info);
    ctx->SetRingBuffer(tmprbuf);
    ctx->SetPlayer(cfp);
    cfp->SetPlayerInfo(NULL, NULL, ctx);

    if (useDB)
    {
        if (program_info->GetRecordingEndTime() > MythDate::current())
        {
            gCoreContext->ConnectToMasterServer();

            recorder = RemoteGetExistingRecorder(program_info);
            if (recorder && (recorder->GetRecorderNumber() != -1))
            {
                recorderNum =  recorder->GetRecorderNumber();
                watchingRecording = true;
                ctx->SetRecorder(recorder);

                LOG(VB_COMMFLAG, LOG_INFO,
                    QString("mythcommflag will flag recording "
                            "currently in progress on cardid %1")
                        .arg(recorderNum));
            }
            else
            {
                recorderNum = -1;
                watchingRecording = false;

                LOG(VB_GENERAL, LOG_ERR,
                        "Unable to find active recorder for this "
                        "recording, realtime flagging will not be enabled.");
            }
            cfp->SetWatchingRecording(watchingRecording);
        }
    }

    // TODO: Add back insertion of job if not in jobqueue

    breaksFound = DoFlagCommercials(
        program_info, progress, fullSpeed, jobid,
        cfp, commDetectMethod, outputfilename, useDB);

    if (progress)
        cerr << breaksFound << "\n";

    LOG(VB_GENERAL, LOG_NOTICE, QString("Finished, %1 break(s) found.")
        .arg(breaksFound));

    delete ctx;
    global_program_info = NULL;

    return breaksFound;
}
Пример #3
0
int main(int argc, char *argv[])
{
    int result = GENERIC_EXIT_OK;

//    QString allStart = "19700101000000";
//    QString allEnd   = MythDate::current().toString("yyyyMMddhhmmss");
    int jobType = JOB_NONE;

    if (!cmdline.Parse(argc, argv))
    {
        cmdline.PrintHelp();
        return GENERIC_EXIT_INVALID_CMDLINE;
    }

    if (cmdline.toBool("showhelp"))
    {
        cmdline.PrintHelp();
        return GENERIC_EXIT_OK;
    }

    if (cmdline.toBool("showversion"))
    {
        cmdline.PrintVersion();
        return GENERIC_EXIT_OK;
    }

    QCoreApplication a(argc, argv);
    QCoreApplication::setApplicationName(MYTH_APPNAME_MYTHCOMMFLAG);
    int retval = cmdline.ConfigureLogging("general",
                                          !cmdline.toBool("noprogress"));
    if (retval != GENERIC_EXIT_OK)
        return retval;

    CleanupGuard callCleanup(cleanup);

#ifndef _WIN32
    QList<int> signallist;
    signallist << SIGINT << SIGTERM << SIGSEGV << SIGABRT << SIGBUS << SIGFPE
               << SIGILL;
#if ! CONFIG_DARWIN
    signallist << SIGRTMIN;
#endif
    SignalHandler::Init(signallist);
    signal(SIGHUP, SIG_IGN);
#endif

    gContext = new MythContext(MYTH_BINARY_VERSION);
    if (!gContext->Init( false, /*use gui*/
                         false, /*prompt for backend*/
                         false, /*bypass auto discovery*/
                         cmdline.toBool("skipdb"))) /*ignoreDB*/
    {
        LOG(VB_GENERAL, LOG_EMERG, "Failed to init MythContext, exiting.");
        return GENERIC_EXIT_NO_MYTHCONTEXT;
    }
    cmdline.ApplySettingsOverride();

    MythTranslation::load("mythfrontend");

    if (cmdline.toBool("outputmethod"))
    {
        QString om = cmdline.toString("outputmethod");
        if (outputTypes->contains(om))
            outputMethod = outputTypes->value(om);
    }
    
    if (cmdline.toBool("chanid") && cmdline.toBool("starttime"))
    {
        // operate on a recording in the database
        uint chanid = cmdline.toUInt("chanid");
        QDateTime starttime = cmdline.toDateTime("starttime");

        if (cmdline.toBool("clearskiplist"))
            return ClearSkipList(chanid, starttime);
        if (cmdline.toBool("gencutlist"))
            return CopySkipListToCutList(chanid, starttime);
        if (cmdline.toBool("clearcutlist"))
            return SetCutList(chanid, starttime, "");
        if (cmdline.toBool("setcutlist"))
            return SetCutList(chanid, starttime, cmdline.toString("setcutlist"));
        if (cmdline.toBool("getcutlist"))
            return GetMarkupList("cutlist", chanid, starttime);
        if (cmdline.toBool("getskiplist"))
            return GetMarkupList("commflag", chanid, starttime);

        // TODO: check for matching jobid
        // create temporary id to operate off of if not

        if (cmdline.toBool("queue"))
            QueueCommFlagJob(chanid, starttime, cmdline.toBool("rebuild"));
        else if (cmdline.toBool("rebuild"))
            result = RebuildSeekTable(chanid, starttime, -1);
        else
            result = FlagCommercials(chanid, starttime, -1,
                                     cmdline.toString("outputfile"), true);
    }
    else if (cmdline.toBool("jobid"))
    {
        jobID = cmdline.toInt("jobid");
        uint chanid;
        QDateTime starttime;

        if (!JobQueue::GetJobInfoFromID(jobID, jobType, chanid, starttime))
        {
            cerr << "mythcommflag: ERROR: Unable to find DB info for "
                 << "JobQueue ID# " << jobID << endl;
            return GENERIC_EXIT_NO_RECORDING_DATA;
        }
        force = true;
        int jobQueueCPU = gCoreContext->GetNumSetting("JobQueueCPU", 0);

        if (jobQueueCPU < 2)
        {
            myth_nice(17);
            myth_ioprio((0 == jobQueueCPU) ? 8 : 7);
        }

        progress = false;

        int ret = 0;

        if (JobQueue::GetJobFlags(jobID) & JOB_REBUILD)
            RebuildSeekTable(chanid, starttime, jobID);
        else
            ret = FlagCommercials(chanid, starttime, jobID, "", jobQueueCPU != 0);

        if (ret > GENERIC_EXIT_NOT_OK)
            JobQueue::ChangeJobStatus(jobID, JOB_ERRORED, 
                QCoreApplication::translate("(mythcommflag)",
                                            "Failed with exit status %1",
                                            "Job status").arg(ret));
        else
            JobQueue::ChangeJobStatus(jobID, JOB_FINISHED,
                QCoreApplication::translate("(mythcommflag)",
                                            "%n commercial break(s)",
                                            "Job status",
                                            QCoreApplication::UnicodeUTF8,
                                            ret));
    }
    else if (cmdline.toBool("video"))
    {
        // build skiplist for video file
        return RebuildSeekTable(cmdline.toString("video"), -1);
    }
    else if (cmdline.toBool("file"))
    {
        if (cmdline.toBool("skipdb"))
        {
            if (cmdline.toBool("rebuild"))
            {
                cerr << "The --rebuild parameter builds the seektable for "
                        "internal MythTV use only. It cannot be used in "
                        "combination with --skipdb." << endl;
                return GENERIC_EXIT_INVALID_CMDLINE;
            }

            if (!cmdline.toBool("outputfile"))
                cmdline.SetValue("outputfile", "-");

            // perform commercial flagging on file outside the database
            FlagCommercials(cmdline.toString("file"), -1,
                            cmdline.toString("outputfile"),
                            !cmdline.toBool("skipdb"),
                            true);
        }
        else
        {
            ProgramInfo pginfo(cmdline.toString("file"));
            // pass chanid and starttime
            // inefficient, but it lets the other function
            // handle sanity checking
            if (cmdline.toBool("rebuild"))
                result = RebuildSeekTable(pginfo.GetChanID(),
                                          pginfo.GetRecordingStartTime(),
                                          -1);
            else
                result = FlagCommercials(pginfo.GetChanID(),
                                         pginfo.GetRecordingStartTime(),
                                         -1, cmdline.toString("outputfile"),
                                         true);
        }
    }
    else if (cmdline.toBool("queue"))
    {
        // run flagging for all recordings with no skiplist
        MSqlQuery query(MSqlQuery::InitCon());
        query.prepare("SELECT r.chanid, r.starttime, c.commmethod "
                        "FROM recorded AS r "
                   "LEFT JOIN channel AS c ON r.chanid=c.chanid "
//                     "WHERE startime >= :STARTTIME AND endtime <= :ENDTIME "
                    "ORDER BY starttime;");
        //query.bindValue(":STARTTIME", allStart);
        //query.bindValue(":ENDTIME", allEnd);

        if (query.exec() && query.isActive() && query.size() > 0)
        {
            QDateTime starttime;
            uint chanid;

            while (query.next())
            {
                starttime = MythDate::fromString(query.value(1).toString());
                chanid = query.value(0).toUInt();

                if (!cmdline.toBool("force") && !cmdline.toBool("rebuild"))
                {
                    // recording is already flagged
                    if (IsMarked(chanid, starttime))
                        continue;

                    // channel is marked as commercial free
                    if (query.value(2).toInt() == COMM_DETECT_COMMFREE)
                        continue;

                    // recording rule did not enable commflagging
#if 0
                    RecordingInfo recinfo(chanid, starttime);
                    if (!(recinfo.GetAutoRunJobs() & JOB_COMMFLAG))
                        continue;
#endif
                }

                QueueCommFlagJob(chanid, starttime, cmdline.toBool("rebuild"));
            }
        }

    }
    else
    {
        LOG(VB_GENERAL, LOG_ERR,
            "No valid combination of command inputs received.");
        cmdline.PrintHelp();
        return GENERIC_EXIT_INVALID_CMDLINE;
    }

    return result;
}
Пример #4
0
int main(int argc, char *argv[])
{
    int result = GENERIC_EXIT_OK;

//    QString allStart = "19700101000000";
//    QString allEnd   = MythDate::current().toString("yyyyMMddhhmmss");
    int jobType = JOB_NONE;

    if (!cmdline.Parse(argc, argv))
    {
        cmdline.PrintHelp();
        return GENERIC_EXIT_INVALID_CMDLINE;
    }

    if (cmdline.toBool("showhelp"))
    {
        cmdline.PrintHelp();
        return GENERIC_EXIT_OK;
    }

    if (cmdline.toBool("showversion"))
    {
        cmdline.PrintVersion();
        return GENERIC_EXIT_OK;
    }

    QCoreApplication a(argc, argv);
    QCoreApplication::setApplicationName(MYTH_APPNAME_MYTHCOMMFLAG);
    int retval = cmdline.ConfigureLogging("general",
                                          !cmdline.toBool("noprogress"));
    if (retval != GENERIC_EXIT_OK)
        return retval;

    CleanupGuard callCleanup(cleanup);

#ifndef _WIN32
    QList<int> signallist;
    signallist << SIGINT << SIGTERM << SIGSEGV << SIGABRT << SIGBUS << SIGFPE
               << SIGILL;
#if ! CONFIG_DARWIN
    signallist << SIGRTMIN;
#endif
    SignalHandler::Init(signallist);
    signal(SIGHUP, SIG_IGN);
#endif

    gContext = new MythContext(MYTH_BINARY_VERSION);
    if (!gContext->Init( false, /*use gui*/
                         false, /*prompt for backend*/
                         false, /*bypass auto discovery*/
                         cmdline.toBool("skipdb"))) /*ignoreDB*/
    {
        LOG(VB_GENERAL, LOG_EMERG, "Failed to init MythContext, exiting.");
        return GENERIC_EXIT_NO_MYTHCONTEXT;
    }
    cmdline.ApplySettingsOverride();

    MythTranslation::load("mythfrontend");

    if (cmdline.toBool("outputmethod"))
    {
        QString om = cmdline.toString("outputmethod");
        if (outputTypes->contains(om))
            outputMethod = outputTypes->value(om);
    }
    
    if (cmdline.toBool("chanid") && cmdline.toBool("starttime"))
    {
        // operate on a recording in the database
        uint chanid = cmdline.toUInt("chanid");
        QDateTime starttime = cmdline.toDateTime("starttime");

        if (cmdline.toBool("clearskiplist"))
            return ClearSkipList(chanid, starttime);
        if (cmdline.toBool("gencutlist"))
            return CopySkipListToCutList(chanid, starttime);
        if (cmdline.toBool("clearcutlist"))
            return SetCutList(chanid, starttime, "");
        if (cmdline.toBool("setcutlist"))
            return SetCutList(chanid, starttime, cmdline.toString("setcutlist"));
        if (cmdline.toBool("getcutlist"))
            return GetMarkupList("cutlist", chanid, starttime);
        if (cmdline.toBool("getskiplist"))
            return GetMarkupList("commflag", chanid, starttime);

        // TODO: check for matching jobid
        // create temporary id to operate off of if not

        if (cmdline.toBool("queue"))
            QueueCommFlagJob(chanid, starttime, cmdline.toBool("rebuild"));
        else if (cmdline.toBool("rebuild"))
            result = RebuildSeekTable(chanid, starttime, -1);
        else
            result = FlagCommercials(chanid, starttime, -1,
                                     cmdline.toString("outputfile"), true);
    }
    else if (cmdline.toBool("jobid"))
    {
        jobID = cmdline.toInt("jobid");
        uint chanid;
        QDateTime starttime;

        if (!JobQueue::GetJobInfoFromID(jobID, jobType, chanid, starttime))
        {
            cerr << "mythcommflag: ERROR: Unable to find DB info for "
                 << "JobQueue ID# " << jobID << endl;
            return GENERIC_EXIT_NO_RECORDING_DATA;
        }
        force = true;
        int jobQueueCPU = gCoreContext->GetNumSetting("JobQueueCPU", 0);

        if (jobQueueCPU < 2)
        {
            myth_nice(17);
            myth_ioprio((0 == jobQueueCPU) ? 8 : 7);
        }

        progress = false;

        int ret = 0;

        if (JobQueue::GetJobFlags(jobID) & JOB_REBUILD)
            RebuildSeekTable(chanid, starttime, jobID);
        else
            ret = FlagCommercials(chanid, starttime, jobID, "", jobQueueCPU != 0);

        if (ret > GENERIC_EXIT_NOT_OK)
            JobQueue::ChangeJobStatus(jobID, JOB_ERRORED, 
                QCoreApplication::translate("(mythcommflag)",
                                            "Failed with exit status %1",
                                            "Job status").arg(ret));
        else
            JobQueue::ChangeJobStatus(jobID, JOB_FINISHED,
#if QT_VERSION < 0x050000
                QCoreApplication::translate("(mythcommflag)",
                                            "%n commercial break(s)",
                                            "Job status",
                                            QCoreApplication::UnicodeUTF8,
                                            ret));
#else
                QCoreApplication::translate("(mythcommflag)",
                                            "%n commercial break(s)",
                                            "Job status",
                                            ret));
#endif
    }
Пример #5
0
int main(int argc, char *argv[])
{
    bool isVideo = false;
    int result = GENERIC_EXIT_OK;

    QString filename;
    QString outputfilename = QString::null;

    QDateTime starttime;
    QString allStart = "19700101000000";
    QString allEnd   = QDateTime::currentDateTime().toString("yyyyMMddhhmmss");
    int jobType = JOB_NONE;
    QDir fullfile;
    QString newCutList = QString::null;

    if (!cmdline.Parse(argc, argv))
    {
        cmdline.PrintHelp();
        return GENERIC_EXIT_INVALID_CMDLINE;
    }

    if (cmdline.toBool("showhelp"))
    {
        cmdline.PrintHelp();
        return GENERIC_EXIT_OK;
    }

    if (cmdline.toBool("showversion"))
    {
        cmdline.PrintVersion();
        return GENERIC_EXIT_OK;
    }

    QCoreApplication a(argc, argv);
    QCoreApplication::setApplicationName(MYTH_APPNAME_MYTHCOMMFLAG);
    int retval;
    if ((retval = cmdline.ConfigureLogging(
                        "important general",
                        !cmdline.toBool("noprogress"))) != GENERIC_EXIT_OK)
        return retval;

    CleanupGuard callCleanup(cleanup);
    gContext = new MythContext(MYTH_BINARY_VERSION);
    if (!gContext->Init( false, /*use gui*/
                         false, /*prompt for backend*/
                         false, /*bypass auto discovery*/
                         cmdline.toBool("skipdb"))) /*ignoreDB*/
    {   
        LOG(VB_GENERAL, LOG_EMERG, "Failed to init MythContext, exiting.");
        return GENERIC_EXIT_NO_MYTHCONTEXT;
    }
    cmdline.ApplySettingsOverride();
    
    MythTranslation::load("mythfrontend");

    if (cmdline.toBool("chanid") && cmdline.toBool("starttime"))
    {
        // operate on a recording in the database
        uint chanid = cmdline.toUInt("chanid");
        QDateTime starttime = cmdline.toDateTime("starttime");

        if (cmdline.toBool("clearskiplist"))
            return ClearSkipList(chanid, starttime);
        if (cmdline.toBool("gencutlist"))
            return CopySkipListToCutList(chanid, starttime);
        if (cmdline.toBool("clearcutlist"))
            return SetCutList(chanid, starttime, "");
        if (cmdline.toBool("setcutlist"))
            return SetCutList(chanid, starttime, cmdline.toString("setcutlist"));
        if (cmdline.toBool("getcutlist"))
            return GetMarkupList("cutlist", chanid, starttime);
        if (cmdline.toBool("getskiplist"))
            return GetMarkupList("commflag", chanid, starttime);

        // TODO: check for matching jobid
        // create temporary id to operate off of if not

        if (cmdline.toBool("queue"))
            QueueCommFlagJob(chanid, starttime, cmdline.toBool("rebuild"));
        else if (cmdline.toBool("rebuild"))
            result = RebuildSeekTable(chanid, starttime, -1);
        else
            result = FlagCommercials(chanid, starttime, -1, "");
    }
    else if (cmdline.toBool("jobid"))
    {
        jobID = cmdline.toInt("jobid");
        uint chanid;
        QDateTime starttime;

        if (!JobQueue::GetJobInfoFromID(jobID, jobType, chanid, starttime))
        {
            cerr << "mythcommflag: ERROR: Unable to find DB info for "
                 << "JobQueue ID# " << jobID << endl;
            return GENERIC_EXIT_NO_RECORDING_DATA;
        }
        inJobQueue = true;
        force = true;
        int jobQueueCPU = gCoreContext->GetNumSetting("JobQueueCPU", 0);

        if (jobQueueCPU < 2)
        {
            myth_nice(17);
            myth_ioprio((0 == jobQueueCPU) ? 8 : 7);
        }

        fullSpeed = jobQueueCPU != 0;

        progress = false;
        isVideo = false;

        int ret = 0;

        if (JobQueue::GetJobFlags(jobID) && JOB_REBUILD)
            RebuildSeekTable(chanid, starttime, jobID);
        else
            ret = FlagCommercials(chanid, starttime, jobID, "");

        if (ret > GENERIC_EXIT_NOT_OK)
            JobQueue::ChangeJobStatus(jobID, JOB_ERRORED,
                        QString("Failed with exit status %1").arg(ret));
        else
            JobQueue::ChangeJobStatus(jobID, JOB_FINISHED,
                        QString("%1 commercial breaks").arg(ret));
    }
    else if (cmdline.toBool("video"))
    {
        // build skiplist for video file
        return RebuildSeekTable(cmdline.toString(filename), -1);
    }
    else if (cmdline.toBool("file"))
    {
        // TODO: add back handling of recording defined by the basename

        // perform commercial flagging on file outside the database
        FlagCommercials(cmdline.toString("file"), -1,
                        cmdline.toString("outputfile"),
                        !cmdline.toBool("skipdb"));
    }
    else if (cmdline.toBool("queue"))
    {
        // run flagging for all recordings with no skiplist
        MSqlQuery query(MSqlQuery::InitCon());
        query.prepare("SELECT r.chanid, r.starttime, c.commmethod "
                        "FROM recorded AS r "
                   "LEFT JOIN channel AS c ON r.chanid=c.chanid "
//                     "WHERE startime >= :STARTTIME AND endtime <= :ENDTIME "
                    "ORDER BY starttime;");
        //query.bindValue(":STARTTIME", allStart);
        //query.bindValue(":ENDTIME", allEnd);
        
        if (query.exec() && query.isActive() && query.size() > 0)
        {
            QDateTime starttime;
            uint chanid;

            while (query.next())
            {
                starttime = QDateTime::fromString(query.value(1).toString(),
                                                        Qt::ISODate);
                chanid = query.value(0).toUInt();

                if (!cmdline.toBool("force") && !cmdline.toBool("rebuild"))
                {
                    // recording is already flagged
                    if (IsMarked(chanid, starttime))
                        continue;

                    // channel is marked as commercial free
                    if (query.value(2).toInt() == COMM_DETECT_COMMFREE)
                        continue;

                    // recording rule did not enable commflagging
//                    RecordingInfo recinfo(chanid, starttime);
//                    if (!(recinfo.GetAutoRunJobs() & JOB_COMMFLAG))
//                        continue;
                }

                QueueCommFlagJob(chanid, starttime, cmdline.toBool("rebuild"));
            }
        }

    }
    else
    {
        VERBOSE(VB_IMPORTANT, "No valid combination of command inputs received.");
        cmdline.PrintHelp();
        return GENERIC_EXIT_INVALID_CMDLINE;
    }

    return result;
}