예제 #1
0
void ExportNative::runScript()
{
    QString tempDir = getTempDirectory();
    QString logDir = tempDir + "logs";
    QString configDir = tempDir + "config";
    QString commandline;

    // remove existing progress.log if present
    if (QFile::exists(logDir + "/progress.log"))
        QFile::remove(logDir + "/progress.log");

    // remove cancel flag file if present
    if (QFile::exists(logDir + "/mythburncancel.lck"))
        QFile::remove(logDir + "/mythburncancel.lck");

    createConfigFile(configDir + "/mydata.xml");
    commandline = "mytharchivehelper --nativearchive --outfile " + configDir + 
                  "/mydata.xml";  // job file
    commandline += logPropagateArgs;
    if (!logPropagateQuiet())
        commandline += " --quiet";
    commandline += " > "  + logDir + "/progress.log 2>&1 &";            // Logs

    uint flags = kMSRunBackground | kMSDontBlockInputDevs | 
                 kMSDontDisableDrawing;
    uint retval = myth_system(commandline, flags);
    if (retval != GENERIC_EXIT_RUNNING && retval != GENERIC_EXIT_OK)
    {
        ShowOkPopup(QObject::tr("It was not possible to create the DVD. "
                                "An error occured when running the scripts") );
        return;
    }

    showLogViewer();
}
예제 #2
0
QString ThumbFinder::createThumbDir(void)
{
    QString thumbDir = getTempDirectory() + "config/thumbs";

    // make sure the thumb directory exists
    QDir dir(thumbDir);
    if (!dir.exists())
    {
        dir.mkdir(thumbDir);
        if( chmod(qPrintable(thumbDir), 0777) )
            LOG(VB_GENERAL, LOG_ERR, "ThumbFinder: Failed to change permissions"
                                     " on thumb directory: " + ENO);
    }

    QString path;
    for (int x = 1; dir.exists(); x++)
    {
        path = thumbDir + QString("/%1").arg(x);
        dir.setPath(path);
    }

    dir.mkdir(path);
    if( chmod(qPrintable(path), 0777) )
        LOG(VB_GENERAL, LOG_ERR, "ThumbFinder: Failed to change permissions on "
                                 "thumb directory: %1" + ENO);

    return path;
}
예제 #3
0
QString ThumbFinder::createThumbDir(void)
{
    QString thumbDir = getTempDirectory() + "config/thumbs";

    // make sure the thumb directory exists
    QDir dir(thumbDir);
    if (!dir.exists())
    {
        dir.mkdir(thumbDir);
        if( !chmod(qPrintable(thumbDir), 0777) )
            VERBOSE(VB_IMPORTANT, QString("ThumbFinder: Failed to change permissions on thumb directory: %1")
                    .arg(strerror(errno)));
    }

    int x = 0;
    QString path;
    do
    {
        x++;
        path = QString(thumbDir + "/%1").arg(x);
        dir.setPath(path);
    } while (dir.exists());

    dir.mkdir(path);
    if( !chmod(qPrintable(path), 0777) )
        VERBOSE(VB_IMPORTANT, QString("ThumbFinder: Failed to change permissions on thumb directory: %1")
                .arg(strerror(errno)));

    return path;
}
예제 #4
0
void ExportNative::runScript()
{
    QString tempDir = getTempDirectory();
    QString logDir = tempDir + "logs";
    QString configDir = tempDir + "config";
    QString commandline;

    // remove existing progress.log if present
    if (QFile::exists(logDir + "/progress.log"))
        QFile::remove(logDir + "/progress.log");

    // remove cancel flag file if present
    if (QFile::exists(logDir + "/mythburncancel.lck"))
        QFile::remove(logDir + "/mythburncancel.lck");

    createConfigFile(configDir + "/mydata.xml");
    commandline = "mytharchivehelper -n " + configDir + "/mydata.xml";  // job file
    commandline += " > "  + logDir + "/progress.log 2>&1 &";            // Logs

    int state = system(qPrintable(commandline));

    if (state != 0)
    {
        ShowOkPopup(QObject::tr("It was not possible to create the DVD. "
                                "An error occured when running the scripts") );
    }
    else
    {
        showLogViewer();
    }
}
예제 #5
0
파일: logviewer.cpp 프로젝트: MythTV/mythtv
void showLogViewer(void)
{
    MythScreenStack *mainStack = GetMythMainWindow()->GetMainStack();
    QString logDir = getTempDirectory() + "logs";
    QString progressLog;
    QString fullLog;

    // wait for a log file to be available
    int tries = 10;
    while (tries--)
    {
        if (QFile::exists(logDir + "/progress.log"))
            progressLog = logDir + "/progress.log";

        if (QFile::exists(logDir + "/mythburn.log"))
            fullLog = logDir + "/mythburn.log";

        // we wait for both the progress.log and mythburn.log
        if ((!progressLog.isEmpty()) && (!fullLog.isEmpty()))
            break;

        // or we wait for a log from mytharchivehelper
        if (progressLog.isEmpty() && fullLog.isEmpty())
        {
            QStringList logFiles;
            QStringList filters;
            filters << "*.log";

            QDir d(logDir);
            logFiles = d.entryList(filters, QDir::Files | QDir::Readable, QDir::Time);

            if (logFiles.count())
            {
                // the first log file should be the newest one available
                progressLog = logDir + '/' + logFiles[0];
                break;
            }
        }

        sleep(1);
    }

    // do any logs exist?
    if ((!progressLog.isEmpty()) || (!fullLog.isEmpty()))
    {
        LogViewer *viewer = new LogViewer(mainStack);
        viewer->setFilenames(progressLog, fullLog);
        if (viewer->Create())
            mainStack->AddScreen(viewer);
    }
    else
        showWarningDialog(QCoreApplication::translate("LogViewer",
            "Cannot find any logs to show!"));
}
예제 #6
0
void showLogViewer(void)
{
    MythScreenStack *mainStack = GetMythMainWindow()->GetMainStack();
    QString logDir = getTempDirectory() + "logs";

    // do any logs exist?
    if (QFile::exists(logDir + "/progress.log") || QFile::exists(logDir + "/mythburn.log"))
    {
        LogViewer *viewer = new LogViewer(mainStack);
        viewer->setFilenames(logDir + "/progress.log", logDir + "/mythburn.log");
        if (viewer->Create())
            mainStack->AddScreen(viewer);
    }
    else
        showWarningDialog(QObject::tr("Cannot find any logs to show!"));
}
예제 #7
0
void iurlstream::open(std::string url) {
    if (url.empty()) {
        url = m_url;
    }
    
    // download the entire URL to a temp file, put into stringbuf for reading
    std::string tempDir = getTempDirectory();
    std::string filename = getUrlFilename(url);
    m_tempFilePath = tempDir + getDirectoryPathSeparator() + filename;
    
    m_lastError = pp->url_download(url, filename);
    
    if (m_lastError == ERR_MALFORMED_URL) {
        error("iurlstream::open: malformed URL when downloading " + url + " to " + m_tempFilePath);
    } else if (m_lastError == ERR_IO_EXCEPTION) {
        error("iurlstream::open: network I/O error when downloading " + url + " to " + m_tempFilePath);
    }
    if (m_lastError == 200) {
        std::ifstream::open(m_tempFilePath.c_str());
    } else {
        setstate(std::ios::failbit);
    }
}
예제 #8
0
void ImportFile::OKPressed()
{
    QString configFile = getTempDirectory() + "config/importjob.xml";

    createConfigFile(configFile);

    QString commandline;
    QString tempDir = gCoreContext->GetSetting("MythArchiveTempDir", "");

    if (tempDir == "")
        return;

    if (!tempDir.endsWith("/"))
        tempDir += "/";

    QString logDir = tempDir + "logs";

    // remove any existing logs
    myth_system("rm -f " + logDir + "/*.log");

    commandline = "mytharchivehelper -v none,jobqueue --logpath " + logDir + " --importfile "
                  "--infile \"" + configFile + "\"";
    uint flags = kMSRunBackground | kMSDontBlockInputDevs |
                 kMSDontDisableDrawing;
    uint retval = myth_system(commandline, flags);
    if (retval != GENERIC_EXIT_RUNNING && retval != GENERIC_EXIT_OK)
    {
        ShowOkPopup(tr("It was not possible to import the file. "
                       " An error occured when running 'mytharchivehelper'") );
        return;
    }

    showLogViewer();

    Close();
}
예제 #9
0
bool ThumbFinder::initAVCodec(const QString &inFile)
{
    // Open recording
    LOG(VB_JOBQUEUE, LOG_INFO, QString("ThumbFinder: Opening '%1'")
            .arg(inFile));

    if (!m_inputFC.Open(inFile))
    {
        LOG(VB_GENERAL, LOG_ERR, "ThumbFinder, Couldn't open input file" + ENO);
        return false;
    }

    // Getting stream information
    int ret = avformat_find_stream_info(m_inputFC, nullptr);
    if (ret < 0)
    {
        LOG(VB_GENERAL, LOG_ERR,
            QString("Couldn't get stream info, error #%1").arg(ret));
        return false;
    }

    av_dump_format(m_inputFC, 0, qPrintable(inFile), 0);

    // find the first video stream
    m_videostream = -1;

    for (uint i = 0; i < m_inputFC->nb_streams; i++)
    {
        AVStream *st = m_inputFC->streams[i];
        if (m_inputFC->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
        {
            m_startTime = -1;
            if (m_inputFC->streams[i]->start_time != (int) AV_NOPTS_VALUE)
                m_startTime = m_inputFC->streams[i]->start_time;
            else
            {
                LOG(VB_GENERAL, LOG_ERR,
                    "ThumbFinder: Failed to get start time");
                return false;
            }

            m_videostream = i;
            m_frameWidth = st->codecpar->width;
            m_frameHeight = st->codecpar->height;
            if (st->r_frame_rate.den && st->r_frame_rate.num)
                m_fps = av_q2d(st->r_frame_rate);
            else
                m_fps = 1/av_q2d(st->time_base);
            break;
        }
    }

    if (m_videostream == -1)
    {
        LOG(VB_GENERAL, LOG_ERR, "Couldn't find a video stream");
        return false;
    }

    // get the codec context for the video stream
    m_codecCtx = gCodecMap->getCodecContext
        (m_inputFC->streams[m_videostream]);
    m_codecCtx->debug_mv = 0;
    m_codecCtx->debug = 0;
    m_codecCtx->workaround_bugs = 1;
    m_codecCtx->lowres = 0;
    m_codecCtx->idct_algo = FF_IDCT_AUTO;
    m_codecCtx->skip_frame = AVDISCARD_DEFAULT;
    m_codecCtx->skip_idct = AVDISCARD_DEFAULT;
    m_codecCtx->skip_loop_filter = AVDISCARD_DEFAULT;
    m_codecCtx->err_recognition = AV_EF_CAREFUL;
    m_codecCtx->error_concealment = 3;

    // get decoder for video stream
    m_codec = avcodec_find_decoder(m_codecCtx->codec_id);

    if (m_codec == nullptr)
    {
        LOG(VB_GENERAL, LOG_ERR,
            "ThumbFinder: Couldn't find codec for video stream");
        return false;
    }

    // open codec
    if (avcodec_open2(m_codecCtx, m_codec, nullptr) < 0)
    {
        LOG(VB_GENERAL, LOG_ERR,
            "ThumbFinder: Couldn't open codec for video stream");
        return false;
    }

    // allocate temp buffer
    int bufflen = m_frameWidth * m_frameHeight * 4;
    m_outputbuf = new unsigned char[bufflen];

    m_frameFile = getTempDirectory() + "work/frame.jpg";

    m_deinterlacer.reset(new MythPictureDeinterlacer(m_codecCtx->pix_fmt,
                                                     m_frameWidth, m_frameHeight));
    return true;
}
예제 #10
0
bool ThumbFinder::initAVCodec(const QString &inFile)
{
    av_register_all();

    m_inputFC = NULL;

    // Open recording
    VERBOSE(VB_JOBQUEUE, QString("ThumbFinder: ") +
            QString("Opening '%1'").arg(inFile));

    QByteArray inFileBA = inFile.toLocal8Bit();

    int ret = av_open_input_file(
                  &m_inputFC, inFileBA.constData(), NULL, 0, NULL);

    if (ret)
    {
        VERBOSE(VB_IMPORTANT, QString("ThumbFinder, Error: ") +
                "Couldn't open input file" + ENO);
        return false;
    }

    // Getting stream information
    if ((ret = av_find_stream_info(m_inputFC)) < 0)
    {
        VERBOSE(VB_IMPORTANT,
                QString("Couldn't get stream info, error #%1").arg(ret));
        av_close_input_file(m_inputFC);
        m_inputFC = NULL;
        return false;
    }
    av_estimate_timings(m_inputFC, 0);
    dump_format(m_inputFC, 0, inFileBA.constData(), 0);

    // find the first video stream
    m_videostream = -1;

    for (uint i = 0; i < m_inputFC->nb_streams; i++)
    {
        AVStream *st = m_inputFC->streams[i];
        if (m_inputFC->streams[i]->codec->codec_type == CODEC_TYPE_VIDEO)
        {
            m_startTime = -1;
            if (m_inputFC->streams[i]->start_time != (int) AV_NOPTS_VALUE)
                m_startTime = m_inputFC->streams[i]->start_time;
            else
            {
                VERBOSE(VB_IMPORTANT, "ThumbFinder: Failed to get start time");
                return false;
            }

            m_videostream = i;
            m_frameWidth = st->codec->width;
            m_frameHeight = st->codec->height;
            if (st->r_frame_rate.den && st->r_frame_rate.num)
                m_fps = av_q2d(st->r_frame_rate);
            else
                m_fps = 1/av_q2d(st->time_base);
            break;
        }
    }

    if (m_videostream == -1)
    {
        VERBOSE(VB_IMPORTANT, "Couldn't find a video stream");
        return false;
    }

    // get the codec context for the video stream
    m_codecCtx = m_inputFC->streams[m_videostream]->codec;
    m_codecCtx->debug_mv = 0;
    m_codecCtx->debug = 0;
    m_codecCtx->workaround_bugs = 1;
    m_codecCtx->lowres = 0;
    m_codecCtx->idct_algo = FF_IDCT_AUTO;
    m_codecCtx->skip_frame = AVDISCARD_DEFAULT;
    m_codecCtx->skip_idct = AVDISCARD_DEFAULT;
    m_codecCtx->skip_loop_filter = AVDISCARD_DEFAULT;
    m_codecCtx->error_recognition = FF_ER_CAREFUL;
    m_codecCtx->error_concealment = 3;

    // get decoder for video stream
    m_codec = avcodec_find_decoder(m_codecCtx->codec_id);

    if (m_codec == NULL)
    {
        VERBOSE(VB_IMPORTANT, "ThumbFinder: Couldn't find codec for video stream");
        return false;
    }

    // open codec
    if (avcodec_open(m_codecCtx, m_codec) < 0)
    {
        VERBOSE(VB_IMPORTANT, "ThumbFinder: Couldn't open codec for video stream");
        return false;
    }

    // allocate temp buffer
    int bufflen = m_frameWidth * m_frameHeight * 4;
    m_outputbuf = new unsigned char[bufflen];

    m_frame = avcodec_alloc_frame();

    m_frameFile = getTempDirectory() + "work/frame.jpg";

    return true;
}
예제 #11
0
void ImportFile::doGetRecording(void)
{
    MythUIButtonListItem *item = m_recordingButtonList->GetItemCurrent();

    if (!item)
        return;

    ImportItem *i = item->GetData().value<ImportItem *>();

    if (!i)
        return;

    uint duration = 60; //i->actualDuration;
    QString videoFile = getTempDirectory() + "work/video.ts";
    QString mxmlFile = getTempDirectory() + "work/video.mxml";

    // record the mp4 video stream
    QString recCommand = QString("mythffmpeg -y -i %1 -t %2 -acodec copy -vcodec copy %3")
                                 .arg(STREAMURL).arg(duration).arg(videoFile);

    QScopedPointer<MythSystem> cmd(MythSystem::Create(recCommand, kMSRunShell));
    cmd->Wait(0);
    if (cmd.data()->GetExitCode() != GENERIC_EXIT_OK)
    {
        LOG(VB_GENERAL, LOG_ERR, QString("ERROR - ffmpeg exited with result: %1").arg(cmd.data()->GetExitCode()));
        return;
    }

    // create a mxml file with the metadata for this recording
    QStringList categories(i->category.split(','));
    MetadataLookup *lookup = new MetadataLookup(kMetadataVideo, kProbableTelevision, QVariant(), kLookupSearch, false, false, false, false, false,
                                                "", videoFile, i->title, categories, 0.0, i->subtitle, "", i->description, i->season, i->episode,
                                                i->startTime, 0,  i->chanNo, i->chanSign, i->chanName,
                                                i->certification, i->startTime.date().year(), i->startTime.date(), i->duration / 60, i->duration, 
                                                "", PeopleMap(), "", ArtworkMap(), DownloadMap());
    if (i->category == "Movies")
        lookup->SetVideoContentType(kContentMovie);
    else
        lookup->SetVideoContentType(kContentTelevision);

    QDomDocument mxmlDoc = CreateMetadataXML(lookup);

    // save the mxml to the file
    QFile f(mxmlFile);
    if (!f.open(QIODevice::WriteOnly))
    {
        LOG(VB_GENERAL, LOG_ERR, QString("ImportFile: Failed to open mxml file for writing - %1").arg(mxmlFile));
        return;
    }

    QTextStream t(&f);
    t << mxmlDoc.toString(4);
    f.close();

    // workout where to save the file in the Video storage group
    QString dstFile = filenameFromMetadataLookup(lookup);

    QString saveFilename;

    // copy the recording to the Video storage group
    saveFilename = gCoreContext->GenMythURL(gCoreContext->GetMasterHostName(), 0, dstFile + ".mp4", "Videos");

    bool result = RemoteFile::CopyFile(videoFile, saveFilename);
    if (!result)
    {
        LOG(VB_GENERAL, LOG_ERR, QString("ImportFile: Failed to copy video file to %1").arg(saveFilename));
        return;
    }

    // copy the metadata xml file to the Video storage group
    saveFilename = gCoreContext->GenMythURL(gCoreContext->GetMasterHostName(), 0, dstFile + ".mxml", "Videos");

    result = RemoteFile::CopyFile(mxmlFile, saveFilename);
    if (!result)
    {
        LOG(VB_GENERAL, LOG_ERR, QString("ImportFile: Failed to copy xml file to %1").arg(saveFilename));
        return;
    }
}
예제 #12
0
void ImportFile::getRecordingList(void)
{
    while (!m_recordingList.isEmpty())
        delete m_recordingList.takeFirst();

    QString xmlFile = getTempDirectory() + "work/recordings.xml";
    QFileInfo fi(xmlFile);

    if (!fi.exists() || QDateTime::currentDateTime() > fi.lastModified().addSecs(3600))
    {
        // run the script to get list of recordings from the External Box
        QString command = gCoreContext->GetSetting("MythArchiveGetRecordingList");
        command.replace("%XMLFILE%", xmlFile);

        QScopedPointer<MythSystem> cmd(MythSystem::Create(command));
        cmd->Wait(0);
        if (cmd.data()->GetExitCode() != GENERIC_EXIT_OK)
        {
            LOG(VB_GENERAL, LOG_ERR, QString("ERROR - Failed to get recording list"));
            LOG(VB_GENERAL, LOG_ERR, QString("Command exited with result: %1").arg(cmd.data()->GetExitCode()));
            LOG(VB_GENERAL, LOG_ERR, QString("Command was: %1").arg(command));
            //return;
        }
    }

    // load the xml file contains the recordings list details
    QDomDocument doc("recordings");
    QFile file(xmlFile);
    if (!file.open(QIODevice::ReadOnly))
    {
        LOG(VB_GENERAL, LOG_ERR, "Could not open recordings file: " + xmlFile);
        return;
    }

    if (!doc.setContent(&file))
    {
        LOG(VB_GENERAL, LOG_ERR, "Could not load recordings file: " + xmlFile);
        file.close();
        return;
    }

    file.close();

    QDomNodeList recordingNodes = doc.elementsByTagName("recording");
    for (int x = 0; x < recordingNodes.count(); x++)
    {
        ImportItem *importItem = new ImportItem;
        QDomNode recordingNode = recordingNodes.item(x);
        QDomElement recordingElement = recordingNode.toElement();
        for (int y = 0; y < recordingElement.childNodes().count(); y++)
        {
            QDomNode node = recordingElement.childNodes().at(y);
            QDomElement e = node.toElement();
            if (e.nodeName() == "no")
                importItem->id = getFirstText(e).toInt();
            else if (e.nodeName() == "title")
                importItem->title = decodeXML(getFirstText(e));
            else if (e.nodeName() == "season")
                importItem->season = decodeXML(getFirstText(e)).toUInt();
            else if (e.nodeName() == "episode")
                importItem->episode = decodeXML(getFirstText(e)).toUInt();
            else if (e.nodeName() == "channelno")
                importItem->chanNo = decodeXML(getFirstText(e));
            else if (e.nodeName() == "channelsign")
                importItem->chanSign = decodeXML(getFirstText(e));
            else if (e.nodeName() == "channelname")
                importItem->chanName = decodeXML(getFirstText(e));
            else if (e.nodeName() == "starttime")
                importItem->startTime = MythDate::fromString(getFirstText(e));
            else if (e.nodeName() == "duration")
                importItem->duration = decodeDuration(getFirstText(e));
            else if (e.nodeName() == "actualduration")
                importItem->actualDuration = decodeDuration(getFirstText(e));
            else if (e.nodeName() == "description")
                importItem->description = decodeXML(getFirstText(e)) + QString("\n\nRecorded from %1 on %2 at %3.")
                    .arg(importItem->chanName).arg(importItem->startTime.toString("dddd dd MMMM yyyy"))
                    .arg(importItem->startTime.toString("hh:mm ap"));
            else if (e.nodeName() == "filesize")
                importItem->size = getFirstText(e).toInt();
            else if (e.nodeName() == "filename")
                importItem->filename = getFirstText(e);
            else if (e.nodeName() == "category")
                importItem->category = getFirstText(e);
        }

        if (importItem->chanSign.isEmpty())
            importItem->chanSign = importItem->chanName;

        if (importItem->category.isEmpty())
            importItem->category = importItem->title;

        if (m_categories.indexOf(importItem->category) == -1)
            m_categories.append(importItem->category);

        // default to using the IPEncoder
        importItem->type = "IPEncoder";

        m_recordingList.append(importItem);
    }
}