Example #1
0
bool Dvr::DeleteRecording(int RecordedId,
                          int chanid, const QDateTime &recstarttsRaw,
                          bool forceDelete, bool allowRerecord)
{
    if ((RecordedId <= 0) &&
        (chanid <= 0 || !recstarttsRaw.isValid()))
        throw QString("Recorded ID or Channel ID and StartTime appears invalid.");

    // TODO Should use RecordingInfo
    ProgramInfo pi;
    if (RecordedId > 0)
        pi = ProgramInfo(RecordedId);
    else
        pi = ProgramInfo(chanid, recstarttsRaw.toUTC());

    if (pi.GetChanID() && pi.HasPathname())
    {
        QString cmd = QString("DELETE_RECORDING %1 %2 %3 %4")
            .arg(pi.GetChanID())
            .arg(pi.GetRecordingStartTime(MythDate::ISODate))
            .arg(forceDelete ? "FORCE" : "NO_FORCE")
            .arg(allowRerecord ? "FORGET" : "NO_FORGET");
        MythEvent me(cmd);

        gCoreContext->dispatch(me);
        return true;
    }

    return false;
}
Example #2
0
/** \brief Adds a ProgramInfo to the cache.
 *  \note This must only be called from the UI thread.
 */
void ProgramInfoCache::Add(const ProgramInfo &pginfo)
{
    if (!pginfo.GetChanID() || Update(pginfo))
        return;

    PICKey key(pginfo.GetChanID(),pginfo.GetRecordingStartTime());
    m_cache[key] = new ProgramInfo(pginfo);
}
Example #3
0
static int QueueJob(const MythUtilCommandLineParser &cmdline)
{
    ProgramInfo pginfo;
    if (!GetProgramInfo(cmdline, pginfo))
        return GENERIC_EXIT_NO_RECORDING_DATA;

    bool rebuildSeektable = false;
    int jobType = JOB_NONE;

    if (cmdline.toString("queuejob") == "transcode")
        jobType = JOB_TRANSCODE;
    else if (cmdline.toString("queuejob") == "commflag")
        jobType = JOB_COMMFLAG;
    else if (cmdline.toString("queuejob") == "rebuild")
    {
        jobType = JOB_COMMFLAG;
        rebuildSeektable = true;
    }
    else if (cmdline.toString("queuejob") == "metadata")
        jobType = JOB_METADATA;
    else if (cmdline.toString("queuejob") == "userjob1")
        jobType = JOB_USERJOB1;
    else if (cmdline.toString("queuejob") == "userjob2")
        jobType = JOB_USERJOB1;
    else if (cmdline.toString("queuejob") == "userjob4")
        jobType = JOB_USERJOB1;
    else if (cmdline.toString("queuejob") == "userjob4")
        jobType = JOB_USERJOB1;
    else if (cmdline.toInt("queuejob") > 0)
        jobType = cmdline.toInt("queuejob");

    if (jobType == JOB_NONE)
    {
        LOG(VB_GENERAL, LOG_ERR,
            "Error, invalid job type given with queuejob option");
        return GENERIC_EXIT_INVALID_CMDLINE;
    }

    bool result = JobQueue::QueueJob(jobType,
                                     pginfo.GetChanID(), pginfo.GetRecordingStartTime(), "", "", "",
                                     rebuildSeektable, JOB_QUEUED, QDateTime());

    if (result)
    {
        QString tmp = QString("%1 Job Queued for chanid %2 @ %3")
                      .arg(cmdline.toString("queuejob"))
                      .arg(pginfo.GetChanID())
                      .arg(pginfo.GetRecordingStartTime().toString());
        cerr << tmp.toLocal8Bit().constData() << endl;
        return GENERIC_EXIT_OK;
    }

    QString tmp = QString("Error queueing job for chanid %1 @ %2")
                  .arg(pginfo.GetChanID())
                  .arg(pginfo.GetRecordingStartTime().toString());
    cerr << tmp.toLocal8Bit().constData() << endl;
    return GENERIC_EXIT_DB_ERROR;
}
Example #4
0
ProgramInfo *getProgramInfoForFile(const QString &inFile)
{
    ProgramInfo *pinfo = NULL;
    QString chanID, startTime;
    bool bIsMythRecording = false;

    bIsMythRecording = extractDetailsFromFilename(inFile, chanID, startTime);

    if (bIsMythRecording)
    {
        uint chanid = chanID.toUInt();
        QDateTime recstartts = MythDate::fromString(startTime);
        pinfo = new ProgramInfo(chanid, recstartts);
        if (pinfo->GetChanID())
        {
            pinfo->SetPathname(pinfo->GetPlaybackURL(false, true));
        }
        else
        {
            delete pinfo;
            pinfo = NULL;
        }
    }

    if (!pinfo)
    {
        // file is not a myth recording or is no longer in the db
        pinfo = new ProgramInfo(inFile);
        LOG(VB_JOBQUEUE, LOG_NOTICE, "File is not a MythTV recording.");
    }
    else
        LOG(VB_JOBQUEUE, LOG_NOTICE, "File is a MythTV recording.");

    return pinfo;
}
Example #5
0
/// \brief Copies important fields from ProgramInfo
void RecordingInfo::clone(const ProgramInfo &other,
                          bool ignore_non_serialized_data)
{
    bool is_same =
        (chanid && recstartts.isValid() && startts.isValid() &&
         chanid     == other.GetChanID() &&
         recstartts == other.GetRecordingStartTime() &&
         startts    == other.GetScheduledStartTime());

    ProgramInfo::clone(other, ignore_non_serialized_data);

    if (!is_same)
    {
        delete record;
        record = NULL;
    }

    oldrecstatus   = rsUnknown;
    savedrecstatus = rsUnknown;
    future         = false;
    schedorder     = 0;
    mplexid        = 0;
    desiredrecstartts = QDateTime();
    desiredrecendts = QDateTime();
}
Example #6
0
void LiveTVChain::SetProgram(const ProgramInfo &pginfo)
{
    QMutexLocker lock(&m_lock);

    m_cur_chanid  = pginfo.GetChanID();
    m_cur_startts = pginfo.GetRecordingStartTime();

    m_curpos = ProgramIsAt(pginfo);
    m_switchid = -1;
}
Example #7
0
/**
*  \brief Show the program guide
*/
void ScheduleCommon::ShowGuide(void) const
{
    ProgramInfo *pginfo = GetCurrentProgram();
    if (!pginfo)
        return;

    QString startchannel = pginfo->GetChanNum();
    uint startchanid = pginfo->GetChanID();
    QDateTime starttime = pginfo->GetScheduledStartTime();
    GuideGrid::RunProgramGuide(startchanid, startchannel, starttime);
}
Example #8
0
/**
*  \brief Show the upcoming recordings for this title
*/
void ScheduleCommon::ShowUpcoming(void) const
{
    ProgramInfo *pginfo = GetCurrentProgram();
    if (!pginfo)
        return;

    if (pginfo->GetChanID() == 0 &&
        pginfo->GetRecordingRuleID() > 0)
        return ShowUpcomingScheduled();

    ShowUpcoming(pginfo->GetTitle(), pginfo->GetSeriesID());
}
Example #9
0
/** \brief Updates a ProgramInfo in the cache.
 *  \note This must only be called from the UI thread.
 *  \return True iff the ProgramInfo was in the cache and was updated.
 */
bool ProgramInfoCache::Update(const ProgramInfo &pginfo)
{
    QMutexLocker locker(&m_lock);

    Cache::iterator it = m_cache.find(
        PICKey(pginfo.GetChanID(),pginfo.GetRecordingStartTime()));

    if (it != m_cache.end())
        it->second->clone(pginfo, true);

    return it != m_cache.end();
}
Example #10
0
QFileInfo Content::GetRecording( int              nRecordedId,
                                 int              nChanId,
                                 const QDateTime &recstarttsRaw )
{
    if ((nRecordedId <= 0) &&
        (nChanId <= 0 || !recstarttsRaw.isValid()))
        throw QString("Recorded ID or Channel ID and StartTime appears invalid.");

    // ------------------------------------------------------------------
    // Read Recording From Database
    // ------------------------------------------------------------------

    // TODO Should use RecordingInfo
    ProgramInfo pginfo;
    if (nRecordedId > 0)
        pginfo = ProgramInfo(nRecordedId);
    else
        pginfo = ProgramInfo(nChanId, recstarttsRaw.toUTC());

    if (!pginfo.GetChanID())
    {
        LOG(VB_UPNP, LOG_ERR, QString("GetRecording - for '%1' failed")
            .arg(nRecordedId));

        return QFileInfo();
    }

    if (pginfo.GetHostname().toLower() != gCoreContext->GetHostName().toLower())
    {
        // We only handle requests for local resources

        QString sMsg =
            QString("GetRecording: Wrong Host '%1' request from '%2'.")
                          .arg( gCoreContext->GetHostName())
                          .arg( pginfo.GetHostname() );

        LOG(VB_UPNP, LOG_ERR, sMsg);

        throw HttpRedirectException( pginfo.GetHostname() );
    }

    QString sFileName( GetPlaybackURL(&pginfo) );

    // ----------------------------------------------------------------------
    // check to see if the file exists
    // ----------------------------------------------------------------------

    if (QFile::exists( sFileName ))
        return QFileInfo( sFileName );

    return QFileInfo();
}
Example #11
0
ProgramInfo *RemoteEncoder::GetRecording(void)
{
    QStringList strlist( QString("QUERY_RECORDER %1").arg(recordernum) );
    strlist << "GET_RECORDING";

    if (SendReceiveStringList(strlist))
    {
        ProgramInfo *proginfo = new ProgramInfo(strlist);
        if (proginfo->GetChanID())
            return proginfo;
        delete proginfo;
    }

    return NULL;
}
Example #12
0
/**
*  \brief Show the channel search
*/
void ScheduleCommon::ShowChannelSearch() const
{
    ProgramInfo *pginfo = GetCurrentProgram();
    if (!pginfo)
        return;

    MythScreenStack *mainStack = GetMythMainWindow()->GetMainStack();
    ProgLister *pl = new ProgLister(mainStack, plChannel,
                                    QString::number(pginfo->GetChanID()), "",
                                    pginfo->GetScheduledStartTime());
    if (pl->Create())
        mainStack->AddScreen(pl);
    else
        delete pl;
}
Example #13
0
ProgramInfo *LiveTVChain::EntryToProgram(const LiveTVChainEntry &entry)
{
    ProgramInfo *pginfo = new ProgramInfo(entry.chanid, entry.starttime);

    if (pginfo->GetChanID())
    {
        pginfo->SetPathname(entry.hostprefix + pginfo->GetBasename());
        return pginfo;
    }

    LOG(VB_GENERAL, LOG_ERR,
        QString("EntryToProgram(%1@%2) failed to get pginfo")
            .arg(entry.chanid).arg(entry.starttime.toString()));
    delete pginfo;
    return NULL;
}
Example #14
0
/** \brief Returns the ProgramInfo being used by any current recording.
 *
 *   Caller is responsible for deleting the ProgramInfo when done with it.
 */
ProgramInfo *PlaybackSock::GetRecording(uint cardid)
{
    QStringList strlist(QString("QUERY_REMOTEENCODER %1").arg(cardid));
    strlist << "GET_CURRENT_RECORDING";

    if (!SendReceiveStringList(strlist))
        return NULL;

    ProgramInfo *pginfo = new ProgramInfo(strlist);
    if (!pginfo->HasPathname() && !pginfo->GetChanID())
    {
        delete pginfo;
        pginfo = NULL;
    }

    return pginfo;
}
Example #15
0
void ProgLister::DeleteOldEpisode(bool ok)
{
    ProgramInfo *pi = GetCurrent();
    if (!ok || !pi)
        return;

    MSqlQuery query(MSqlQuery::InitCon());
    query.prepare(
        "DELETE FROM oldrecorded "
        "WHERE chanid    = :CHANID AND "
        "      starttime = :STARTTIME");
    query.bindValue(":CHANID",    pi->GetChanID());
    query.bindValue(":STARTTIME", pi->GetScheduledStartTime());

    if (!query.exec())
        MythDB::DBError("ProgLister::DeleteOldEpisode", query);

    ScheduledRecording::signalChange(0);
    FillItemList(true);
}
Example #16
0
bool Dvr::UpdateRecordedWatchedStatus ( int RecordedId,
                                        int   chanid,
                                        const QDateTime &recstarttsRaw,
                                        bool  watched)
{
    if ((RecordedId <= 0) &&
        (chanid <= 0 || !recstarttsRaw.isValid()))
        throw QString("Recorded ID or Channel ID and StartTime appears invalid.");

    // TODO Should use RecordingInfo
    ProgramInfo pi;
    if (RecordedId > 0)
        pi = ProgramInfo(RecordedId);
    else
        pi = ProgramInfo(chanid, recstarttsRaw.toUTC());

    if (pi.GetChanID() && pi.HasPathname())
    {
        pi.SaveWatched(watched);
        return true;
    }

    return false;
}
Example #17
0
DTC::ProgramGuide *Guide::GetProgramGuide( const QDateTime &dtStartTime ,
                                           const QDateTime &dtEndTime   ,
                                           int              nStartChanId,
                                           int              nNumChannels,
                                           bool             bDetails      )
{     

    if (!dtStartTime.isValid())
        throw( "StartTime is invalid" );

    if (!dtEndTime.isValid())
        throw( "EndTime is invalid" );

    if (dtEndTime < dtStartTime)
        throw( "EndTime is before StartTime");

    if (nNumChannels == 0)
        nNumChannels = 1;

    if (nNumChannels == -1)
        nNumChannels = SHRT_MAX;

    // ----------------------------------------------------------------------
    // Find the ending channel Id
    // ----------------------------------------------------------------------

    int nEndChanId = nStartChanId;

    MSqlQuery query(MSqlQuery::InitCon());

    query.prepare( "SELECT chanid FROM channel WHERE (chanid >= :STARTCHANID )"
                   " ORDER BY chanid LIMIT :NUMCHAN" );

    query.bindValue(":STARTCHANID", nStartChanId );
    query.bindValue(":NUMCHAN"    , nNumChannels );

    if (!query.exec())
        MythDB::DBError("Select ChanId", query);

    query.first();  nStartChanId = query.value(0).toInt();
    query.last();   nEndChanId   = query.value(0).toInt();

    // ----------------------------------------------------------------------
    // Build SQL statement for Program Listing
    // ----------------------------------------------------------------------

    ProgramList  progList;
    ProgramList  schedList;
    MSqlBindings bindings;

    QString      sSQL = "WHERE program.chanid >= :StartChanId "
                         "AND program.chanid <= :EndChanId "
                         "AND program.endtime >= :StartDate "
                         "AND program.starttime <= :EndDate "
                        "GROUP BY program.starttime, channel.channum, "
                         "channel.callsign, program.title "
                        "ORDER BY program.chanid ";

    bindings[":StartChanId"] = nStartChanId;
    bindings[":EndChanId"  ] = nEndChanId;
    bindings[":StartDate"  ] = dtStartTime;
    bindings[":EndDate"    ] = dtEndTime;

    // ----------------------------------------------------------------------
    // Get all Pending Scheduled Programs
    // ----------------------------------------------------------------------

    bool hasConflicts;
    LoadFromScheduler(schedList, hasConflicts);

    // ----------------------------------------------------------------------

    LoadFromProgram( progList, sSQL, bindings, schedList, false );

    // ----------------------------------------------------------------------
    // Build Response
    // ----------------------------------------------------------------------

    DTC::ProgramGuide *pGuide = new DTC::ProgramGuide();

    int               nChanCount = 0;
    uint              nCurChanId = 0;
    DTC::ChannelInfo *pChannel   = NULL;

    for( uint n = 0; n < progList.size(); n++)
    {
        ProgramInfo *pInfo = progList[ n ];

        if ( nCurChanId != pInfo->GetChanID() )
        {
            nChanCount++;

            nCurChanId = pInfo->GetChanID();

            pChannel = pGuide->AddNewChannel();

            FillChannelInfo( pChannel, pInfo, bDetails );
        }

        
        DTC::Program *pProgram = pChannel->AddNewProgram();

        FillProgramInfo( pProgram, pInfo, false, bDetails );
    }

    // ----------------------------------------------------------------------

    pGuide->setStartTime    ( dtStartTime   );
    pGuide->setEndTime      ( dtEndTime     );
    pGuide->setStartChanId  ( nStartChanId  );
    pGuide->setEndChanId    ( nEndChanId    );
    pGuide->setNumOfChannels( nChanCount    );
    pGuide->setDetails      ( bDetails      );
    
    pGuide->setCount        ( progList.size());
    pGuide->setAsOf         ( QDateTime::currentDateTime() );
    
    pGuide->setVersion      ( MYTH_BINARY_VERSION );
    pGuide->setProtoVer     ( MYTH_PROTO_VERSION  );
    
    return pGuide;
}
Example #18
0
int main(int argc, char *argv[])
{
    uint chanid;
    QDateTime starttime;
    QString infile, outfile;
    QString profilename = QString("autodetect");
    QString fifodir = NULL;
    int jobID = -1;
    int jobType = JOB_NONE;
    int otype = REPLEX_MPEG2;
    bool useCutlist = false, keyframesonly = false;
    bool build_index = false, fifosync = false;
    bool mpeg2 = false;
    bool fifo_info = false;
    bool cleanCut = false;
    QMap<QString, QString> settingsOverride;
    frm_dir_map_t deleteMap;
    frm_pos_map_t posMap;
    int AudioTrackNo = -1;

    int found_starttime = 0;
    int found_chanid = 0;
    int found_infile = 0;
    int update_index = 1;
    int isVideo = 0;
    bool passthru = false;

    MythTranscodeCommandLineParser cmdline;
    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_MYTHTRANSCODE);

    if (cmdline.toBool("outputfile"))
    {
        outfile = cmdline.toString("outputfile");
        update_index = 0;
    }

    bool showprogress = cmdline.toBool("showprogress");

    int retval;
    QString mask("general");
    bool quiet = (outfile == "-") || showprogress;
    if ((retval = cmdline.ConfigureLogging(mask, quiet)) != GENERIC_EXIT_OK)
        return retval;

    if (cmdline.toBool("starttime"))
    {
        starttime = cmdline.toDateTime("starttime");
        found_starttime = 1;
    }
    if (cmdline.toBool("chanid"))
    {
        chanid = cmdline.toUInt("chanid");
        found_chanid = 1;
    }
    if (cmdline.toBool("jobid"))
        jobID = cmdline.toInt("jobid");
    if (cmdline.toBool("inputfile"))
    {
        infile = cmdline.toString("inputfile");
        found_infile = 1;
    }
    if (cmdline.toBool("video"))
        isVideo = true;
    if (cmdline.toBool("profile"))
        profilename = cmdline.toString("profile");

    if (cmdline.toBool("usecutlist"))    
    {
        useCutlist = true;
        if (!cmdline.toString("usecutlist").isEmpty())
        {
            if (!cmdline.toBool("inputfile") && !cmdline.toBool("hls"))
            {
                LOG(VB_GENERAL, LOG_CRIT, "External cutlists are only allowed "
                                          "when using the --infile option.");
                return GENERIC_EXIT_INVALID_CMDLINE;
            }

            uint64_t last = 0, start, end;
            QStringList cutlist = cmdline.toStringList("usecutlist", " ");
            QStringList::iterator it;
            for (it = cutlist.begin(); it != cutlist.end(); ++it)
            {
                QStringList startend =
                    (*it).split("-", QString::SkipEmptyParts);
                if (startend.size() == 2)
                {
                    start = startend.first().toULongLong();
                    end = startend.last().toULongLong();

                    if (cmdline.toBool("inversecut"))
                    {
                        LOG(VB_GENERAL, LOG_DEBUG,
                                QString("Cutting section %1-%2.")
                                    .arg(last).arg(start));
                        deleteMap[start] = MARK_CUT_END;
                        deleteMap[end] = MARK_CUT_START;
                        last = end;
                    }
                    else
                    {
                        LOG(VB_GENERAL, LOG_DEBUG,
                                QString("Cutting section %1-%2.")
                                    .arg(start).arg(end));
                        deleteMap[start] = MARK_CUT_START;
                        deleteMap[end] = MARK_CUT_END;
                    }
                }
            }

            if (cmdline.toBool("inversecut"))
            {
                if (deleteMap.contains(0) && (deleteMap[0] == MARK_CUT_END))
                    deleteMap.remove(0);
                else
                    deleteMap[0] = MARK_CUT_START;
                deleteMap[999999999] = MARK_CUT_END;
                LOG(VB_GENERAL, LOG_DEBUG,
                    QString("Cutting section %1-999999999.")
                                    .arg(last));
            }

            // sanitize cutlist
            if (deleteMap.count() >= 2)
            {
                frm_dir_map_t::iterator cur = deleteMap.begin(), prev;
                prev = cur++;
                while (cur != deleteMap.end())
                {
                    if (prev.value() == cur.value())
                    {
                        // two of the same type next to each other
                        QString err("Cut %1points found at %3 and %4, with no "
                                    "%2 point in between.");
                        if (prev.value() == MARK_CUT_END)
                            err = err.arg("end").arg("start");
                        else
                            err = err.arg("start").arg("end");
                        LOG(VB_GENERAL, LOG_CRIT, "Invalid cutlist defined!");
                        LOG(VB_GENERAL, LOG_CRIT, err.arg(prev.key())
                                                     .arg(cur.key()));
                        return GENERIC_EXIT_INVALID_CMDLINE;
                    }
                    else if ( (prev.value() == MARK_CUT_START) &&
                              ((cur.key() - prev.key()) < 2) )
                    {
                        LOG(VB_GENERAL, LOG_WARNING, QString("Discarding "
                                          "insufficiently long cut: %1-%2")
                                            .arg(prev.key()).arg(cur.key()));
                        prev = deleteMap.erase(prev);
                        cur  = deleteMap.erase(cur);

                        if (cur == deleteMap.end())
                            continue;
                    }
                    prev = cur++;
                }
            }
        }
        else if (cmdline.toBool("inversecut"))
        {
            cerr << "Cutlist inversion requires an external cutlist be" << endl
                 << "provided using the --honorcutlist option." << endl;
            return GENERIC_EXIT_INVALID_CMDLINE;
        }
    }

    if (cmdline.toBool("cleancut"))
        cleanCut = true;

    if (cmdline.toBool("allkeys"))
        keyframesonly = true;
    if (cmdline.toBool("reindex"))
        build_index = true;
    if (cmdline.toBool("fifodir"))
        fifodir = cmdline.toString("fifodir");
    if (cmdline.toBool("fifoinfo"))
        fifo_info = true;
    if (cmdline.toBool("fifosync"))
        fifosync = true;
    if (cmdline.toBool("recopt"))
        recorderOptions = cmdline.toString("recopt");
    if (cmdline.toBool("mpeg2"))
        mpeg2 = true;
    if (cmdline.toBool("ostream"))
    {
        if (cmdline.toString("ostream") == "dvd")
            otype = REPLEX_DVD;
        else if (cmdline.toString("ostream") == "ts")
            otype = REPLEX_TS_SD;
        else
        {
            cerr << "Invalid 'ostream' type: "
                 << cmdline.toString("ostream").toLocal8Bit().constData()
                 << endl;
            return GENERIC_EXIT_INVALID_CMDLINE;
        }
    }
    if (cmdline.toBool("audiotrack"))
        AudioTrackNo = cmdline.toInt("audiotrack");
    if (cmdline.toBool("passthru"))
        passthru = true;

    CleanupGuard callCleanup(cleanup);

#ifndef _WIN32
    QList<int> signallist;
    signallist << SIGINT << SIGTERM << SIGSEGV << SIGABRT << SIGBUS << SIGFPE
               << SIGILL;
    SignalHandler handler(signallist);
    signal(SIGHUP, SIG_IGN);
#endif

    //  Load the context
    gContext = new MythContext(MYTH_BINARY_VERSION);
    if (!gContext->Init(false))
    {
        LOG(VB_GENERAL, LOG_ERR, "Failed to init MythContext, exiting.");
        return GENERIC_EXIT_NO_MYTHCONTEXT;
    }

    MythTranslation::load("mythfrontend");

    cmdline.ApplySettingsOverride();

    if (jobID != -1)
    {
        if (JobQueue::GetJobInfoFromID(jobID, jobType, chanid, starttime))
        {
            found_starttime = 1;
            found_chanid = 1;
        }
        else
        {
            cerr << "mythtranscode: ERROR: Unable to find DB info for "
                 << "JobQueue ID# " << jobID << endl;
            return GENERIC_EXIT_NO_RECORDING_DATA;
        }
    }

    if (((!found_infile && !(found_chanid && found_starttime)) ||
         (found_infile && (found_chanid || found_starttime))) &&
        (!cmdline.toBool("hls")))
    {
         cerr << "Must specify -i OR -c AND -s options!" << endl;
         return GENERIC_EXIT_INVALID_CMDLINE;
    }
    if (isVideo && !found_infile && !cmdline.toBool("hls"))
    {
         cerr << "Must specify --infile to use --video" << endl;
         return GENERIC_EXIT_INVALID_CMDLINE;
    }
    if (jobID >= 0 && (found_infile || build_index))
    {
         cerr << "Can't specify -j with --buildindex, --video or --infile"
              << endl;
         return GENERIC_EXIT_INVALID_CMDLINE;
    }
    if ((jobID >= 0) && build_index)
    {
         cerr << "Can't specify both -j and --buildindex" << endl;
         return GENERIC_EXIT_INVALID_CMDLINE;
    }
    if (keyframesonly && !fifodir.isEmpty())
    {
         cerr << "Cannot specify both --fifodir and --allkeys" << endl;
         return GENERIC_EXIT_INVALID_CMDLINE;
    }
    if (fifosync && fifodir.isEmpty())
    {
         cerr << "Must specify --fifodir to use --fifosync" << endl;
         return GENERIC_EXIT_INVALID_CMDLINE;
    }
    if (fifo_info && !fifodir.isEmpty())
    {
        cerr << "Cannot specify both --fifodir and --fifoinfo" << endl;
        return GENERIC_EXIT_INVALID_CMDLINE;
    }
    if (cleanCut && fifodir.isEmpty() && !fifo_info)
    {
        cerr << "Clean cutting works only in fifodir mode" << endl;
        return GENERIC_EXIT_INVALID_CMDLINE;
    }
    if (cleanCut && !useCutlist)
    {
        cerr << "--cleancut is pointless without --honorcutlist" << endl;
        return GENERIC_EXIT_INVALID_CMDLINE;
    }

    if (fifo_info)
    {
        // Setup a dummy fifodir path, so that the "fifodir" code path
        // is taken. The path wont actually be used.
        fifodir = "DummyFifoPath";
    }

    if (!MSqlQuery::testDBConnection())
    {
        LOG(VB_GENERAL, LOG_ERR, "couldn't open db");
        return GENERIC_EXIT_DB_ERROR;
    }

    ProgramInfo *pginfo = NULL;
    if (cmdline.toBool("hls"))
    {
        pginfo = new ProgramInfo();
    }
    else if (isVideo)
    {
        // We want the absolute file path for the filemarkup table
        QFileInfo inf(infile);
        infile = inf.absoluteFilePath();
        pginfo = new ProgramInfo(infile);
    }
    else if (!found_infile)
    {
        pginfo = new ProgramInfo(chanid, starttime);

        if (!pginfo->GetChanID())
        {
            LOG(VB_GENERAL, LOG_ERR,
                QString("Couldn't find recording for chanid %1 @ %2")
                .arg(chanid).arg(starttime.toString(Qt::ISODate)));
            delete pginfo;
            return GENERIC_EXIT_NO_RECORDING_DATA;
        }

        infile = pginfo->GetPlaybackURL(false, true);
    }
    else
    {
        pginfo = new ProgramInfo(infile);
        if (!pginfo->GetChanID())
        {
            LOG(VB_GENERAL, LOG_ERR,
                QString("Couldn't find a recording for filename '%1'")
                    .arg(infile));
            delete pginfo;
            return GENERIC_EXIT_NO_RECORDING_DATA;
        }
    }

    if (!pginfo)
    {
        LOG(VB_GENERAL, LOG_ERR, "No program info found!");
        return GENERIC_EXIT_NO_RECORDING_DATA;
    }

    if (cmdline.toBool("queue"))
    {
        QString hostname = cmdline.toString("queue");
        return QueueTranscodeJob(pginfo, profilename, hostname, useCutlist);
    }

    if (infile.left(7) == "myth://" && (outfile.isEmpty() || outfile != "-") &&
        fifodir.isEmpty() && !cmdline.toBool("hls") && !cmdline.toBool("avf"))
    {
        LOG(VB_GENERAL, LOG_ERR,
            QString("Attempted to transcode %1. Mythtranscode is currently "
                    "unable to transcode remote files.") .arg(infile));
        return GENERIC_EXIT_REMOTE_FILE;
    }

    if (outfile.isEmpty() && !build_index && fifodir.isEmpty())
        outfile = infile + ".tmp";

    if (jobID >= 0)
        JobQueue::ChangeJobStatus(jobID, JOB_RUNNING);

    Transcode *transcode = new Transcode(pginfo);

    if (!build_index)
    {
        if (cmdline.toBool("hlsstreamid"))
            LOG(VB_GENERAL, LOG_NOTICE,
                QString("Transcoding HTTP Live Stream ID %1")
                        .arg(cmdline.toInt("hlsstreamid")));
        else if (fifodir.isEmpty())
            LOG(VB_GENERAL, LOG_NOTICE, QString("Transcoding from %1 to %2")
                    .arg(infile).arg(outfile));
        else
            LOG(VB_GENERAL, LOG_NOTICE, QString("Transcoding from %1 to FIFO")
                    .arg(infile));
    }

    if (cmdline.toBool("avf"))
    {
        transcode->SetAVFMode();

        if (cmdline.toBool("container"))
            transcode->SetCMDContainer(cmdline.toString("container"));
        if (cmdline.toBool("acodec"))
            transcode->SetCMDAudioCodec(cmdline.toString("acodec"));
        if (cmdline.toBool("vcodec"))
            transcode->SetCMDVideoCodec(cmdline.toString("vcodec"));
    }
    else if (cmdline.toBool("hls"))
    {
        transcode->SetHLSMode();

        if (cmdline.toBool("hlsstreamid"))
            transcode->SetHLSStreamID(cmdline.toInt("hlsstreamid"));
        if (cmdline.toBool("maxsegments"))
            transcode->SetHLSMaxSegments(cmdline.toInt("maxsegments"));
        if (cmdline.toBool("noaudioonly"))
            transcode->DisableAudioOnlyHLS();
    }

    if (cmdline.toBool("avf") || cmdline.toBool("hls"))
    {
        if (cmdline.toBool("width"))
            transcode->SetCMDWidth(cmdline.toInt("width"));
        if (cmdline.toBool("height"))
            transcode->SetCMDHeight(cmdline.toInt("height"));
        if (cmdline.toBool("bitrate"))
            transcode->SetCMDBitrate(cmdline.toInt("bitrate") * 1000);
        if (cmdline.toBool("audiobitrate"))
            transcode->SetCMDAudioBitrate(cmdline.toInt("audiobitrate") * 1000);
    }

    if (showprogress)
        transcode->ShowProgress(true);
    if (!recorderOptions.isEmpty())
        transcode->SetRecorderOptions(recorderOptions);
    int result = 0;
    if ((!mpeg2 && !build_index) || cmdline.toBool("hls"))
    {
        result = transcode->TranscodeFile(infile, outfile,
                                          profilename, useCutlist,
                                          (fifosync || keyframesonly), jobID,
                                          fifodir, fifo_info, cleanCut, deleteMap,
                                          AudioTrackNo, passthru);
        if ((result == REENCODE_OK) && (jobID >= 0))
            JobQueue::ChangeJobArgs(jobID, "RENAME_TO_NUV");
    }

    if (fifo_info)
    {
        delete transcode;
        return GENERIC_EXIT_OK;
    }

    int exitcode = GENERIC_EXIT_OK;
    if ((result == REENCODE_MPEG2TRANS) || mpeg2 || build_index)
    {
        void (*update_func)(float) = NULL;
        int (*check_func)() = NULL;
        if (useCutlist && !found_infile)
            pginfo->QueryCutList(deleteMap);
        if (jobID >= 0)
        {
           glbl_jobID = jobID;
           update_func = &UpdateJobQueue;
           check_func = &CheckJobQueue;
        }

        MPEG2fixup *m2f = new MPEG2fixup(infile, outfile,
                                         &deleteMap, NULL, false, false, 20,
                                         showprogress, otype, update_func,
                                         check_func);

        if (build_index)
        {
            int err = BuildKeyframeIndex(m2f, infile, posMap, jobID);
            if (err)
                return err;
            if (update_index)
                UpdatePositionMap(posMap, NULL, pginfo);
            else
                UpdatePositionMap(posMap, outfile + QString(".map"), pginfo);
        }
        else
        {
            result = m2f->Start();
            if (result == REENCODE_OK)
            {
                result = BuildKeyframeIndex(m2f, outfile, posMap, jobID);
                if (result == REENCODE_OK)
                {
                    if (update_index)
                        UpdatePositionMap(posMap, NULL, pginfo);
                    else
                        UpdatePositionMap(posMap, outfile + QString(".map"),
                                          pginfo);
                }
            }
        }
        delete m2f;
    }

    if (result == REENCODE_OK)
    {
        if (jobID >= 0)
            JobQueue::ChangeJobStatus(jobID, JOB_STOPPING);
        LOG(VB_GENERAL, LOG_NOTICE, QString("%1 %2 done")
                .arg(build_index ? "Building Index for" : "Transcoding")
                .arg(infile));
    }
    else if (result == REENCODE_CUTLIST_CHANGE)
    {
        if (jobID >= 0)
            JobQueue::ChangeJobStatus(jobID, JOB_RETRY);
        LOG(VB_GENERAL, LOG_NOTICE,
            QString("Transcoding %1 aborted because of cutlist update")
                .arg(infile));
        exitcode = GENERIC_EXIT_RESTART;
    }
    else if (result == REENCODE_STOPPED)
    {
        if (jobID >= 0)
            JobQueue::ChangeJobStatus(jobID, JOB_ABORTING);
        LOG(VB_GENERAL, LOG_NOTICE,
            QString("Transcoding %1 stopped because of stop command")
                .arg(infile));
        exitcode = GENERIC_EXIT_KILLED;
    }
    else
    {
        if (jobID >= 0)
            JobQueue::ChangeJobStatus(jobID, JOB_ERRORING);
        LOG(VB_GENERAL, LOG_ERR, QString("Transcoding %1 failed").arg(infile));
        exitcode = result;
    }

    if (jobID >= 0)
        CompleteJob(jobID, pginfo, useCutlist, &deleteMap, exitcode);

    transcode->deleteLater();

    return exitcode;
}
Example #19
0
int preview_helper(uint chanid, QDateTime starttime,
                   long long previewFrameNumber, long long previewSeconds,
                   const QSize &previewSize,
                   const QString &infile, const QString &outfile)
{
    // Lower scheduling priority, to avoid problems with recordings.
    if (setpriority(PRIO_PROCESS, 0, 9))
        LOG(VB_GENERAL, LOG_ERR, "Setting priority failed." + ENO);

    if (!chanid || !starttime.isValid())
        ProgramInfo::QueryKeyFromPathname(infile, chanid, starttime);

    ProgramInfo *pginfo = NULL;
    if (chanid && starttime.isValid())
    {
        pginfo = new ProgramInfo(chanid, starttime);
        if (!pginfo->GetChanID())
        {
            LOG(VB_GENERAL, LOG_ERR,
                QString("Cannot locate recording made on '%1' at '%2'")
                .arg(chanid).arg(starttime.toString(Qt::ISODate)));
            delete pginfo;
            return GENERIC_EXIT_NOT_OK;
        }
        pginfo->SetPathname(pginfo->GetPlaybackURL(false, true));
    }
    else if (!infile.isEmpty())
    {
        if (!QFileInfo(infile).isReadable())
        {
            LOG(VB_GENERAL, LOG_ERR,
                QString("Cannot read this file '%1'").arg(infile));
            return GENERIC_EXIT_NOT_OK;
        }
        pginfo = new ProgramInfo(
            infile, ""/*plot*/, ""/*title*/, ""/*subtitle*/, ""/*director*/,
            0/*season*/, 0/*episode*/, ""/*inetref*/, 120/*length_in_minutes*/,
            1895/*year*/, ""/*id*/);
    }
    else
    {
        LOG(VB_GENERAL, LOG_ERR, "Cannot locate recording to preview");
        return GENERIC_EXIT_NOT_OK;
    }

    PreviewGenerator *previewgen = new PreviewGenerator(
        pginfo, QString(), PreviewGenerator::kLocal);

    if (previewFrameNumber >= 0)
        previewgen->SetPreviewTimeAsFrameNumber(previewFrameNumber);

    if (previewSeconds >= 0)
        previewgen->SetPreviewTimeAsSeconds(previewSeconds);

    previewgen->SetOutputSize(previewSize);
    previewgen->SetOutputFilename(outfile);
    bool ok = previewgen->RunReal();
    previewgen->deleteLater();

    delete pginfo;

    return (ok) ? GENERIC_EXIT_OK : GENERIC_EXIT_NOT_OK;
}
Example #20
0
DTC::ProgramGuide *Guide::GetProgramGuide( const QDateTime &rawStartTime ,
                                           const QDateTime &rawEndTime   ,
                                           int              nStartChanId,
                                           int              nNumChannels,
                                           bool             bDetails,
                                           int              nChannelGroupId )
{     
    if (!rawStartTime.isValid())
        throw( "StartTime is invalid" );

    if (!rawEndTime.isValid())
        throw( "EndTime is invalid" );

    QDateTime dtStartTime = rawStartTime.toUTC();
    QDateTime dtEndTime = rawEndTime.toUTC();

    if (dtEndTime < dtStartTime)
        throw( "EndTime is before StartTime");

    if (nNumChannels == 0)
        nNumChannels = SHRT_MAX;

    // ----------------------------------------------------------------------
    // Find the ending channel Id
    // ----------------------------------------------------------------------

    int nEndChanId = nStartChanId;

    MSqlQuery query(MSqlQuery::InitCon());

    query.prepare( "SELECT chanid FROM channel WHERE (chanid >= :STARTCHANID )"
                   " ORDER BY chanid LIMIT :NUMCHAN" );

    query.bindValue(":STARTCHANID", nStartChanId );
    query.bindValue(":NUMCHAN"    , nNumChannels );

    if (!query.exec())
        MythDB::DBError("Select ChanId", query);

    query.first();  nStartChanId = query.value(0).toInt();
    query.last();   nEndChanId   = query.value(0).toInt();

    // ----------------------------------------------------------------------
    // Build SQL statement for Program Listing
    // ----------------------------------------------------------------------

    ProgramList  progList;
    ProgramList  schedList;
    MSqlBindings bindings;

    // lpad is to allow natural sorting of numbers
    QString      sSQL;

    if (nChannelGroupId > 0)
    {
        sSQL = "LEFT JOIN channelgroup ON program.chanid = channelgroup.chanid "
                         "WHERE channelgroup.grpid = :CHANGRPID AND ";
        bindings[":CHANGRPID"  ] = nChannelGroupId;
    }
    else
        sSQL = "WHERE ";

    sSQL +=     "visible != 0 "
                "AND program.chanid >= :StartChanId "
                "AND program.chanid <= :EndChanId "
                "AND program.endtime >= :StartDate "
                "AND program.starttime <= :EndDate "
                "AND program.manualid = 0 " // Exclude programmes created purely for 'manual' recording schedules
                "ORDER BY LPAD(CAST(channum AS UNSIGNED), 10, 0), "
                "         LPAD(channum,  10, 0),             "
                "         callsign,                          "
                "         LPAD(program.chanid, 10, 0),       "
                "         program.starttime ";

    bindings[":StartChanId"] = nStartChanId;
    bindings[":EndChanId"  ] = nEndChanId;
    bindings[":StartDate"  ] = dtStartTime;
    bindings[":EndDate"    ] = dtEndTime;

    // ----------------------------------------------------------------------
    // Get all Pending Scheduled Programs
    // ----------------------------------------------------------------------

    bool hasConflicts;
    LoadFromScheduler(schedList, hasConflicts);

    // ----------------------------------------------------------------------

    LoadFromProgram( progList, sSQL, bindings, schedList );

    // ----------------------------------------------------------------------
    // Build Response
    // ----------------------------------------------------------------------

    DTC::ProgramGuide *pGuide = new DTC::ProgramGuide();

    int               nChanCount = 0;
    uint              nCurChanId = 0;
    DTC::ChannelInfo *pChannel   = NULL;
    QString           sCurCallsign;
    uint              nSkipChanId = 0;

    for( uint n = 0; n < progList.size(); n++)
    {
        ProgramInfo *pInfo = progList[ n ];

        if ( nSkipChanId == pInfo->GetChanID())
            continue;

        if ( nCurChanId != pInfo->GetChanID() )
        {
            nChanCount++;

            nCurChanId = pInfo->GetChanID();

            // Filter out channels with the same callsign, keeping just the
            // first seen
            if (sCurCallsign == pInfo->GetChannelSchedulingID())
            {
                nSkipChanId = pInfo->GetChanID();
                continue;
            }

            pChannel = pGuide->AddNewChannel();

            FillChannelInfo( pChannel, pInfo->GetChanID(), bDetails );

            sCurCallsign = pChannel->CallSign();
        }
        
        DTC::Program *pProgram = pChannel->AddNewProgram();

        FillProgramInfo( pProgram, pInfo, false, bDetails, false ); // No cast info
    }

    // ----------------------------------------------------------------------

    pGuide->setStartTime    ( dtStartTime   );
    pGuide->setEndTime      ( dtEndTime     );
    pGuide->setStartChanId  ( nStartChanId  );
    pGuide->setEndChanId    ( nEndChanId    );
    pGuide->setNumOfChannels( nChanCount    );
    pGuide->setDetails      ( bDetails      );
    
    pGuide->setCount        ( progList.size());
    pGuide->setAsOf         ( MythDate::current() );
    
    pGuide->setVersion      ( MYTH_BINARY_VERSION );
    pGuide->setProtoVer     ( MYTH_PROTO_VERSION  );
    
    return pGuide;
}
Example #21
0
DTC::LiveStreamInfo *Content::AddRecordingLiveStream(
    int              nRecordedId,
    int              nChanId,
    const QDateTime &recstarttsRaw,
    int              nMaxSegments,
    int              nWidth,
    int              nHeight,
    int              nBitrate,
    int              nAudioBitrate,
    int              nSampleRate )
{
    if ((nRecordedId <= 0) &&
        (nChanId <= 0 || !recstarttsRaw.isValid()))
        throw QString("Recorded ID or Channel ID and StartTime appears invalid.");

    // ------------------------------------------------------------------
    // Read Recording From Database
    // ------------------------------------------------------------------

    // TODO Should use RecordingInfo
    ProgramInfo pginfo;
    if (nRecordedId > 0)
        pginfo = ProgramInfo(nRecordedId);
    else
        pginfo = ProgramInfo(nChanId, recstarttsRaw.toUTC());

    if (!pginfo.GetChanID())
    {
        LOG(VB_UPNP, LOG_ERR,
            QString("AddRecordingLiveStream - for %1, %2 failed")
            .arg(QString::number(nRecordedId)));
        return NULL;
    }

    if (pginfo.GetHostname().toLower() != gCoreContext->GetHostName().toLower())
    {
        // We only handle requests for local resources

        QString sMsg =
            QString("GetRecording: Wrong Host '%1' request from '%2'.")
                          .arg( gCoreContext->GetHostName())
                          .arg( pginfo.GetHostname() );

        LOG(VB_UPNP, LOG_ERR, sMsg);

        throw HttpRedirectException( pginfo.GetHostname() );
    }

    QString sFileName( GetPlaybackURL(&pginfo) );

    // ----------------------------------------------------------------------
    // check to see if the file exists
    // ----------------------------------------------------------------------

    if (!QFile::exists( sFileName ))
    {
        LOG( VB_UPNP, LOG_ERR, QString("AddRecordingLiveStream - for %1, %2 failed")
                                    .arg( nChanId )
                                    .arg( recstarttsRaw.toUTC().toString() ));
        return NULL;
    }

    QFileInfo fInfo( sFileName );

    return AddLiveStream( pginfo.GetStorageGroup(), fInfo.fileName(),
                          pginfo.GetHostname(), nMaxSegments, nWidth,
                          nHeight, nBitrate, nAudioBitrate, nSampleRate );
}
Example #22
0
QFileInfo Content::GetPreviewImage(        int        nRecordedId,
                                           int        nChanId,
                                     const QDateTime &recstarttsRaw,
                                           int        nWidth,
                                           int        nHeight,
                                           int        nSecsIn,
                                     const QString   &sFormat )
{
    if ((nRecordedId <= 0) &&
        (nChanId <= 0 || !recstarttsRaw.isValid()))
        throw QString("Recorded ID or Channel ID and StartTime appears invalid.");

    if (!sFormat.isEmpty()
        && !QImageWriter::supportedImageFormats().contains(sFormat.toLower().toLocal8Bit()))
    {
        throw "GetPreviewImage: Specified 'Format' is not supported.";
    }

    // ----------------------------------------------------------------------
    // Read Recording From Database
    // ----------------------------------------------------------------------

    // TODO Should use RecordingInfo
    ProgramInfo pginfo;
    if (nRecordedId > 0)
        pginfo = ProgramInfo(nRecordedId);
    else
        pginfo = ProgramInfo(nChanId, recstarttsRaw.toUTC());

    if (!pginfo.GetChanID())
    {
        LOG(VB_GENERAL, LOG_ERR,
            QString("GetPreviewImage: No recording for '%1'")
            .arg(nRecordedId));
        return QFileInfo();
    }

    if (pginfo.GetHostname().toLower() != gCoreContext->GetHostName().toLower())
    {
        QString sMsg =
            QString("GetPreviewImage: Wrong Host '%1' request from '%2'")
                          .arg( gCoreContext->GetHostName())
                          .arg( pginfo.GetHostname() );

        LOG(VB_UPNP, LOG_ERR, sMsg);

        throw HttpRedirectException( pginfo.GetHostname() );
    }

    QString sImageFormat = sFormat;
    if (sImageFormat.isEmpty())
        sImageFormat = "PNG";

    QString sFileName = GetPlaybackURL(&pginfo);

    // ----------------------------------------------------------------------
    // check to see if default preview image is already created.
    // ----------------------------------------------------------------------

    QString sPreviewFileName;

    if (nSecsIn <= 0)
    {
        nSecsIn = -1;
        sPreviewFileName = QString("%1.png").arg(sFileName);
    }
    else
    {
        sPreviewFileName = QString("%1.%2.png").arg(sFileName).arg(nSecsIn);
    }

    if (!QFile::exists( sPreviewFileName ))
    {
        // ------------------------------------------------------------------
        // Must generate Preview Image, Generate Image and save.
        // ------------------------------------------------------------------
        if (!pginfo.IsLocal() && sFileName.startsWith("/"))
            pginfo.SetPathname(sFileName);

        if (!pginfo.IsLocal())
            return QFileInfo();

        PreviewGenerator *previewgen = new PreviewGenerator( &pginfo, 
                                                             QString(), 
                                                             PreviewGenerator::kLocal);
        previewgen->SetPreviewTimeAsSeconds( nSecsIn          );
        previewgen->SetOutputFilename      ( sPreviewFileName );

        bool ok = previewgen->Run();

        previewgen->deleteLater();

        if (!ok)
            return QFileInfo();
    }

    bool bDefaultPixmap = (nWidth == 0) && (nHeight == 0);

    QString sNewFileName;

    if (bDefaultPixmap)
        sNewFileName = sPreviewFileName;
    else
    {
        sNewFileName = QString( "%1.%2.%3x%4.%5" )
                          .arg( sFileName )
                          .arg( nSecsIn   )
                          .arg( nWidth == 0 ? -1 : nWidth )
                          .arg( nHeight == 0 ? -1 : nHeight )
                          .arg( sImageFormat.toLower() );

        // ----------------------------------------------------------------------
        // check to see if scaled preview image is already created and isn't
        // out of date
        // ----------------------------------------------------------------------
        if (QFile::exists( sNewFileName ))
        {
            if (QFileInfo(sPreviewFileName).lastModified() <=
                QFileInfo(sNewFileName).lastModified())
                return QFileInfo( sNewFileName );
        }

        QImage image = QImage(sPreviewFileName);

        if (image.isNull())
            return QFileInfo();

        // We can just re-scale the default (full-size version) to avoid
        // a preview generator run
        if ( nWidth <= 0 )
            image = image.scaledToHeight(nHeight, Qt::SmoothTransformation);
        else if ( nHeight <= 0 )
            image = image.scaledToWidth(nWidth, Qt::SmoothTransformation);
        else
            image = image.scaled(nWidth, nHeight, Qt::IgnoreAspectRatio,
                                        Qt::SmoothTransformation);

        image.save(sNewFileName, sImageFormat.toUpper().toLocal8Bit());

        // Let anybody update it
        bool ret = makeFileAccessible(sNewFileName.toLocal8Bit().constData());
        if (!ret)
        {
            LOG(VB_GENERAL, LOG_ERR, "Unable to change permissions on "
                                     "preview image. Backends and frontends "
                                     "running under different users will be "
                                     "unable to access it");
        }
    }

    if (QFile::exists( sNewFileName ))
        return QFileInfo( sNewFileName );

    PreviewGenerator *previewgen = new PreviewGenerator( &pginfo,
                                                         QString(),
                                                         PreviewGenerator::kLocal);
    previewgen->SetPreviewTimeAsSeconds( nSecsIn             );
    previewgen->SetOutputFilename      ( sNewFileName        );
    previewgen->SetOutputSize          (QSize(nWidth,nHeight));

    bool ok = previewgen->Run();

    previewgen->deleteLater();

    if (!ok)
        return QFileInfo();

    return QFileInfo( sNewFileName );
}
Example #23
0
void StatusBox::customEvent(QEvent *event)
{
    if (event->type() == DialogCompletionEvent::kEventType)
    {
        DialogCompletionEvent *dce = (DialogCompletionEvent*)(event);

        QString resultid  = dce->GetId();
        int     buttonnum = dce->GetResult();

        if (resultid == "LogAck")
        {
            if (buttonnum == 1)
            {
                QString sql = dce->GetData().toString();
                MSqlQuery query(MSqlQuery::InitCon());
                query.prepare("UPDATE mythlog SET acknowledged = 1 "
                            "WHERE logid = :LOGID ;");
                query.bindValue(":LOGID", sql);
                if (!query.exec())
                    MythDB::DBError("StatusBox::customEvent -- LogAck", query);
                m_logList->RemoveItem(m_logList->GetItemCurrent());
            }
        }
        else if (resultid == "LogAckAll")
        {
            if (buttonnum == 1)
            {
                MSqlQuery query(MSqlQuery::InitCon());
                query.prepare("UPDATE mythlog SET acknowledged = 1 "
                                "WHERE priority <= :PRIORITY ;");
                query.bindValue(":PRIORITY", m_minLevel);
                if (!query.exec())
                    MythDB::DBError("StatusBox::customEvent -- LogAckAll",
                                    query);
                doLogEntries();
            }
        }
        else if (resultid == "JobDelete")
        {
            if (buttonnum == 1)
            {
                int jobID = dce->GetData().toInt();
                JobQueue::DeleteJob(jobID);

                m_logList->RemoveItem(m_logList->GetItemCurrent());
            }
        }
        else if (resultid == "JobRequeue")
        {
            if (buttonnum == 1)
            {
                int jobID = dce->GetData().toInt();
                JobQueue::ChangeJobStatus(jobID, JOB_QUEUED);
                doJobQueueStatus();
            }
        }
        else if (resultid == "JobModify")
        {
            int jobID = dce->GetData().toInt();
            if (buttonnum == 0)
            {
                if (JobQueue::GetJobStatus(jobID) == JOB_PAUSED)
                    JobQueue::ResumeJob(jobID);
                else
                    JobQueue::PauseJob(jobID);
            }
            else if (buttonnum == 1)
            {
                JobQueue::StopJob(jobID);
            }

            doJobQueueStatus();
        }
        else if (resultid == "AutoExpireManage")
        {
            ProgramInfo* rec = qVariantValue<ProgramInfo*>(dce->GetData());

            // button 2 is "No Change"
            if (!rec || buttonnum == 2)
                return;

            // button 1 is "Delete Now"
            if ((buttonnum == 0) && rec->QueryIsDeleteCandidate())
            {
                if (!RemoteDeleteRecording(
                    rec->GetChanID(), rec->GetRecordingStartTime(),
                    false, false))
                {
                    LOG(VB_GENERAL, LOG_ERR, QString("Failed to delete recording: %1").arg(rec->GetTitle()));
                    return;
                }
            }
            // button 1 is "Move To Default Group" or "UnDelete" or "Disable AutoExpire"
            else if (buttonnum == 1)
            {
                if ((rec)->GetRecordingGroup() == "Deleted")
                {
                    RemoteUndeleteRecording(
                        rec->GetChanID(), rec->GetRecordingStartTime());
                }
                else
                {
                    rec->SaveAutoExpire(kDisableAutoExpire);

                    if ((rec)->GetRecordingGroup() == "LiveTV")
                    {
                        RecordingInfo ri(*rec);
                        ri.ApplyRecordRecGroupChange("Default");
                        *rec = ri;
                    }
                }
            }

            // remove the changed recording from the expire list
            delete m_expList[m_logList->GetCurrentPos()];
            m_expList.erase(m_expList.begin() + m_logList->GetCurrentPos());

            int pos = m_logList->GetCurrentPos();
            int topPos = m_logList->GetTopItemPos();
            doAutoExpireList(false);
            m_logList->SetItemCurrent(pos, topPos);
        }

    }
}
Example #24
0
/** \fn LiveTVChain::ProgramIsAt(const ProgramInfo&) const
 *  \returns program location or -1 for not found.
 */
int LiveTVChain::ProgramIsAt(const ProgramInfo &pginfo) const
{
    return ProgramIsAt(pginfo.GetChanID(), pginfo.GetRecordingStartTime());
}
Example #25
0
int main(int argc, char *argv[])
{
    uint chanid;
    QString starttime, infile, outfile;
    QString profilename = QString("autodetect");
    QString fifodir = NULL;
    int jobID = -1;
    QDateTime startts;
    int jobType = JOB_NONE;
    int otype = REPLEX_MPEG2;
    bool useCutlist = false, keyframesonly = false;
    bool build_index = false, fifosync = false, showprogress = false, mpeg2 = false;
    QMap<QString, QString> settingsOverride;
    frm_dir_map_t deleteMap;
    frm_pos_map_t posMap;
    srand(time(NULL));
    int AudioTrackNo = -1;

    QCoreApplication a(argc, argv);

    QCoreApplication::setApplicationName(MYTH_APPNAME_MYTHTRANSCODE);

    print_verbose_messages = VB_IMPORTANT;
    verboseString = "important";

    int found_starttime = 0;
    int found_chanid = 0;
    int found_infile = 0;
    int update_index = 1;
    int isVideo = 0;
    bool passthru = false;

    for (int argpos = 1; argpos < a.argc(); ++argpos)
    {
        if (!strcmp(a.argv()[argpos],"-s") ||
            !strcmp(a.argv()[argpos],"--starttime"))
        {
            if (a.argc()-1 > argpos && a.argv()[argpos+1][0] != '-')
            {
                starttime = a.argv()[argpos + 1];
                found_starttime = 1;
                ++argpos;
            }
            else
            {
                cerr << "Missing argument to -s/--starttime option\n";
                usage(a.argv()[0]);
                return GENERIC_EXIT_INVALID_CMDLINE;
            }
        }
        else if (!strcmp(a.argv()[argpos],"-c") ||
                 !strcmp(a.argv()[argpos],"--chanid"))
        {
            if (a.argc()-1 > argpos && a.argv()[argpos+1][0] != '-')
            {
                chanid = QString(a.argv()[argpos + 1]).toUInt();
                found_chanid = 1;
                ++argpos;
            }
            else
            {
                cerr << "Missing argument to -c/--chanid option\n";
                usage(a.argv()[0]);
                return GENERIC_EXIT_INVALID_CMDLINE;
            }
        }
        else if (!strcmp(a.argv()[argpos], "-j"))
        {
            if (a.argc()-1 > argpos && a.argv()[argpos+1][0] != '-')
            {
                jobID = QString(a.argv()[++argpos]).toInt();
            }
            else
            {
                cerr << "Missing argument to -j option\n";
                usage(a.argv()[0]);
                return GENERIC_EXIT_INVALID_CMDLINE;
            }
        }
        else if (!strcmp(a.argv()[argpos],"-i") ||
                 !strcmp(a.argv()[argpos],"--infile"))
        {
            if (a.argc()-1 > argpos && a.argv()[argpos+1][0] != '-')
            {
                infile = a.argv()[argpos + 1];
                found_infile = 1;
                ++argpos;
            }
            else
            {
                cerr << "Missing argument to -i/--infile option\n";
                usage(a.argv()[0]);
                return GENERIC_EXIT_INVALID_CMDLINE;
            }
        }
        else if (!strcmp(a.argv()[argpos],"--video"))
        {
            isVideo = 1;
            //mpeg2 = true;
        }
        else if (!strcmp(a.argv()[argpos],"-o") ||
                 !strcmp(a.argv()[argpos],"--outfile"))
        {
            if ((a.argc()-1 > argpos) &&
                (a.argv()[argpos+1][0] != '-' || a.argv()[argpos+1][1] == 0x0))
            {
                outfile = a.argv()[argpos + 1];
                update_index = 0;
                ++argpos;
            }
            else
            {
                cerr << "Missing argument to -o/--outfile option\n";
                usage(a.argv()[0]);
                return GENERIC_EXIT_INVALID_CMDLINE;
            }
        }
        else if (!strcmp(a.argv()[argpos],"-V"))
        {
            if (a.argc()-1 > argpos && a.argv()[argpos+1][0] != '-')
            {
                QString temp = a.argv()[++argpos];
                print_verbose_messages = temp.toUInt();
            }
            else
            {
                cerr << "Missing argument to -V option\n";
                return GENERIC_EXIT_INVALID_CMDLINE;
            }
        }
        else if (!strcmp(a.argv()[argpos],"-v") ||
                 !strcmp(a.argv()[argpos],"--verbose"))
        {
            if (a.argc()-1 > argpos && a.argv()[argpos+1][0] != '-')
            {
                if (parse_verbose_arg(a.argv()[argpos+1]) ==
                        GENERIC_EXIT_INVALID_CMDLINE)
                    return GENERIC_EXIT_INVALID_CMDLINE;

                ++argpos;
            } else
            {
                cerr << "Missing argument to -v/--verbose option\n";
                return GENERIC_EXIT_INVALID_CMDLINE;
            }
        }
        else if (!strcmp(a.argv()[argpos],"-p") ||
                 !strcmp(a.argv()[argpos],"--profile"))
        {
            if (a.argc()-1 > argpos && a.argv()[argpos+1][0] != '-')
            {
                profilename = a.argv()[argpos + 1];
                ++argpos;
            }
            else
            {
                cerr << "Missing argument to -p/--profile option\n";
                usage(a.argv()[0]);
                return GENERIC_EXIT_INVALID_CMDLINE;
            }
        }
        else if (!strcmp(a.argv()[argpos],"-l") ||
                 !strcmp(a.argv()[argpos],"--honorcutlist"))
        {
            useCutlist = true;
            if (!found_infile)
                continue;

            if (a.argc()-1 > argpos && a.argv()[argpos+1][0] != '-')
            {
                QStringList cutlist = QString(a.argv()[argpos + 1])
                    .split(" ", QString::SkipEmptyParts);
                ++argpos;
                for (QStringList::Iterator it = cutlist.begin();
                     it != cutlist.end(); ++it )
                {
                    QStringList startend = (*it)
                        .split("-", QString::SkipEmptyParts);
                    if (startend.count() == 2)
                    {
                        cerr << "Cutting from: "
                             << startend.first().toULongLong()
                             << " to: " << startend.last().toULongLong() <<"\n";
                        deleteMap[startend.first().toULongLong()] =
                            MARK_CUT_START;
                        deleteMap[startend.last().toULongLong()] =
                            MARK_CUT_END;
                    }
                }
            }
            else
            {
                cerr << "Missing argument to -l/--honorcutlist option\n";
                usage(a.argv()[0]);
                return GENERIC_EXIT_INVALID_CMDLINE;
            }
        }
        else if (!strcmp(a.argv()[argpos],"--inversecut"))
        {
            useCutlist = true;
            if (!found_infile)
            {
                cerr << "--inversecut option can only be used with --infile\n";
                usage(a.argv()[0]);
                return GENERIC_EXIT_INVALID_CMDLINE;
            }

            if (a.argc()-1 > argpos && a.argv()[argpos+1][0] != '-')
            {
                uint64_t last = 0;
                QStringList cutlist =  QString(a.argv()[argpos + 1])
                    .split(" ", QString::SkipEmptyParts);
                ++argpos;
                deleteMap[0] = MARK_CUT_START;
                for (QStringList::Iterator it = cutlist.begin();
                     it != cutlist.end(); ++it )
                {
                    QStringList startend = (*it).split(
                        "-", QString::SkipEmptyParts);
                    if (startend.count() == 2)
                    {
                        cerr << "Cutting from: " << last
                             << " to: "
                             << startend.first().toULongLong() <<"\n";
                        deleteMap[startend.first().toULongLong()] =
                            MARK_CUT_END;
                        deleteMap[startend.last().toULongLong()] =
                            MARK_CUT_START;
                        last = startend.last().toInt();
                    }
                }
                cerr << "Cutting from: " << last
                     << " to the end\n";
                deleteMap[999999999] = MARK_CUT_END;
            }
            else
            {
                cerr << "Missing argument to --inversecut option\n";
                usage(a.argv()[0]);
                return GENERIC_EXIT_INVALID_CMDLINE;
            }
        }
        else if (!strcmp(a.argv()[argpos],"-k") ||
                 !strcmp(a.argv()[argpos],"--allkeys"))
        {
            keyframesonly = true;
        }
        else if (!strcmp(a.argv()[argpos],"-b") ||
                 !strcmp(a.argv()[argpos],"--buildindex"))
        {
            build_index = true;
        }
        else if (!strcmp(a.argv()[argpos],"-f") ||
                 !strcmp(a.argv()[argpos],"--fifodir"))
        {
            if (a.argc()-1 > argpos && a.argv()[argpos+1][0] != '-')
            {
                fifodir = a.argv()[argpos + 1];
                ++argpos;
            }
            else
            {
                cerr << "Missing argument to -f/--fifodir option\n";
                usage(a.argv()[0]);
                return GENERIC_EXIT_INVALID_CMDLINE;
            }
        }
        else if (!strcmp(a.argv()[argpos],"-ro") ||
                 !strcmp(a.argv()[argpos],"--recorderOptions"))
        {
            if (a.argc()-1 > argpos && a.argv()[argpos+1][0] != '-')
            {
                recorderOptions = a.argv()[argpos + 1];
                ++argpos;
            }
            else
            {
                cerr << "Missing argument to -ro/--recorderOptions option\n";
                usage(a.argv()[0]);
                return GENERIC_EXIT_INVALID_CMDLINE;
            }
        }
        else if (!strcmp(a.argv()[argpos],"--fifosync"))
        {
            fifosync = true;
        }
        else if (!strcmp(a.argv()[argpos],"--showprogress"))
        {
            showprogress = true;
        }
        else if (!strcmp(a.argv()[argpos],"-m") ||
                 !strcmp(a.argv()[argpos],"--mpeg2"))
        {
            mpeg2 = true;
        }
        else if (!strcmp(a.argv()[argpos],"-e") ||
                 !strcmp(a.argv()[argpos],"--ostream"))
        {
            if (a.argc()-1 > argpos && a.argv()[argpos+1][0] != '-')
            {
                if(!strcmp(a.argv()[argpos + 1], "dvd"))
                    otype = REPLEX_DVD;
                if(!strcmp(a.argv()[argpos + 1], "ts"))
                    otype = REPLEX_TS_SD;

                ++argpos;
            }
            else
            {
                cerr << "Missing argument to -e/--ostream option\n";
                usage(a.argv()[0]);
                return GENERIC_EXIT_INVALID_CMDLINE;
            }
        }
        else if (!strcmp(a.argv()[argpos],"-O") ||
                 !strcmp(a.argv()[argpos],"--override-setting"))
        {
            if (a.argc()-1 > argpos && a.argv()[argpos+1][0] != '-')
            {
                QStringList pairs = QString(a.argv()[argpos+1]).split(
                    ",", QString::SkipEmptyParts);
                for (int index = 0; index < pairs.size(); ++index)
                {
                    QStringList tokens = pairs[index].split(
                        "=", QString::SkipEmptyParts);
                    tokens[0].replace(QRegExp("^[\"']"), "");
                    tokens[0].replace(QRegExp("[\"']$"), "");
                    tokens[1].replace(QRegExp("^[\"']"), "");
                    tokens[1].replace(QRegExp("[\"']$"), "");
                    settingsOverride[tokens[0]] = tokens[1];
                }
            }
            else
            {
                cerr << "Invalid or missing argument to -O/--override-setting "
                        "option\n";
                usage(a.argv()[0]);
                return GENERIC_EXIT_INVALID_CMDLINE;
            }

            ++argpos;
        }
        else if (!strcmp(a.argv()[argpos],"--audiotrack"))
        {
            if (a.argc()-1 > argpos && a.argv()[argpos+1][0] != '-')
            {
                AudioTrackNo = QString(a.argv()[argpos + 1]).toInt();
            }
            else
            {
                cerr << "Invalid or missing argument to --audiotrack "
                        "option\n";
                usage(a.argv()[0]);
                return GENERIC_EXIT_INVALID_CMDLINE;
            }

            ++argpos;
        }
        else if (!strcmp(a.argv()[argpos],"-h") ||
                 !strcmp(a.argv()[argpos],"--help"))
        {
            usage(a.argv()[0]);
            return GENERIC_EXIT_OK;
        }
        else if (!strcmp(a.argv()[argpos],"--passthrough"))
        {
            passthru = true;
        }
        else
        {
            cerr << "Unknown option: " << a.argv()[argpos] << endl;
            usage(a.argv()[0]);
            return GENERIC_EXIT_INVALID_CMDLINE;
        }
    }

    if (outfile == "-")
        print_verbose_messages = VB_NONE;

    //  Load the context
    gContext = new MythContext(MYTH_BINARY_VERSION);
    if (!gContext->Init(false))
    {
        VERBOSE(VB_IMPORTANT, "Failed to init MythContext, exiting.");
        return GENERIC_EXIT_NO_MYTHCONTEXT;
    }

    MythTranslation::load("mythfrontend");

    if (settingsOverride.size())
    {
        QMap<QString, QString>::iterator it;
        for (it = settingsOverride.begin(); it != settingsOverride.end(); ++it)
        {
            VERBOSE(VB_IMPORTANT, QString("Setting '%1' being forced to '%2'")
                                          .arg(it.key()).arg(*it));
            gCoreContext->OverrideSettingForSession(it.key(), *it);
        }
    }

    if (jobID != -1)
    {
        if (JobQueue::GetJobInfoFromID(
                jobID, jobType, chanid, startts))
        {
            starttime = startts.toString(Qt::ISODate);
            found_starttime = 1;
            found_chanid = 1;
        }
        else
        {
            cerr << "mythtranscode: ERROR: Unable to find DB info for "
                 << "JobQueue ID# " << jobID << endl;
            return GENERIC_EXIT_NO_RECORDING_DATA;
        }
    }

    if ((! found_infile && !(found_chanid && found_starttime)) ||
        (found_infile && (found_chanid || found_starttime)) )
    {
         cerr << "Must specify -i OR -c AND -s options!\n";
         return GENERIC_EXIT_INVALID_CMDLINE;
    }
    if (isVideo && !found_infile)
    {
         cerr << "Must specify --infile to use --video\n";
         return GENERIC_EXIT_INVALID_CMDLINE;
    }
    if (jobID >= 0 && (found_infile || build_index))
    {
         cerr << "Can't specify -j with --buildindex, --video or --infile\n";
         return GENERIC_EXIT_INVALID_CMDLINE;
    }
    if ((jobID >= 0) && build_index)
    {
         cerr << "Can't specify both -j and --buildindex\n";
         return GENERIC_EXIT_INVALID_CMDLINE;
    }
    if (keyframesonly && !fifodir.isEmpty())
    {
         cerr << "Cannot specify both --fifodir and --allkeys\n";
         return GENERIC_EXIT_INVALID_CMDLINE;
    }
    if (fifosync && fifodir.isEmpty())
    {
         cerr << "Must specify --fifodir to use --fifosync\n";
         return GENERIC_EXIT_INVALID_CMDLINE;
    }

    VERBOSE(VB_IMPORTANT, QString("Enabled verbose msgs: %1").arg(verboseString));

    if (!MSqlQuery::testDBConnection())
    {
        printf("couldn't open db\n");
        return GENERIC_EXIT_DB_ERROR;
    }

    ProgramInfo *pginfo = NULL;
    if (isVideo)
    {
        // We want the absolute file path for the filemarkup table
        QFileInfo inf(infile);
        infile = inf.absoluteFilePath();
        pginfo = new ProgramInfo(infile);
    }
    else if (!found_infile)
    {
        QDateTime recstartts = myth_dt_from_string(starttime);
        pginfo = new ProgramInfo(chanid, recstartts);

        if (!pginfo->GetChanID())
        {
            QString msg = QString("Couldn't find recording for chanid %1 @ %2")
                .arg(chanid).arg(starttime);
            cerr << msg.toLocal8Bit().constData() << endl;
            delete pginfo;
            return GENERIC_EXIT_NO_RECORDING_DATA;
        }

        infile = pginfo->GetPlaybackURL(false, true);
    }
    else
    {
        pginfo = new ProgramInfo(infile);
        if (!pginfo->GetChanID())
        {
            VERBOSE(VB_IMPORTANT,
                    QString("Couldn't find a recording for filename '%1'")
                    .arg(infile));
            delete pginfo;
            pginfo = NULL;
        }
    }

    if (infile.left(7) == "myth://" && (outfile.isNull() || outfile != "-"))
    {
        VERBOSE(VB_IMPORTANT, QString("Attempted to transcode %1. "
               "Mythtranscode is currently unable to transcode remote "
               "files.")
               .arg(infile));
        return GENERIC_EXIT_REMOTE_FILE;
    }

    if (outfile.isNull() && !build_index)
        outfile = infile + ".tmp";

    if (jobID >= 0)
        JobQueue::ChangeJobStatus(jobID, JOB_RUNNING);

    Transcode *transcode = new Transcode(pginfo);

    if (!build_index)
        VERBOSE(VB_GENERAL, QString("Transcoding from %1 to %2")
                            .arg(infile).arg(outfile));

    if (showprogress)
        transcode->ShowProgress(true);
    if (!recorderOptions.isEmpty())
        transcode->SetRecorderOptions(recorderOptions);
    int result = 0;
    if (!mpeg2 && !build_index)
    {
        result = transcode->TranscodeFile(infile, outfile,
                                          profilename, useCutlist,
                                          (fifosync || keyframesonly), jobID,
                                          fifodir, deleteMap, AudioTrackNo,
                                          passthru);
        if ((result == REENCODE_OK) && (jobID >= 0))
            JobQueue::ChangeJobArgs(jobID, "RENAME_TO_NUV");
    }

    int exitcode = GENERIC_EXIT_OK;
    if ((result == REENCODE_MPEG2TRANS) || mpeg2 || build_index)
    {
        void (*update_func)(float) = NULL;
        int (*check_func)() = NULL;
        if (useCutlist && !found_infile)
            pginfo->QueryCutList(deleteMap);
        if (jobID >= 0)
        {
           glbl_jobID = jobID;
           update_func = &UpdateJobQueue;
           check_func = &CheckJobQueue;
        }

        MPEG2fixup *m2f = new MPEG2fixup(
            infile, outfile,
            &deleteMap, NULL, false, false, 20,
            showprogress, otype, update_func,
            check_func);

        if (build_index)
        {
            int err = BuildKeyframeIndex(m2f, infile, posMap, jobID);
            if (err)
                return err;
            if (update_index)
                UpdatePositionMap(posMap, NULL, pginfo);
            else
                UpdatePositionMap(posMap, outfile + QString(".map"), pginfo);
        }
        else
        {
            result = m2f->Start();
            if (result == REENCODE_OK)
            {
                result = BuildKeyframeIndex(m2f, outfile, posMap, jobID);
                if (result == REENCODE_OK)
                {
                    if (update_index)
                        UpdatePositionMap(posMap, NULL, pginfo);
                    else
                        UpdatePositionMap(posMap, outfile + QString(".map"),
                                          pginfo);
                }
            }
        }
        delete m2f;
    }

    if (result == REENCODE_OK)
    {
        if (jobID >= 0)
            JobQueue::ChangeJobStatus(jobID, JOB_STOPPING);
        VERBOSE(VB_GENERAL, QString("%1 %2 done")
                .arg(build_index ? "Building Index for" : "Transcoding")
                .arg(infile));
    }
    else if (result == REENCODE_CUTLIST_CHANGE)
    {
        if (jobID >= 0)
            JobQueue::ChangeJobStatus(jobID, JOB_RETRY);
        VERBOSE(VB_GENERAL, QString("Transcoding %1 aborted because of "
                                    "cutlist update").arg(infile));
        exitcode = GENERIC_EXIT_RESTART;
    }
    else if (result == REENCODE_STOPPED)
    {
        if (jobID >= 0)
            JobQueue::ChangeJobStatus(jobID, JOB_ABORTING);
        VERBOSE(VB_GENERAL, QString("Transcoding %1 stopped because of "
                                    "stop command").arg(infile));
        exitcode = GENERIC_EXIT_KILLED;
    }
    else
    {
        if (jobID >= 0)
            JobQueue::ChangeJobStatus(jobID, JOB_ERRORING);
        VERBOSE(VB_GENERAL, QString("Transcoding %1 failed").arg(infile));
        exitcode = result;
    }

    if (jobID >= 0)
        CompleteJob(jobID, pginfo, useCutlist, &deleteMap, exitcode);

    transcode->deleteLater();

    delete gContext;
    return exitcode;
}
Example #26
0
int preview_helper(const QString &_chanid, const QString &starttime,
                   long long previewFrameNumber, long long previewSeconds,
                   const QSize &previewSize,
                   const QString &infile, const QString &outfile)
{
    // Lower scheduling priority, to avoid problems with recordings.
    if (setpriority(PRIO_PROCESS, 0, 9))
        VERBOSE(VB_GENERAL, "Setting priority failed." + ENO);

    uint chanid = _chanid.toUInt();
    QDateTime recstartts = myth_dt_from_string(starttime);
    if (!chanid || !recstartts.isValid())
        ProgramInfo::ExtractKeyFromPathname(infile, chanid, recstartts);

    ProgramInfo *pginfo = NULL;
    if (chanid && recstartts.isValid())
    {
        pginfo = new ProgramInfo(chanid, recstartts);
        if (!pginfo->GetChanID())
        {
            VERBOSE(VB_IMPORTANT, QString(
                        "Cannot locate recording made on '%1' at '%2'")
                    .arg(chanid).arg(starttime));
            delete pginfo;
            return PREVIEWGEN_EXIT_NOT_OK;
        }
        pginfo->SetPathname(pginfo->GetPlaybackURL(false, true));
    }
    else if (!infile.isEmpty())
    {
        if (!QFileInfo(infile).isReadable())
        {
            VERBOSE(VB_IMPORTANT, QString(
                        "Cannot read this file '%1'").arg(infile));
            return PREVIEWGEN_EXIT_NOT_OK;
        }
        pginfo = new ProgramInfo(
            infile, ""/*plot*/, ""/*title*/, ""/*subtitle*/, ""/*director*/,
            0/*season*/, 0/*episode*/, 120/*length_in_minutes*/,
            1895/*year*/);
    }
    else
    {
        VERBOSE(VB_IMPORTANT, "Cannot locate recording to preview");
        return PREVIEWGEN_EXIT_NOT_OK;
    }

    PreviewGenerator *previewgen = new PreviewGenerator(
        pginfo, QString(), PreviewGenerator::kLocal);

    if (previewFrameNumber >= 0)
        previewgen->SetPreviewTimeAsFrameNumber(previewFrameNumber);

    if (previewSeconds >= 0)
        previewgen->SetPreviewTimeAsSeconds(previewSeconds);

    previewgen->SetOutputSize(previewSize);
    previewgen->SetOutputFilename(outfile);
    bool ok = previewgen->RunReal();
    previewgen->deleteLater();

    delete pginfo;

    return (ok) ? PREVIEWGEN_EXIT_OK : PREVIEWGEN_EXIT_NOT_OK;
}