Example #1
0
void PreviewGeneratorQueue::GetPreviewImage(
    const ProgramInfo &pginfo,
    const QSize &outputsize,
    const QString &outputfile,
    long long time, bool in_seconds,
    QString token)
{
    if (!s_pgq)
        return;

    if (pginfo.GetPathname().isEmpty() ||
        pginfo.GetBasename() == pginfo.GetPathname())
    {
        return;
    }

    QStringList extra;
    pginfo.ToStringList(extra);
    extra += token;
    extra += QString::number(outputsize.width());
    extra += QString::number(outputsize.height());
    extra += outputfile;
    extra += QString::number(time);
    extra += (in_seconds ? "1" : "0");
    MythEvent *e = new MythEvent("GET_PREVIEW", extra);
    QCoreApplication::postEvent(s_pgq, e);
}
Example #2
0
void RecordingSelector::titleChanged(MythUIButtonListItem *item)
{
    ProgramInfo *p;

    p = qVariantValue<ProgramInfo *>(item->GetData());

    if (!p)
        return;

    if (m_titleText)
        m_titleText->SetText(p->GetTitle());

    if (m_datetimeText)
        m_datetimeText->SetText(p->GetScheduledStartTime()
                                .toString("dd MMM yy (hh:mm)"));

    if (m_descriptionText)
    {
        m_descriptionText->SetText(
            ((!p->GetSubtitle().isEmpty()) ? p->GetSubtitle() + "\n" : "") +
            p->GetDescription());
    }

    if (m_filesizeText)
    {
        m_filesizeText->SetText(formatSize(p->GetFilesize() / 1024));
    }

    if (m_cutlistImage)
    {
        if (p->HasCutlist())
            m_cutlistImage->Show();
        else
            m_cutlistImage->Hide();
    }

    if (m_previewImage)
    {
        // try to locate a preview image
        if (QFile::exists(p->GetPathname() + ".png"))
        {
            m_previewImage->SetFilename(p->GetPathname() + ".png");
            m_previewImage->Load();
        }
        else
        {
            m_previewImage->SetFilename("blank.png");
            m_previewImage->Load();
        }
    }
}
Example #3
0
QString PreviewGeneratorQueue::GeneratePreviewImage(
    ProgramInfo &pginfo,
    const QSize &size,
    const QString &outputfile,
    long long time, bool in_seconds,
    QString token)
{
    QString key = QString("%1_%2x%3_%4%5")
        .arg(pginfo.GetBasename()).arg(size.width()).arg(size.height())
        .arg(time).arg(in_seconds?"s":"f");

    if (pginfo.GetAvailableStatus() == asPendingDelete)
    {
        SendEvent(pginfo, "PREVIEW_FAILED", key, token,
                  "Pending Delete", QDateTime());
        return QString();
    }

    QString filename = (outputfile.isEmpty()) ?
        pginfo.GetPathname() + ".png" : outputfile;
    QString ret_file = filename;
    QString ret;

    bool is_special = !outputfile.isEmpty() || time >= 0 ||
        size.width() || size.height();

    bool needs_gen = true;
    if (!is_special)
    {
        QDateTime previewLastModified;
        bool streaming = filename.left(1) != "/";
        bool locally_accessible = false;
        bool bookmark_updated = false;

        QDateTime bookmark_ts = pginfo.QueryBookmarkTimeStamp();
        QDateTime cmp_ts;
        if (bookmark_ts.isValid())
            cmp_ts = bookmark_ts;
        else if (MythDate::current() >= pginfo.GetRecordingEndTime())
            cmp_ts = pginfo.GetLastModifiedTime();
        else
            cmp_ts = pginfo.GetRecordingStartTime();

        if (streaming)
        {
            ret_file = QString("%1/remotecache/%2")
                .arg(GetConfDir()).arg(filename.section('/', -1));

            QFileInfo finfo(ret_file);
            if (finfo.isReadable() && finfo.lastModified() >= cmp_ts)
            {
                // This is just an optimization to avoid
                // hitting the backend if our cached copy
                // is newer than the bookmark, or if we have
                // a preview and do not update it when the
                // bookmark changes.
                previewLastModified = finfo.lastModified();
            }
            else if (!IsGeneratingPreview(key))
            {
                previewLastModified =
                    RemoteGetPreviewIfModified(pginfo, ret_file);
            }
        }
        else
        {
            QFileInfo fi(filename);
            if ((locally_accessible = fi.isReadable()))
                previewLastModified = fi.lastModified();
        }

        bookmark_updated =
            (!previewLastModified.isValid() || (previewLastModified <= cmp_ts));

        if (bookmark_updated && bookmark_ts.isValid() &&
            previewLastModified.isValid())
        {
            ClearPreviewGeneratorAttempts(key);
        }

        bool preview_exists = previewLastModified.isValid();

        if (0)
        {
            QString alttext = (bookmark_ts.isValid()) ? QString() :
                QString("\n\t\t\tcmp_ts:               %1")
                .arg(cmp_ts.toString(Qt::ISODate));
            LOG(VB_GENERAL, LOG_INFO,
                QString("previewLastModified:  %1\n\t\t\t"
                        "bookmark_ts:          %2%3\n\t\t\t"
                        "pginfo.lastmodified:  %4")
                    .arg(previewLastModified.toString(Qt::ISODate))
                    .arg(bookmark_ts.toString(Qt::ISODate))
                    .arg(alttext)
                    .arg(pginfo.GetLastModifiedTime(MythDate::ISODate)) +
                QString("Title: %1\n\t\t\t")
                    .arg(pginfo.toString(ProgramInfo::kTitleSubtitle)) +
                QString("File  '%1' \n\t\t\tCache '%2'")
                    .arg(filename).arg(ret_file) +
                QString("\n\t\t\tPreview Exists: %1, Bookmark Updated: %2, "
                        "Need Preview: %3")
                    .arg(preview_exists).arg(bookmark_updated)
                    .arg((bookmark_updated || !preview_exists)));
        }

        needs_gen = bookmark_updated || !preview_exists;

        if (!needs_gen)
        {
            if (locally_accessible)
                ret = filename;
            else if (preview_exists && QFileInfo(ret_file).isReadable())
                ret = ret_file;
        }
    }

    if (needs_gen && !IsGeneratingPreview(key))
    {
        uint attempts = IncPreviewGeneratorAttempts(key);
        if (attempts < m_maxAttempts)
        {
            LOG(VB_PLAYBACK, LOG_INFO, LOC +
                QString("Requesting preview for '%1'") .arg(key));
            PreviewGenerator *pg = new PreviewGenerator(&pginfo, token, m_mode);
            if (!outputfile.isEmpty() || time >= 0 ||
                size.width() || size.height())
            {
                pg->SetPreviewTime(time, in_seconds);
                pg->SetOutputFilename(outputfile);
                pg->SetOutputSize(size);
            }

            SetPreviewGenerator(key, pg);

            LOG(VB_PLAYBACK, LOG_INFO, LOC +
                QString("Requested preview for '%1'").arg(key));
        }
        else if (attempts >= m_maxAttempts)
        {
            LOG(VB_GENERAL, LOG_ERR, LOC +
                QString("Attempted to generate preview for '%1' "
                        "%2 times; >= max(%3)")
                    .arg(key).arg(attempts).arg(m_maxAttempts));
        }
    }
    else if (needs_gen)
    {
        LOG(VB_PLAYBACK, LOG_INFO, LOC +
            QString("Not requesting preview for %1,"
                    "as it is already being generated")
                .arg(pginfo.toString(ProgramInfo::kTitleSubtitle)));
        IncPreviewGeneratorPriority(key, token);
    }

    UpdatePreviewGeneratorThreads();

    if (!ret.isEmpty())
    {
        QString msg = "On Disk";
        QDateTime dt = QFileInfo(ret).lastModified();
        SendEvent(pginfo, "PREVIEW_SUCCESS", ret, token, msg, dt);
    }
    else
    {
        uint queue_depth, token_cnt;
        GetInfo(key, queue_depth, token_cnt);
        QString msg = QString("Queue depth %1, our tokens %2")
            .arg(queue_depth).arg(token_cnt);
        SendEvent(pginfo, "PREVIEW_QUEUED", ret, token, msg, QDateTime());
    }

    return ret;
}
Example #4
0
static int internal_play_media(const QString &mrl, const QString &plot,
                        const QString &title, const QString &subtitle,
                        const QString &director, int season, int episode,
                        int lenMins, const QString &year)
{
    int res = -1;

    QFile checkFile(mrl);
    if ((!checkFile.exists() && !mrl.startsWith("dvd:")
         && !mrl.startsWith("bd:")
         && !mrl.startsWith("myth:")))
    {
        QString errorText = QObject::tr("Failed to open \n '%1' in %2 \n"
                                        "Check if the video exists")
                                        .arg(mrl.section('/', -1))
                                        .arg(mrl.section('/', 0, -2));
        ShowOkPopup(errorText);
        return res;
    }

    ProgramInfo *pginfo = new ProgramInfo(
        mrl, plot, title, subtitle, director, season, episode,
        lenMins, (year.toUInt()) ? year.toUInt() : 1900);

    int64_t pos = 0;

    if (pginfo->IsVideoDVD())
    {
        RingBuffer *tmprbuf = RingBuffer::Create(pginfo->GetPathname(), false);

        if (!tmprbuf)
        {
            delete pginfo;
            return res;
        }
        QString name;
        QString serialid;
        if (tmprbuf->IsDVD() &&
            tmprbuf->DVD()->GetNameAndSerialNum(name, serialid))
        {
            QStringList fields = pginfo->QueryDVDBookmark(serialid);
            if (!fields.empty())
            {
                QStringList::Iterator it = fields.begin();
                pos = (int64_t)((*++it).toLongLong() & 0xffffffffLL);
            }
        }
        delete tmprbuf;
    }
    else if (pginfo->IsVideo())
        pos = pginfo->QueryBookmark();

    if (pos > 0)
    {
        MythScreenStack *mainStack = GetMythMainWindow()->GetMainStack();
        BookmarkDialog *bookmarkdialog = new BookmarkDialog(pginfo, mainStack);
        if (!bookmarkdialog->Create())
        {
            delete bookmarkdialog;
            delete pginfo;
            return res;
        }
    }
    else
    {
        TV::StartTV(pginfo, kStartTVNoFlags);

        res = 0;

        delete pginfo;
    }

    return res;
}
Example #5
0
static int RunCCExtract(const ProgramInfo &program_info)
{
    QString filename = program_info.GetPlaybackURL();
    if (filename.startsWith("myth://"))
    {
        QString msg =
            QString("Only locally accessible files are supported (%1).")
            .arg(program_info.GetPathname());
        cerr << qPrintable(msg) << endl;
        return GENERIC_EXIT_INVALID_CMDLINE;
    }

    if (!QFile::exists(filename))
    {
        cerr << qPrintable(
            QString("Could not open input file (%1).").arg(filename)) << endl;
        return GENERIC_EXIT_INVALID_CMDLINE;
    }

    RingBuffer *tmprbuf = RingBuffer::Create(filename, false);
    if (!tmprbuf)
    {
        cerr << qPrintable(QString("Unable to create RingBuffer for %1")
                           .arg(filename)) << endl;
        return GENERIC_EXIT_PERMISSIONS_ERROR;
    }

    if (program_info.GetRecordingEndTime() > MythDate::current())
    {
        cout << "Program will end @ "
             << qPrintable(program_info.GetRecordingEndTime(MythDate::ISODate))
             << endl;
        tmprbuf->SetWaitForWrite();
    }

    PlayerFlags flags = (PlayerFlags)(kVideoIsNull | kAudioMuted  |
                                      kDecodeNoLoopFilter | kDecodeFewBlocks |
                                      kDecodeLowRes | kDecodeSingleThreaded |
                                      kDecodeNoDecode);
    MythCCExtractorPlayer *ccp = new MythCCExtractorPlayer(flags, true, filename);
    PlayerContext *ctx = new PlayerContext(kCCExtractorInUseID);
    ctx->SetPlayingInfo(&program_info);
    ctx->SetRingBuffer(tmprbuf);
    ctx->SetPlayer(ccp);

    ccp->SetPlayerInfo(NULL, NULL, ctx);
    if (ccp->OpenFile() < 0)
    {
        cerr << "Failed to open " << qPrintable(filename) << endl;
        return GENERIC_EXIT_NOT_OK;
    }
    if (!ccp->run())
    {
        cerr << "Failed to decode " << qPrintable(filename) << endl;
        return GENERIC_EXIT_NOT_OK;
    }

    delete ctx;

    return GENERIC_EXIT_OK;
}